[multiple changes]
[platform/upstream/gcc.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-2015, Free Software Foundation, Inc.         --
10 --                                                                          --
11 -- GNAT is free software;  you can  redistribute it  and/or modify it under --
12 -- terms of the  GNU General Public License as published  by the Free Soft- --
13 -- ware  Foundation;  either version 3,  or (at your option) any later ver- --
14 -- sion.  GNAT is distributed in the hope that it will be useful, but WITH- --
15 -- OUT ANY WARRANTY;  without even the  implied warranty of MERCHANTABILITY --
16 -- or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License --
17 -- for  more details.  You should have  received  a copy of the GNU General --
18 -- Public License  distributed with GNAT; see file COPYING3.  If not, go to --
19 -- http://www.gnu.org/licenses for a complete copy of the license.          --
20 --                                                                          --
21 -- GNAT was originally developed  by the GNAT team at  New York University. --
22 -- Extensive contributions were provided by Ada Core Technologies Inc.      --
23 --                                                                          --
24 ------------------------------------------------------------------------------
25
26 with Atree;    use Atree;
27 with Checks;   use Checks;
28 with Einfo;    use Einfo;
29 with Elists;   use Elists;
30 with Errout;   use Errout;
31 with Exp_Ch3;  use Exp_Ch3;
32 with Exp_Ch6;  use Exp_Ch6;
33 with Exp_Ch11; use Exp_Ch11;
34 with Exp_Dbug; use Exp_Dbug;
35 with Exp_Disp; use Exp_Disp;
36 with Exp_Sel;  use Exp_Sel;
37 with Exp_Smem; use Exp_Smem;
38 with Exp_Tss;  use Exp_Tss;
39 with Exp_Util; use Exp_Util;
40 with Freeze;   use Freeze;
41 with Hostparm;
42 with Itypes;   use Itypes;
43 with Namet;    use Namet;
44 with Nlists;   use Nlists;
45 with Nmake;    use Nmake;
46 with Opt;      use Opt;
47 with Restrict; use Restrict;
48 with Rident;   use Rident;
49 with Rtsfind;  use Rtsfind;
50 with Sem;      use Sem;
51 with Sem_Aux;  use Sem_Aux;
52 with Sem_Ch6;  use Sem_Ch6;
53 with Sem_Ch8;  use Sem_Ch8;
54 with Sem_Ch9;  use Sem_Ch9;
55 with Sem_Ch11; use Sem_Ch11;
56 with Sem_Elab; use Sem_Elab;
57 with Sem_Eval; use Sem_Eval;
58 with Sem_Res;  use Sem_Res;
59 with Sem_Util; use Sem_Util;
60 with Sinfo;    use Sinfo;
61 with Snames;   use Snames;
62 with Stand;    use Stand;
63 with Stringt;  use Stringt;
64 with Targparm; use Targparm;
65 with Tbuild;   use Tbuild;
66 with Uintp;    use Uintp;
67
68 package body Exp_Ch9 is
69
70    --  The following constant establishes the upper bound for the index of
71    --  an entry family. It is used to limit the allocated size of protected
72    --  types with defaulted discriminant of an integer type, when the bound
73    --  of some entry family depends on a discriminant. The limitation to entry
74    --  families of 128K should be reasonable in all cases, and is a documented
75    --  implementation restriction.
76
77    Entry_Family_Bound : constant Int := 2**16;
78
79    -----------------------
80    -- Local Subprograms --
81    -----------------------
82
83    function Actual_Index_Expression
84      (Sloc  : Source_Ptr;
85       Ent   : Entity_Id;
86       Index : Node_Id;
87       Tsk   : Entity_Id) return Node_Id;
88    --  Compute the index position for an entry call. Tsk is the target task. If
89    --  the bounds of some entry family depend on discriminants, the expression
90    --  computed by this function uses the discriminants of the target task.
91
92    procedure Add_Object_Pointer
93      (Loc      : Source_Ptr;
94       Conc_Typ : Entity_Id;
95       Decls    : List_Id);
96    --  Prepend an object pointer declaration to the declaration list Decls.
97    --  This object pointer is initialized to a type conversion of the System.
98    --  Address pointer passed to entry barrier functions and entry body
99    --  procedures.
100
101    procedure Add_Formal_Renamings
102      (Spec  : Node_Id;
103       Decls : List_Id;
104       Ent   : Entity_Id;
105       Loc   : Source_Ptr);
106    --  Create renaming declarations for the formals, inside the procedure that
107    --  implements an entry body. The renamings make the original names of the
108    --  formals accessible to gdb, and serve no other purpose.
109    --    Spec is the specification of the procedure being built.
110    --    Decls is the list of declarations to be enhanced.
111    --    Ent is the entity for the original entry body.
112
113    function Build_Accept_Body (Astat : Node_Id) return Node_Id;
114    --  Transform accept statement into a block with added exception handler.
115    --  Used both for simple accept statements and for accept alternatives in
116    --  select statements. Astat is the accept statement.
117
118    function Build_Barrier_Function
119      (N   : Node_Id;
120       Ent : Entity_Id;
121       Pid : Node_Id) return Node_Id;
122    --  Build the function body returning the value of the barrier expression
123    --  for the specified entry body.
124
125    function Build_Barrier_Function_Specification
126      (Loc    : Source_Ptr;
127       Def_Id : Entity_Id) return Node_Id;
128    --  Build a specification for a function implementing the protected entry
129    --  barrier of the specified entry body.
130
131    function Build_Corresponding_Record
132      (N    : Node_Id;
133       Ctyp : Node_Id;
134       Loc  : Source_Ptr) return Node_Id;
135    --  Common to tasks and protected types. Copy discriminant specifications,
136    --  build record declaration. N is the type declaration, Ctyp is the
137    --  concurrent entity (task type or protected type).
138
139    function Build_Dispatching_Tag_Check
140      (K : Entity_Id;
141       N : Node_Id) return Node_Id;
142    --  Utility to create the tree to check whether the dispatching call in
143    --  a timed entry call, a conditional entry call, or an asynchronous
144    --  transfer of control is a call to a primitive of a non-synchronized type.
145    --  K is the temporary that holds the tagged kind of the target object, and
146    --  N is the enclosing construct.
147
148    function Build_Entry_Count_Expression
149      (Concurrent_Type : Node_Id;
150       Component_List  : List_Id;
151       Loc             : Source_Ptr) return Node_Id;
152    --  Compute number of entries for concurrent object. This is a count of
153    --  simple entries, followed by an expression that computes the length
154    --  of the range of each entry family. A single array with that size is
155    --  allocated for each concurrent object of the type.
156
157    function Build_Find_Body_Index (Typ : Entity_Id) return Node_Id;
158    --  Build the function that translates the entry index in the call
159    --  (which depends on the size of entry families) into an index into the
160    --  Entry_Bodies_Array, to determine the body and barrier function used
161    --  in a protected entry call. A pointer to this function appears in every
162    --  protected object.
163
164    function Build_Find_Body_Index_Spec (Typ : Entity_Id) return Node_Id;
165    --  Build subprogram declaration for previous one
166
167    function Build_Lock_Free_Protected_Subprogram_Body
168      (N           : Node_Id;
169       Prot_Typ    : Node_Id;
170       Unprot_Spec : Node_Id) return Node_Id;
171    --  N denotes a subprogram body of protected type Prot_Typ. Unprot_Spec is
172    --  the subprogram specification of the unprotected version of N. Transform
173    --  N such that it invokes the unprotected version of the body.
174
175    function Build_Lock_Free_Unprotected_Subprogram_Body
176      (N        : Node_Id;
177       Prot_Typ : Node_Id) return Node_Id;
178    --  N denotes a subprogram body of protected type Prot_Typ. Build a version
179    --  of N where the original statements of N are synchronized through atomic
180    --  actions such as compare and exchange. Prior to invoking this routine, it
181    --  has been established that N can be implemented in a lock-free fashion.
182
183    function Build_Parameter_Block
184      (Loc     : Source_Ptr;
185       Actuals : List_Id;
186       Formals : List_Id;
187       Decls   : List_Id) return Entity_Id;
188    --  Generate an access type for each actual parameter in the list Actuals.
189    --  Create an encapsulating record that contains all the actuals and return
190    --  its type. Generate:
191    --    type Ann1 is access all <actual1-type>
192    --    ...
193    --    type AnnN is access all <actualN-type>
194    --    type Pnn is record
195    --       <formal1> : Ann1;
196    --       ...
197    --       <formalN> : AnnN;
198    --    end record;
199
200    procedure Build_PPC_Wrapper (E : Entity_Id; Decl : Node_Id);
201    --  Build body of wrapper procedure for an entry or entry family that has
202    --  pre/postconditions. The body gathers the PPC's and expands them in the
203    --  usual way, and performs the entry call itself. This way preconditions
204    --  are evaluated before the call is queued. E is the entry in question,
205    --  and Decl is the enclosing synchronized type declaration at whose freeze
206    --  point the generated body is analyzed.
207
208    function Build_Protected_Entry
209      (N   : Node_Id;
210       Ent : Entity_Id;
211       Pid : Node_Id) return Node_Id;
212    --  Build the procedure implementing the statement sequence of the specified
213    --  entry body.
214
215    function Build_Protected_Entry_Specification
216      (Loc    : Source_Ptr;
217       Def_Id : Entity_Id;
218       Ent_Id : Entity_Id) return Node_Id;
219    --  Build a specification for the procedure implementing the statements of
220    --  the specified entry body. Add attributes associating it with the entry
221    --  defining identifier Ent_Id.
222
223    function Build_Protected_Spec
224      (N           : Node_Id;
225       Obj_Type    : Entity_Id;
226       Ident       : Entity_Id;
227       Unprotected : Boolean := False) return List_Id;
228    --  Utility shared by Build_Protected_Sub_Spec and Expand_Access_Protected_
229    --  Subprogram_Type. Builds signature of protected subprogram, adding the
230    --  formal that corresponds to the object itself. For an access to protected
231    --  subprogram, there is no object type to specify, so the parameter has
232    --  type Address and mode In. An indirect call through such a pointer will
233    --  convert the address to a reference to the actual object. The object is
234    --  a limited record and therefore a by_reference type.
235
236    function Build_Protected_Subprogram_Body
237      (N         : Node_Id;
238       Pid       : Node_Id;
239       N_Op_Spec : Node_Id) return Node_Id;
240    --  This function is used to construct the protected version of a protected
241    --  subprogram. Its statement sequence first defers abort, then locks the
242    --  associated protected object, and then enters a block that contains a
243    --  call to the unprotected version of the subprogram (for details, see
244    --  Build_Unprotected_Subprogram_Body). This block statement requires a
245    --  cleanup handler that unlocks the object in all cases. For details,
246    --  see Exp_Ch7.Expand_Cleanup_Actions.
247
248    function Build_Renamed_Formal_Declaration
249      (New_F          : Entity_Id;
250       Formal         : Entity_Id;
251       Comp           : Entity_Id;
252       Renamed_Formal : Node_Id) return Node_Id;
253    --  Create a renaming declaration for a formal, within a protected entry
254    --  body or an accept body. The renamed object is a component of the
255    --  parameter block that is a parameter in the entry call.
256    --
257    --  In Ada 2012, if the formal is an incomplete tagged type, the renaming
258    --  does not dereference the corresponding component to prevent an illegal
259    --  use of the incomplete type (AI05-0151).
260
261    function Build_Selected_Name
262      (Prefix      : Entity_Id;
263       Selector    : Entity_Id;
264       Append_Char : Character := ' ') return Name_Id;
265    --  Build a name in the form of Prefix__Selector, with an optional character
266    --  appended. This is used for internal subprograms generated for operations
267    --  of protected types, including barrier functions. For the subprograms
268    --  generated for entry bodies and entry barriers, the generated name
269    --  includes a sequence number that makes names unique in the presence of
270    --  entry overloading. This is necessary because entry body procedures and
271    --  barrier functions all have the same signature.
272
273    procedure Build_Simple_Entry_Call
274      (N       : Node_Id;
275       Concval : Node_Id;
276       Ename   : Node_Id;
277       Index   : Node_Id);
278    --  Some comments here would be useful ???
279
280    function Build_Task_Proc_Specification (T : Entity_Id) return Node_Id;
281    --  This routine constructs a specification for the procedure that we will
282    --  build for the task body for task type T. The spec has the form:
283    --
284    --    procedure tnameB (_Task : access tnameV);
285    --
286    --  where name is the character name taken from the task type entity that
287    --  is passed as the argument to the procedure, and tnameV is the task
288    --  value type that is associated with the task type.
289
290    function Build_Unprotected_Subprogram_Body
291      (N   : Node_Id;
292       Pid : Node_Id) return Node_Id;
293    --  This routine constructs the unprotected version of a protected
294    --  subprogram body, which is contains all of the code in the original,
295    --  unexpanded body. This is the version of the protected subprogram that is
296    --  called from all protected operations on the same object, including the
297    --  protected version of the same subprogram.
298
299    procedure Build_Wrapper_Bodies
300      (Loc : Source_Ptr;
301       Typ : Entity_Id;
302       N   : Node_Id);
303    --  Ada 2005 (AI-345): Typ is either a concurrent type or the corresponding
304    --  record of a concurrent type. N is the insertion node where all bodies
305    --  will be placed. This routine builds the bodies of the subprograms which
306    --  serve as an indirection mechanism to overriding primitives of concurrent
307    --  types, entries and protected procedures. Any new body is analyzed.
308
309    procedure Build_Wrapper_Specs
310      (Loc : Source_Ptr;
311       Typ : Entity_Id;
312       N   : in out Node_Id);
313    --  Ada 2005 (AI-345): Typ is either a concurrent type or the corresponding
314    --  record of a concurrent type. N is the insertion node where all specs
315    --  will be placed. This routine builds the specs of the subprograms which
316    --  serve as an indirection mechanism to overriding primitives of concurrent
317    --  types, entries and protected procedures. Any new spec is analyzed.
318
319    procedure Collect_Entry_Families
320      (Loc          : Source_Ptr;
321       Cdecls       : List_Id;
322       Current_Node : in out Node_Id;
323       Conctyp      : Entity_Id);
324    --  For each entry family in a concurrent type, create an anonymous array
325    --  type of the right size, and add a component to the corresponding_record.
326
327    function Concurrent_Object
328      (Spec_Id  : Entity_Id;
329       Conc_Typ : Entity_Id) return Entity_Id;
330    --  Given a subprogram entity Spec_Id and concurrent type Conc_Typ, return
331    --  the entity associated with the concurrent object in the Protected_Body_
332    --  Subprogram or the Task_Body_Procedure of Spec_Id. The returned entity
333    --  denotes formal parameter _O, _object or _task.
334
335    function Copy_Result_Type (Res : Node_Id) return Node_Id;
336    --  Copy the result type of a function specification, when building the
337    --  internal operation corresponding to a protected function, or when
338    --  expanding an access to protected function. If the result is an anonymous
339    --  access to subprogram itself, we need to create a new signature with the
340    --  same parameter names and the same resolved types, but with new entities
341    --  for the formals.
342
343    procedure Debug_Private_Data_Declarations (Decls : List_Id);
344    --  Decls is a list which may contain the declarations created by Install_
345    --  Private_Data_Declarations. All generated entities are marked as needing
346    --  debug info and debug nodes are manually generation where necessary. This
347    --  step of the expansion must to be done after private data has been moved
348    --  to its final resting scope to ensure proper visibility of debug objects.
349
350    procedure Ensure_Statement_Present (Loc : Source_Ptr; Alt : Node_Id);
351    --  If control flow optimizations are suppressed, and Alt is an accept,
352    --  delay, or entry call alternative with no trailing statements, insert
353    --  a null trailing statement with the given Loc (which is the sloc of
354    --  the accept, delay, or entry call statement). There might not be any
355    --  generated code for the accept, delay, or entry call itself (the effect
356    --  of these statements is part of the general processsing done for the
357    --  enclosing selective accept, timed entry call, or asynchronous select),
358    --  and the null statement is there to carry the sloc of that statement to
359    --  the back-end for trace-based coverage analysis purposes.
360
361    procedure Extract_Dispatching_Call
362      (N        : Node_Id;
363       Call_Ent : out Entity_Id;
364       Object   : out Entity_Id;
365       Actuals  : out List_Id;
366       Formals  : out List_Id);
367    --  Given a dispatching call, extract the entity of the name of the call,
368    --  its actual dispatching object, its actual parameters and the formal
369    --  parameters of the overridden interface-level version. If the type of
370    --  the dispatching object is an access type then an explicit dereference
371    --  is returned in Object.
372
373    procedure Extract_Entry
374      (N       : Node_Id;
375       Concval : out Node_Id;
376       Ename   : out Node_Id;
377       Index   : out Node_Id);
378    --  Given an entry call, returns the associated concurrent object, the entry
379    --  name, and the entry family index.
380
381    function Family_Offset
382      (Loc  : Source_Ptr;
383       Hi   : Node_Id;
384       Lo   : Node_Id;
385       Ttyp : Entity_Id;
386       Cap  : Boolean) return Node_Id;
387    --  Compute (Hi - Lo) for two entry family indexes. Hi is the index in an
388    --  accept statement, or the upper bound in the discrete subtype of an entry
389    --  declaration. Lo is the corresponding lower bound. Ttyp is the concurrent
390    --  type of the entry. If Cap is true, the result is capped according to
391    --  Entry_Family_Bound.
392
393    function Family_Size
394      (Loc  : Source_Ptr;
395       Hi   : Node_Id;
396       Lo   : Node_Id;
397       Ttyp : Entity_Id;
398       Cap  : Boolean) return Node_Id;
399    --  Compute (Hi - Lo) + 1 Max 0, to determine the number of entries in a
400    --  family, and handle properly the superflat case. This is equivalent to
401    --  the use of 'Length on the index type, but must use Family_Offset to
402    --  handle properly the case of bounds that depend on discriminants. If
403    --  Cap is true, the result is capped according to Entry_Family_Bound.
404
405    procedure Find_Enclosing_Context
406      (N             : Node_Id;
407       Context       : out Node_Id;
408       Context_Id    : out Entity_Id;
409       Context_Decls : out List_Id);
410    --  Subsidiary routine to procedures Build_Activation_Chain_Entity and
411    --  Build_Master_Entity. Given an arbitrary node in the tree, find the
412    --  nearest enclosing body, block, package or return statement and return
413    --  its constituents. Context is the enclosing construct, Context_Id is
414    --  the scope of Context_Id and Context_Decls is the declarative list of
415    --  Context.
416
417    function Index_Object (Spec_Id : Entity_Id) return Entity_Id;
418    --  Given a subprogram identifier, return the entity which is associated
419    --  with the protection entry index in the Protected_Body_Subprogram or
420    --  the Task_Body_Procedure of Spec_Id. The returned entity denotes formal
421    --  parameter _E.
422
423    function Is_Exception_Safe (Subprogram : Node_Id) return Boolean;
424    --  Tell whether a given subprogram cannot raise an exception
425
426    function Is_Potentially_Large_Family
427      (Base_Index : Entity_Id;
428       Conctyp    : Entity_Id;
429       Lo         : Node_Id;
430       Hi         : Node_Id) return Boolean;
431
432    function Is_Private_Primitive_Subprogram (Id : Entity_Id) return Boolean;
433    --  Determine whether Id is a function or a procedure and is marked as a
434    --  private primitive.
435
436    function Null_Statements (Stats : List_Id) return Boolean;
437    --  Used to check DO-END sequence. Checks for equivalent of DO NULL; END.
438    --  Allows labels, and pragma Warnings/Unreferenced in the sequence as well
439    --  to still count as null. Returns True for a null sequence. The argument
440    --  is the list of statements from the DO-END sequence.
441
442    function Parameter_Block_Pack
443      (Loc     : Source_Ptr;
444       Blk_Typ : Entity_Id;
445       Actuals : List_Id;
446       Formals : List_Id;
447       Decls   : List_Id;
448       Stmts   : List_Id) return Entity_Id;
449    --  Set the components of the generated parameter block with the values
450    --  of the actual parameters. Generate aliased temporaries to capture the
451    --  values for types that are passed by copy. Otherwise generate a reference
452    --  to the actual's value. Return the address of the aggregate block.
453    --  Generate:
454    --    Jnn1 : alias <formal-type1>;
455    --    Jnn1 := <actual1>;
456    --    ...
457    --    P : Blk_Typ := (
458    --      Jnn1'unchecked_access;
459    --      <actual2>'reference;
460    --      ...);
461
462    function Parameter_Block_Unpack
463      (Loc     : Source_Ptr;
464       P       : Entity_Id;
465       Actuals : List_Id;
466       Formals : List_Id) return List_Id;
467    --  Retrieve the values of the components from the parameter block and
468    --  assign then to the original actual parameters. Generate:
469    --    <actual1> := P.<formal1>;
470    --    ...
471    --    <actualN> := P.<formalN>;
472
473    function Trivial_Accept_OK return Boolean;
474    --  If there is no DO-END block for an accept, or if the DO-END block has
475    --  only null statements, then it is possible to do the Rendezvous with much
476    --  less overhead using the Accept_Trivial routine in the run-time library.
477    --  However, this is not always a valid optimization. Whether it is valid or
478    --  not depends on the Task_Dispatching_Policy. The issue is whether a full
479    --  rescheduling action is required or not. In FIFO_Within_Priorities, such
480    --  a rescheduling is required, so this optimization is not allowed. This
481    --  function returns True if the optimization is permitted.
482
483    -----------------------------
484    -- Actual_Index_Expression --
485    -----------------------------
486
487    function Actual_Index_Expression
488      (Sloc  : Source_Ptr;
489       Ent   : Entity_Id;
490       Index : Node_Id;
491       Tsk   : Entity_Id) return Node_Id
492    is
493       Ttyp : constant Entity_Id := Etype (Tsk);
494       Expr : Node_Id;
495       Num  : Node_Id;
496       Lo   : Node_Id;
497       Hi   : Node_Id;
498       Prev : Entity_Id;
499       S    : Node_Id;
500
501       function Actual_Family_Offset (Hi, Lo : Node_Id) return Node_Id;
502       --  Compute difference between bounds of entry family
503
504       --------------------------
505       -- Actual_Family_Offset --
506       --------------------------
507
508       function Actual_Family_Offset (Hi, Lo : Node_Id) return Node_Id is
509
510          function Actual_Discriminant_Ref (Bound : Node_Id) return Node_Id;
511          --  Replace a reference to a discriminant with a selected component
512          --  denoting the discriminant of the target task.
513
514          -----------------------------
515          -- Actual_Discriminant_Ref --
516          -----------------------------
517
518          function Actual_Discriminant_Ref (Bound : Node_Id) return Node_Id is
519             Typ : constant Entity_Id := Etype (Bound);
520             B   : Node_Id;
521
522          begin
523             if not Is_Entity_Name (Bound)
524               or else Ekind (Entity (Bound)) /= E_Discriminant
525             then
526                if Nkind (Bound) = N_Attribute_Reference then
527                   return Bound;
528                else
529                   B := New_Copy_Tree (Bound);
530                end if;
531
532             else
533                B :=
534                  Make_Selected_Component (Sloc,
535                    Prefix        => New_Copy_Tree (Tsk),
536                    Selector_Name => New_Occurrence_Of (Entity (Bound), Sloc));
537
538                Analyze_And_Resolve (B, Typ);
539             end if;
540
541             return
542               Make_Attribute_Reference (Sloc,
543                 Attribute_Name => Name_Pos,
544                 Prefix         => New_Occurrence_Of (Etype (Bound), Sloc),
545                 Expressions    => New_List (B));
546          end Actual_Discriminant_Ref;
547
548       --  Start of processing for Actual_Family_Offset
549
550       begin
551          return
552            Make_Op_Subtract (Sloc,
553              Left_Opnd  => Actual_Discriminant_Ref (Hi),
554              Right_Opnd => Actual_Discriminant_Ref (Lo));
555       end Actual_Family_Offset;
556
557    --  Start of processing for Actual_Index_Expression
558
559    begin
560       --  The queues of entries and entry families appear in textual order in
561       --  the associated record. The entry index is computed as the sum of the
562       --  number of queues for all entries that precede the designated one, to
563       --  which is added the index expression, if this expression denotes a
564       --  member of a family.
565
566       --  The following is a place holder for the count of simple entries
567
568       Num := Make_Integer_Literal (Sloc, 1);
569
570       --  We construct an expression which is a series of addition operations.
571       --  See comments in Entry_Index_Expression, which is identical in
572       --  structure.
573
574       if Present (Index) then
575          S := Etype (Discrete_Subtype_Definition (Declaration_Node (Ent)));
576
577          Expr :=
578            Make_Op_Add (Sloc,
579              Left_Opnd  => Num,
580              Right_Opnd =>
581                Actual_Family_Offset (
582                  Make_Attribute_Reference (Sloc,
583                    Attribute_Name => Name_Pos,
584                    Prefix => New_Occurrence_Of (Base_Type (S), Sloc),
585                    Expressions => New_List (Relocate_Node (Index))),
586                  Type_Low_Bound (S)));
587       else
588          Expr := Num;
589       end if;
590
591       --  Now add lengths of preceding entries and entry families
592
593       Prev := First_Entity (Ttyp);
594       while Chars (Prev) /= Chars (Ent)
595         or else (Ekind (Prev) /= Ekind (Ent))
596         or else not Sem_Ch6.Type_Conformant (Ent, Prev)
597       loop
598          if Ekind (Prev) = E_Entry then
599             Set_Intval (Num, Intval (Num) + 1);
600
601          elsif Ekind (Prev) = E_Entry_Family then
602             S :=
603               Etype (Discrete_Subtype_Definition (Declaration_Node (Prev)));
604
605             --  The need for the following full view retrieval stems from this
606             --  complex case of nested generics and tasking:
607
608             --     generic
609             --        type Formal_Index is range <>;
610             --        ...
611             --     package Outer is
612             --        type Index is private;
613             --        generic
614             --           ...
615             --        package Inner is
616             --           procedure P;
617             --        end Inner;
618             --     private
619             --        type Index is new Formal_Index range 1 .. 10;
620             --     end Outer;
621
622             --     package body Outer is
623             --        task type T is
624             --           entry Fam (Index);  --  (2)
625             --           entry E;
626             --        end T;
627             --        package body Inner is  --  (3)
628             --           procedure P is
629             --           begin
630             --              T.E;             --  (1)
631             --           end P;
632             --       end Inner;
633             --       ...
634
635             --  We are currently building the index expression for the entry
636             --  call "T.E" (1). Part of the expansion must mention the range
637             --  of the discrete type "Index" (2) of entry family "Fam".
638
639             --  However only the private view of type "Index" is available to
640             --  the inner generic (3) because there was no prior mention of
641             --  the type inside "Inner". This visibility requirement is
642             --  implicit and cannot be detected during the construction of
643             --  the generic trees and needs special handling.
644
645             if In_Instance_Body
646               and then Is_Private_Type (S)
647               and then Present (Full_View (S))
648             then
649                S := Full_View (S);
650             end if;
651
652             Lo := Type_Low_Bound  (S);
653             Hi := Type_High_Bound (S);
654
655             Expr :=
656               Make_Op_Add (Sloc,
657               Left_Opnd  => Expr,
658               Right_Opnd =>
659                 Make_Op_Add (Sloc,
660                   Left_Opnd  => Actual_Family_Offset (Hi, Lo),
661                   Right_Opnd => Make_Integer_Literal (Sloc, 1)));
662
663          --  Other components are anonymous types to be ignored
664
665          else
666             null;
667          end if;
668
669          Next_Entity (Prev);
670       end loop;
671
672       return Expr;
673    end Actual_Index_Expression;
674
675    --------------------------
676    -- Add_Formal_Renamings --
677    --------------------------
678
679    procedure Add_Formal_Renamings
680      (Spec  : Node_Id;
681       Decls : List_Id;
682       Ent   : Entity_Id;
683       Loc   : Source_Ptr)
684    is
685       Ptr : constant Entity_Id :=
686               Defining_Identifier
687                 (Next (First (Parameter_Specifications (Spec))));
688       --  The name of the formal that holds the address of the parameter block
689       --  for the call.
690
691       Comp            : Entity_Id;
692       Decl            : Node_Id;
693       Formal          : Entity_Id;
694       New_F           : Entity_Id;
695       Renamed_Formal  : Node_Id;
696
697    begin
698       Formal := First_Formal (Ent);
699       while Present (Formal) loop
700          Comp := Entry_Component (Formal);
701          New_F :=
702            Make_Defining_Identifier (Sloc (Formal),
703              Chars => Chars (Formal));
704          Set_Etype (New_F, Etype (Formal));
705          Set_Scope (New_F, Ent);
706
707          --  Now we set debug info needed on New_F even though it does not come
708          --  from source, so that the debugger will get the right information
709          --  for these generated names.
710
711          Set_Debug_Info_Needed (New_F);
712
713          if Ekind (Formal) = E_In_Parameter then
714             Set_Ekind (New_F, E_Constant);
715          else
716             Set_Ekind (New_F, E_Variable);
717             Set_Extra_Constrained (New_F, Extra_Constrained (Formal));
718          end if;
719
720          Set_Actual_Subtype (New_F, Actual_Subtype (Formal));
721
722          Renamed_Formal :=
723            Make_Selected_Component (Loc,
724              Prefix        =>
725                Unchecked_Convert_To (Entry_Parameters_Type (Ent),
726                  Make_Identifier (Loc, Chars (Ptr))),
727              Selector_Name => New_Occurrence_Of (Comp, Loc));
728
729          Decl :=
730            Build_Renamed_Formal_Declaration
731              (New_F, Formal, Comp, Renamed_Formal);
732
733          Append (Decl, Decls);
734          Set_Renamed_Object (Formal, New_F);
735          Next_Formal (Formal);
736       end loop;
737    end Add_Formal_Renamings;
738
739    ------------------------
740    -- Add_Object_Pointer --
741    ------------------------
742
743    procedure Add_Object_Pointer
744      (Loc      : Source_Ptr;
745       Conc_Typ : Entity_Id;
746       Decls    : List_Id)
747    is
748       Rec_Typ : constant Entity_Id := Corresponding_Record_Type (Conc_Typ);
749       Decl    : Node_Id;
750       Obj_Ptr : Node_Id;
751
752    begin
753       --  Create the renaming declaration for the Protection object of a
754       --  protected type. _Object is used by Complete_Entry_Body.
755       --  ??? An attempt to make this a renaming was unsuccessful.
756
757       --  Build the entity for the access type
758
759       Obj_Ptr :=
760         Make_Defining_Identifier (Loc,
761           New_External_Name (Chars (Rec_Typ), 'P'));
762
763       --  Generate:
764       --    _object : poVP := poVP!O;
765
766       Decl :=
767         Make_Object_Declaration (Loc,
768           Defining_Identifier => Make_Defining_Identifier (Loc, Name_uObject),
769           Object_Definition   => New_Occurrence_Of (Obj_Ptr, Loc),
770           Expression          =>
771             Unchecked_Convert_To (Obj_Ptr, Make_Identifier (Loc, Name_uO)));
772       Set_Debug_Info_Needed (Defining_Identifier (Decl));
773       Prepend_To (Decls, Decl);
774
775       --  Generate:
776       --    type poVP is access poV;
777
778       Decl :=
779         Make_Full_Type_Declaration (Loc,
780           Defining_Identifier =>
781             Obj_Ptr,
782           Type_Definition =>
783             Make_Access_To_Object_Definition (Loc,
784               Subtype_Indication =>
785                 New_Occurrence_Of (Rec_Typ, Loc)));
786       Set_Debug_Info_Needed (Defining_Identifier (Decl));
787       Prepend_To (Decls, Decl);
788    end Add_Object_Pointer;
789
790    -----------------------
791    -- Build_Accept_Body --
792    -----------------------
793
794    function Build_Accept_Body (Astat : Node_Id) return  Node_Id is
795       Loc     : constant Source_Ptr := Sloc (Astat);
796       Stats   : constant Node_Id    := Handled_Statement_Sequence (Astat);
797       New_S   : Node_Id;
798       Hand    : Node_Id;
799       Call    : Node_Id;
800       Ohandle : Node_Id;
801
802    begin
803       --  At the end of the statement sequence, Complete_Rendezvous is called.
804       --  A label skipping the Complete_Rendezvous, and all other accept
805       --  processing, has already been added for the expansion of requeue
806       --  statements. The Sloc is copied from the last statement since it
807       --  is really part of this last statement.
808
809       Call :=
810         Build_Runtime_Call
811           (Sloc (Last (Statements (Stats))), RE_Complete_Rendezvous);
812       Insert_Before (Last (Statements (Stats)), Call);
813       Analyze (Call);
814
815       --  If exception handlers are present, then append Complete_Rendezvous
816       --  calls to the handlers, and construct the required outer block. As
817       --  above, the Sloc is copied from the last statement in the sequence.
818
819       if Present (Exception_Handlers (Stats)) then
820          Hand := First (Exception_Handlers (Stats));
821          while Present (Hand) loop
822             Call :=
823               Build_Runtime_Call
824                 (Sloc (Last (Statements (Hand))), RE_Complete_Rendezvous);
825             Append (Call, Statements (Hand));
826             Analyze (Call);
827             Next (Hand);
828          end loop;
829
830          New_S :=
831            Make_Handled_Sequence_Of_Statements (Loc,
832              Statements => New_List (
833                Make_Block_Statement (Loc,
834                  Handled_Statement_Sequence => Stats)));
835
836       else
837          New_S := Stats;
838       end if;
839
840       --  At this stage we know that the new statement sequence does
841       --  not have an exception handler part, so we supply one to call
842       --  Exceptional_Complete_Rendezvous. This handler is
843
844       --    when all others =>
845       --       Exceptional_Complete_Rendezvous (Get_GNAT_Exception);
846
847       --  We handle Abort_Signal to make sure that we properly catch the abort
848       --  case and wake up the caller.
849
850       Ohandle := Make_Others_Choice (Loc);
851       Set_All_Others (Ohandle);
852
853       Set_Exception_Handlers (New_S,
854         New_List (
855           Make_Implicit_Exception_Handler (Loc,
856             Exception_Choices => New_List (Ohandle),
857
858             Statements =>  New_List (
859               Make_Procedure_Call_Statement (Sloc (Stats),
860                 Name                   => New_Occurrence_Of (
861                   RTE (RE_Exceptional_Complete_Rendezvous), Sloc (Stats)),
862                 Parameter_Associations => New_List (
863                   Make_Function_Call (Sloc (Stats),
864                     Name =>
865                       New_Occurrence_Of
866                         (RTE (RE_Get_GNAT_Exception), Sloc (Stats)))))))));
867
868       Set_Parent (New_S, Astat); -- temp parent for Analyze call
869       Analyze_Exception_Handlers (Exception_Handlers (New_S));
870       Expand_Exception_Handlers (New_S);
871
872       --  Exceptional_Complete_Rendezvous must be called with abort still
873       --  deferred, which is the case for a "when all others" handler.
874
875       return New_S;
876    end Build_Accept_Body;
877
878    -----------------------------------
879    -- Build_Activation_Chain_Entity --
880    -----------------------------------
881
882    procedure Build_Activation_Chain_Entity (N : Node_Id) is
883       function Has_Activation_Chain (Stmt : Node_Id) return Boolean;
884       --  Determine whether an extended return statement has activation chain
885
886       --------------------------
887       -- Has_Activation_Chain --
888       --------------------------
889
890       function Has_Activation_Chain (Stmt : Node_Id) return Boolean is
891          Decl : Node_Id;
892
893       begin
894          Decl := First (Return_Object_Declarations (Stmt));
895          while Present (Decl) loop
896             if Nkind (Decl) = N_Object_Declaration
897               and then Chars (Defining_Identifier (Decl)) = Name_uChain
898             then
899                return True;
900             end if;
901
902             Next (Decl);
903          end loop;
904
905          return False;
906       end Has_Activation_Chain;
907
908       --  Local variables
909
910       Context    : Node_Id;
911       Context_Id : Entity_Id;
912       Decls      : List_Id;
913
914    --  Start of processing for Build_Activation_Chain_Entity
915
916    begin
917       --  Activation chain is never used for sequential elaboration policy, see
918       --  comment for Create_Restricted_Task_Sequential in s-tarest.ads).
919
920       if Partition_Elaboration_Policy = 'S' then
921          return;
922       end if;
923
924       Find_Enclosing_Context (N, Context, Context_Id, Decls);
925
926       --  If activation chain entity has not been declared already, create one
927
928       if Nkind (Context) = N_Extended_Return_Statement
929         or else No (Activation_Chain_Entity (Context))
930       then
931          --  Since extended return statements do not store the entity of the
932          --  chain, examine the return object declarations to avoid creating
933          --  a duplicate.
934
935          if Nkind (Context) = N_Extended_Return_Statement
936            and then Has_Activation_Chain (Context)
937          then
938             return;
939          end if;
940
941          declare
942             Loc   : constant Source_Ptr := Sloc (Context);
943             Chain : Entity_Id;
944             Decl  : Node_Id;
945
946          begin
947             Chain := Make_Defining_Identifier (Sloc (N), Name_uChain);
948
949             --  Note: An extended return statement is not really a task
950             --  activator, but it does have an activation chain on which to
951             --  store the tasks temporarily. On successful return, the tasks
952             --  on this chain are moved to the chain passed in by the caller.
953             --  We do not build an Activation_Chain_Entity for an extended
954             --  return statement, because we do not want to build a call to
955             --  Activate_Tasks. Task activation is the responsibility of the
956             --  caller.
957
958             if Nkind (Context) /= N_Extended_Return_Statement then
959                Set_Activation_Chain_Entity (Context, Chain);
960             end if;
961
962             Decl :=
963               Make_Object_Declaration (Loc,
964                 Defining_Identifier => Chain,
965                 Aliased_Present     => True,
966                 Object_Definition   =>
967                   New_Occurrence_Of (RTE (RE_Activation_Chain), Loc));
968
969             Prepend_To (Decls, Decl);
970
971             --  Ensure that _chain appears in the proper scope of the context
972
973             if Context_Id /= Current_Scope then
974                Push_Scope (Context_Id);
975                Analyze (Decl);
976                Pop_Scope;
977             else
978                Analyze (Decl);
979             end if;
980          end;
981       end if;
982    end Build_Activation_Chain_Entity;
983
984    ----------------------------
985    -- Build_Barrier_Function --
986    ----------------------------
987
988    function Build_Barrier_Function
989      (N   : Node_Id;
990       Ent : Entity_Id;
991       Pid : Node_Id) return Node_Id
992    is
993       Ent_Formals : constant Node_Id    := Entry_Body_Formal_Part (N);
994       Cond        : constant Node_Id    := Condition (Ent_Formals);
995       Loc         : constant Source_Ptr := Sloc (Cond);
996       Func_Id     : constant Entity_Id  := Barrier_Function (Ent);
997       Op_Decls    : constant List_Id    := New_List;
998       Stmt        : Node_Id;
999       Func_Body   : Node_Id;
1000
1001    begin
1002       --  Add a declaration for the Protection object, renaming declarations
1003       --  for the discriminals and privals and finally a declaration for the
1004       --  entry family index (if applicable).
1005
1006       Install_Private_Data_Declarations (Sloc (N),
1007          Spec_Id  => Func_Id,
1008          Conc_Typ => Pid,
1009          Body_Nod => N,
1010          Decls    => Op_Decls,
1011          Barrier  => True,
1012          Family   => Ekind (Ent) = E_Entry_Family);
1013
1014       --  If compiling with -fpreserve-control-flow, make sure we insert an
1015       --  IF statement so that the back-end knows to generate a conditional
1016       --  branch instruction, even if the condition is just the name of a
1017       --  boolean object. Note that Expand_N_If_Statement knows to preserve
1018       --  such redundant IF statements under -fpreserve-control-flow
1019       --  (whether coming from this routine, or directly from source).
1020
1021       if Opt.Suppress_Control_Flow_Optimizations then
1022          Stmt :=
1023            Make_Implicit_If_Statement (Cond,
1024              Condition       => Cond,
1025              Then_Statements => New_List (
1026                Make_Simple_Return_Statement (Loc,
1027                  New_Occurrence_Of (Standard_True, Loc))),
1028
1029              Else_Statements => New_List (
1030                Make_Simple_Return_Statement (Loc,
1031                  New_Occurrence_Of (Standard_False, Loc))));
1032
1033       else
1034          Stmt := Make_Simple_Return_Statement (Loc, Cond);
1035       end if;
1036
1037       --  Note: the condition in the barrier function needs to be properly
1038       --  processed for the C/Fortran boolean possibility, but this happens
1039       --  automatically since the return statement does this normalization.
1040
1041       Func_Body :=
1042         Make_Subprogram_Body (Loc,
1043           Specification =>
1044             Build_Barrier_Function_Specification (Loc,
1045               Make_Defining_Identifier (Loc, Chars (Func_Id))),
1046           Declarations => Op_Decls,
1047           Handled_Statement_Sequence =>
1048             Make_Handled_Sequence_Of_Statements (Loc,
1049               Statements => New_List (Stmt)));
1050       Set_Is_Entry_Barrier_Function (Func_Body);
1051
1052       return Func_Body;
1053    end Build_Barrier_Function;
1054
1055    ------------------------------------------
1056    -- Build_Barrier_Function_Specification --
1057    ------------------------------------------
1058
1059    function Build_Barrier_Function_Specification
1060      (Loc    : Source_Ptr;
1061       Def_Id : Entity_Id) return Node_Id
1062    is
1063    begin
1064       Set_Debug_Info_Needed (Def_Id);
1065
1066       return
1067         Make_Function_Specification (Loc,
1068           Defining_Unit_Name       => Def_Id,
1069           Parameter_Specifications => New_List (
1070             Make_Parameter_Specification (Loc,
1071               Defining_Identifier =>
1072                 Make_Defining_Identifier (Loc, Name_uO),
1073               Parameter_Type      =>
1074                 New_Occurrence_Of (RTE (RE_Address), Loc)),
1075
1076             Make_Parameter_Specification (Loc,
1077               Defining_Identifier =>
1078                 Make_Defining_Identifier (Loc, Name_uE),
1079               Parameter_Type      =>
1080                 New_Occurrence_Of (RTE (RE_Protected_Entry_Index), Loc))),
1081
1082           Result_Definition        =>
1083             New_Occurrence_Of (Standard_Boolean, Loc));
1084    end Build_Barrier_Function_Specification;
1085
1086    --------------------------
1087    -- Build_Call_With_Task --
1088    --------------------------
1089
1090    function Build_Call_With_Task
1091      (N : Node_Id;
1092       E : Entity_Id) return Node_Id
1093    is
1094       Loc : constant Source_Ptr := Sloc (N);
1095    begin
1096       return
1097         Make_Function_Call (Loc,
1098           Name                   => New_Occurrence_Of (E, Loc),
1099           Parameter_Associations => New_List (Concurrent_Ref (N)));
1100    end Build_Call_With_Task;
1101
1102    -----------------------------
1103    -- Build_Class_Wide_Master --
1104    -----------------------------
1105
1106    procedure Build_Class_Wide_Master (Typ : Entity_Id) is
1107       Loc          : constant Source_Ptr := Sloc (Typ);
1108       Master_Id    : Entity_Id;
1109       Master_Scope : Entity_Id;
1110       Name_Id      : Node_Id;
1111       Related_Node : Node_Id;
1112       Ren_Decl     : Node_Id;
1113
1114    begin
1115       --  Nothing to do if there is no task hierarchy
1116
1117       if Restriction_Active (No_Task_Hierarchy) then
1118          return;
1119       end if;
1120
1121       --  Find the declaration that created the access type, which is either a
1122       --  type declaration, or an object declaration with an access definition,
1123       --  in which case the type is anonymous.
1124
1125       if Is_Itype (Typ) then
1126          Related_Node := Associated_Node_For_Itype (Typ);
1127       else
1128          Related_Node := Parent (Typ);
1129       end if;
1130
1131       Master_Scope := Find_Master_Scope (Typ);
1132
1133       --  Nothing to do if the master scope already contains a _master entity.
1134       --  The only exception to this is the following scenario:
1135
1136       --    Source_Scope
1137       --       Transient_Scope_1
1138       --          _master
1139
1140       --       Transient_Scope_2
1141       --          use of master
1142
1143       --  In this case the source scope is marked as having the master entity
1144       --  even though the actual declaration appears inside an inner scope. If
1145       --  the second transient scope requires a _master, it cannot use the one
1146       --  already declared because the entity is not visible.
1147
1148       Name_Id := Make_Identifier (Loc, Name_uMaster);
1149
1150       if not Has_Master_Entity (Master_Scope)
1151         or else No (Current_Entity_In_Scope (Name_Id))
1152       then
1153          declare
1154             Master_Decl : Node_Id;
1155          begin
1156             Set_Has_Master_Entity (Master_Scope);
1157
1158             --  Generate:
1159             --    _master : constant Integer := Current_Master.all;
1160
1161             Master_Decl :=
1162               Make_Object_Declaration (Loc,
1163                 Defining_Identifier =>
1164                   Make_Defining_Identifier (Loc, Name_uMaster),
1165                 Constant_Present    => True,
1166                 Object_Definition   =>
1167                   New_Occurrence_Of (Standard_Integer, Loc),
1168                 Expression          =>
1169                   Make_Explicit_Dereference (Loc,
1170                     New_Occurrence_Of (RTE (RE_Current_Master), Loc)));
1171
1172             Insert_Action (Find_Hook_Context (Related_Node), Master_Decl);
1173             Analyze (Master_Decl);
1174
1175             --  Mark the containing scope as a task master. Masters associated
1176             --  with return statements are already marked at this stage (see
1177             --  Analyze_Subprogram_Body).
1178
1179             if Ekind (Current_Scope) /= E_Return_Statement then
1180                declare
1181                   Par : Node_Id := Related_Node;
1182
1183                begin
1184                   while Nkind (Par) /= N_Compilation_Unit loop
1185                      Par := Parent (Par);
1186
1187                      --  If we fall off the top, we are at the outer level,
1188                      --  and the environment task is our effective master,
1189                      --  so nothing to mark.
1190
1191                      if Nkind_In (Par, N_Block_Statement,
1192                                        N_Subprogram_Body,
1193                                        N_Task_Body)
1194                      then
1195                         Set_Is_Task_Master (Par);
1196                         exit;
1197                      end if;
1198                   end loop;
1199                end;
1200             end if;
1201          end;
1202       end if;
1203
1204       Master_Id :=
1205         Make_Defining_Identifier (Loc, New_External_Name (Chars (Typ), 'M'));
1206
1207       --  Generate:
1208       --    typeMnn renames _master;
1209
1210       Ren_Decl :=
1211         Make_Object_Renaming_Declaration (Loc,
1212           Defining_Identifier => Master_Id,
1213           Subtype_Mark        => New_Occurrence_Of (Standard_Integer, Loc),
1214           Name                => Name_Id);
1215
1216       Insert_Action (Related_Node, Ren_Decl);
1217
1218       Set_Master_Id (Typ, Master_Id);
1219    end Build_Class_Wide_Master;
1220
1221    --------------------------------
1222    -- Build_Corresponding_Record --
1223    --------------------------------
1224
1225    function Build_Corresponding_Record
1226     (N    : Node_Id;
1227      Ctyp : Entity_Id;
1228      Loc  : Source_Ptr) return Node_Id
1229    is
1230       Rec_Ent  : constant Entity_Id :=
1231                    Make_Defining_Identifier
1232                      (Loc, New_External_Name (Chars (Ctyp), 'V'));
1233       Disc     : Entity_Id;
1234       Dlist    : List_Id;
1235       New_Disc : Entity_Id;
1236       Cdecls   : List_Id;
1237
1238    begin
1239       Set_Corresponding_Record_Type     (Ctyp, Rec_Ent);
1240       Set_Ekind                         (Rec_Ent, E_Record_Type);
1241       Set_Has_Delayed_Freeze            (Rec_Ent, Has_Delayed_Freeze (Ctyp));
1242       Set_Is_Concurrent_Record_Type     (Rec_Ent, True);
1243       Set_Corresponding_Concurrent_Type (Rec_Ent, Ctyp);
1244       Set_Stored_Constraint             (Rec_Ent, No_Elist);
1245       Cdecls := New_List;
1246
1247       --  Propagate type invariants to the corresponding record type
1248
1249       Set_Has_Invariants                (Rec_Ent, Has_Invariants (Ctyp));
1250       Set_Has_Inheritable_Invariants    (Rec_Ent,
1251         Has_Inheritable_Invariants (Ctyp));
1252
1253       --  Use discriminals to create list of discriminants for record, and
1254       --  create new discriminals for use in default expressions, etc. It is
1255       --  worth noting that a task discriminant gives rise to 5 entities;
1256
1257       --  a) The original discriminant.
1258       --  b) The discriminal for use in the task.
1259       --  c) The discriminant of the corresponding record.
1260       --  d) The discriminal for the init proc of the corresponding record.
1261       --  e) The local variable that renames the discriminant in the procedure
1262       --     for the task body.
1263
1264       --  In fact the discriminals b) are used in the renaming declarations
1265       --  for e). See details in einfo (Handling of Discriminants).
1266
1267       if Present (Discriminant_Specifications (N)) then
1268          Dlist := New_List;
1269          Disc := First_Discriminant (Ctyp);
1270
1271          while Present (Disc) loop
1272             New_Disc := CR_Discriminant (Disc);
1273
1274             Append_To (Dlist,
1275               Make_Discriminant_Specification (Loc,
1276                 Defining_Identifier => New_Disc,
1277                 Discriminant_Type =>
1278                   New_Occurrence_Of (Etype (Disc), Loc),
1279                 Expression =>
1280                   New_Copy (Discriminant_Default_Value (Disc))));
1281
1282             Next_Discriminant (Disc);
1283          end loop;
1284
1285       else
1286          Dlist := No_List;
1287       end if;
1288
1289       --  Now we can construct the record type declaration. Note that this
1290       --  record is "limited tagged". It is "limited" to reflect the underlying
1291       --  limitedness of the task or protected object that it represents, and
1292       --  ensuring for example that it is properly passed by reference. It is
1293       --  "tagged" to give support to dispatching calls through interfaces. We
1294       --  propagate here the list of interfaces covered by the concurrent type
1295       --  (Ada 2005: AI-345).
1296
1297       return
1298         Make_Full_Type_Declaration (Loc,
1299           Defining_Identifier => Rec_Ent,
1300           Discriminant_Specifications => Dlist,
1301           Type_Definition =>
1302             Make_Record_Definition (Loc,
1303               Component_List  =>
1304                 Make_Component_List (Loc, Component_Items => Cdecls),
1305               Tagged_Present  =>
1306                  Ada_Version >= Ada_2005 and then Is_Tagged_Type (Ctyp),
1307               Interface_List  => Interface_List (N),
1308               Limited_Present => True));
1309    end Build_Corresponding_Record;
1310
1311    ---------------------------------
1312    -- Build_Dispatching_Tag_Check --
1313    ---------------------------------
1314
1315    function Build_Dispatching_Tag_Check
1316      (K : Entity_Id;
1317       N : Node_Id) return Node_Id
1318    is
1319       Loc : constant Source_Ptr := Sloc (N);
1320
1321    begin
1322       return
1323          Make_Op_Or (Loc,
1324            Make_Op_Eq (Loc,
1325              Left_Opnd  =>
1326                New_Occurrence_Of (K, Loc),
1327              Right_Opnd =>
1328                New_Occurrence_Of (RTE (RE_TK_Limited_Tagged), Loc)),
1329
1330            Make_Op_Eq (Loc,
1331              Left_Opnd  =>
1332                New_Occurrence_Of (K, Loc),
1333              Right_Opnd =>
1334                New_Occurrence_Of (RTE (RE_TK_Tagged), Loc)));
1335    end Build_Dispatching_Tag_Check;
1336
1337    ----------------------------------
1338    -- Build_Entry_Count_Expression --
1339    ----------------------------------
1340
1341    function Build_Entry_Count_Expression
1342      (Concurrent_Type : Node_Id;
1343       Component_List  : List_Id;
1344       Loc             : Source_Ptr) return Node_Id
1345    is
1346       Eindx  : Nat;
1347       Ent    : Entity_Id;
1348       Ecount : Node_Id;
1349       Comp   : Node_Id;
1350       Lo     : Node_Id;
1351       Hi     : Node_Id;
1352       Typ    : Entity_Id;
1353       Large  : Boolean;
1354
1355    begin
1356       --  Count number of non-family entries
1357
1358       Eindx := 0;
1359       Ent := First_Entity (Concurrent_Type);
1360       while Present (Ent) loop
1361          if Ekind (Ent) = E_Entry then
1362             Eindx := Eindx + 1;
1363          end if;
1364
1365          Next_Entity (Ent);
1366       end loop;
1367
1368       Ecount := Make_Integer_Literal (Loc, Eindx);
1369
1370       --  Loop through entry families building the addition nodes
1371
1372       Ent := First_Entity (Concurrent_Type);
1373       Comp := First (Component_List);
1374       while Present (Ent) loop
1375          if Ekind (Ent) = E_Entry_Family then
1376             while Chars (Ent) /= Chars (Defining_Identifier (Comp)) loop
1377                Next (Comp);
1378             end loop;
1379
1380             Typ := Etype (Discrete_Subtype_Definition (Parent (Ent)));
1381             Hi := Type_High_Bound (Typ);
1382             Lo := Type_Low_Bound  (Typ);
1383             Large := Is_Potentially_Large_Family
1384                        (Base_Type (Typ), Concurrent_Type, Lo, Hi);
1385             Ecount :=
1386               Make_Op_Add (Loc,
1387                 Left_Opnd  => Ecount,
1388                 Right_Opnd =>
1389                   Family_Size (Loc, Hi, Lo, Concurrent_Type, Large));
1390          end if;
1391
1392          Next_Entity (Ent);
1393       end loop;
1394
1395       return Ecount;
1396    end Build_Entry_Count_Expression;
1397
1398    -----------------------
1399    -- Build_Entry_Names --
1400    -----------------------
1401
1402    procedure Build_Entry_Names
1403      (Obj_Ref : Node_Id;
1404       Obj_Typ : Entity_Id;
1405       Stmts   : List_Id)
1406    is
1407       Loc   : constant Source_Ptr := Sloc (Obj_Ref);
1408       Data  : Entity_Id := Empty;
1409       Index : Entity_Id := Empty;
1410       Typ   : Entity_Id := Obj_Typ;
1411
1412       procedure Build_Entry_Name (Comp_Id : Entity_Id);
1413       --  Given an entry [family], create a static string which denotes the
1414       --  name of Comp_Id and assign it to the underlying data structure which
1415       --  contains the entry names of a concurrent object.
1416
1417       function Object_Reference return Node_Id;
1418       --  Return a reference to field _object or _task_id depending on the
1419       --  concurrent object being processed.
1420
1421       ----------------------
1422       -- Build_Entry_Name --
1423       ----------------------
1424
1425       procedure Build_Entry_Name (Comp_Id : Entity_Id) is
1426          function Build_Range (Def : Node_Id) return Node_Id;
1427          --  Given a discrete subtype definition of an entry family, generate a
1428          --  range node which covers the range of Def's type.
1429
1430          procedure Create_Index_And_Data;
1431          --  Generate the declarations of variables Index and Data. Subsequent
1432          --  calls do nothing.
1433
1434          function Increment_Index return Node_Id;
1435          --  Increment the index used in the assignment of string names to the
1436          --  Data array.
1437
1438          function Name_Declaration (Def_Id : Entity_Id) return Node_Id;
1439          --  Given the name of a temporary variable, create the following
1440          --  declaration for it:
1441          --
1442          --    Def_Id : aliased constant String := <String_Name_From_Buffer>;
1443
1444          function Set_Entry_Name (Def_Id : Entity_Id) return Node_Id;
1445          --  Given the name of a temporary variable, place it in the array of
1446          --  string names. Generate:
1447          --
1448          --    Data (Index) := Def_Id'Unchecked_Access;
1449
1450          -----------------
1451          -- Build_Range --
1452          -----------------
1453
1454          function Build_Range (Def : Node_Id) return Node_Id is
1455             High : Node_Id := Type_High_Bound (Etype (Def));
1456             Low  : Node_Id := Type_Low_Bound  (Etype (Def));
1457
1458          begin
1459             --  If a bound references a discriminant, generate an identifier
1460             --  with the same name. Resolution will map it to the formals of
1461             --  the init proc.
1462
1463             if Is_Entity_Name (Low)
1464               and then Ekind (Entity (Low)) = E_Discriminant
1465             then
1466                Low :=
1467                  Make_Selected_Component (Loc,
1468                    Prefix        => New_Copy_Tree (Obj_Ref),
1469                    Selector_Name => Make_Identifier (Loc, Chars (Low)));
1470             else
1471                Low := New_Copy_Tree (Low);
1472             end if;
1473
1474             if Is_Entity_Name (High)
1475               and then Ekind (Entity (High)) = E_Discriminant
1476             then
1477                High :=
1478                  Make_Selected_Component (Loc,
1479                    Prefix        => New_Copy_Tree (Obj_Ref),
1480                    Selector_Name => Make_Identifier (Loc, Chars (High)));
1481             else
1482                High := New_Copy_Tree (High);
1483             end if;
1484
1485             return
1486               Make_Range (Loc,
1487                 Low_Bound  => Low,
1488                 High_Bound => High);
1489          end Build_Range;
1490
1491          ---------------------------
1492          -- Create_Index_And_Data --
1493          ---------------------------
1494
1495          procedure Create_Index_And_Data is
1496          begin
1497             if No (Index) and then No (Data) then
1498                declare
1499                   Count    : RE_Id;
1500                   Data_Typ : RE_Id;
1501                   Size     : Entity_Id;
1502
1503                begin
1504                   if Is_Protected_Type (Typ) then
1505                      Count    := RO_PE_Number_Of_Entries;
1506                      Data_Typ := RE_Protected_Entry_Names_Array;
1507                   else
1508                      Count    := RO_ST_Number_Of_Entries;
1509                      Data_Typ := RE_Task_Entry_Names_Array;
1510                   end if;
1511
1512                   --  Step 1: Generate the declaration of the index variable:
1513
1514                   --    Index : Entry_Index := 1;
1515
1516                   Index := Make_Temporary (Loc, 'I');
1517
1518                   Append_To (Stmts,
1519                     Make_Object_Declaration (Loc,
1520                       Defining_Identifier => Index,
1521                       Object_Definition   =>
1522                         New_Occurrence_Of (RTE (RE_Entry_Index), Loc),
1523                       Expression          => Make_Integer_Literal (Loc, 1)));
1524
1525                   --  Step 2: Generate the declaration of an array to house all
1526                   --  names:
1527
1528                   --    Size : constant Entry_Index := <Count> (Obj_Ref);
1529                   --    Data : aliased <Data_Typ> := (1 .. Size => null);
1530
1531                   Size := Make_Temporary (Loc, 'S');
1532
1533                   Append_To (Stmts,
1534                     Make_Object_Declaration (Loc,
1535                       Defining_Identifier => Size,
1536                       Constant_Present    => True,
1537                       Object_Definition   =>
1538                         New_Occurrence_Of (RTE (RE_Entry_Index), Loc),
1539                       Expression          =>
1540                         Make_Function_Call (Loc,
1541                           Name                   =>
1542                             New_Occurrence_Of (RTE (Count), Loc),
1543                           Parameter_Associations =>
1544                             New_List (Object_Reference))));
1545
1546                   Data := Make_Temporary (Loc, 'A');
1547
1548                   Append_To (Stmts,
1549                     Make_Object_Declaration (Loc,
1550                       Defining_Identifier => Data,
1551                       Aliased_Present     => True,
1552                       Object_Definition   =>
1553                         New_Occurrence_Of (RTE (Data_Typ), Loc),
1554                       Expression          =>
1555                         Make_Aggregate (Loc,
1556                           Component_Associations => New_List (
1557                             Make_Component_Association (Loc,
1558                               Choices    => New_List (
1559                                 Make_Range (Loc,
1560                                   Low_Bound  =>
1561                                     Make_Integer_Literal (Loc, 1),
1562                                   High_Bound =>
1563                                     New_Occurrence_Of (Size, Loc))),
1564                               Expression => Make_Null (Loc))))));
1565                end;
1566             end if;
1567          end Create_Index_And_Data;
1568
1569          ---------------------
1570          -- Increment_Index --
1571          ---------------------
1572
1573          function Increment_Index return Node_Id is
1574          begin
1575             return
1576               Make_Assignment_Statement (Loc,
1577                 Name       => New_Occurrence_Of (Index, Loc),
1578                 Expression =>
1579                   Make_Op_Add (Loc,
1580                     Left_Opnd  => New_Occurrence_Of (Index, Loc),
1581                     Right_Opnd => Make_Integer_Literal (Loc, 1)));
1582          end Increment_Index;
1583
1584          ----------------------
1585          -- Name_Declaration --
1586          ----------------------
1587
1588          function Name_Declaration (Def_Id : Entity_Id) return Node_Id is
1589          begin
1590             return
1591               Make_Object_Declaration (Loc,
1592                 Defining_Identifier => Def_Id,
1593                 Aliased_Present     => True,
1594                 Constant_Present    => True,
1595                 Object_Definition   =>
1596                   New_Occurrence_Of (Standard_String, Loc),
1597                 Expression          =>
1598                   Make_String_Literal (Loc, String_From_Name_Buffer));
1599          end Name_Declaration;
1600
1601          --------------------
1602          -- Set_Entry_Name --
1603          --------------------
1604
1605          function Set_Entry_Name (Def_Id : Entity_Id) return Node_Id is
1606          begin
1607             return
1608               Make_Assignment_Statement (Loc,
1609                 Name       =>
1610                   Make_Indexed_Component (Loc,
1611                     Prefix      => New_Occurrence_Of (Data, Loc),
1612                     Expressions => New_List (New_Occurrence_Of (Index, Loc))),
1613
1614                 Expression =>
1615                   Make_Attribute_Reference (Loc,
1616                     Prefix         => New_Occurrence_Of (Def_Id, Loc),
1617                     Attribute_Name => Name_Unchecked_Access));
1618          end Set_Entry_Name;
1619
1620          --  Local variables
1621
1622          Temp_Id  : Entity_Id;
1623          Subt_Def : Node_Id;
1624
1625       --  Start of processing for Build_Entry_Name
1626
1627       begin
1628          if Ekind (Comp_Id) = E_Entry_Family then
1629             Subt_Def := Discrete_Subtype_Definition (Parent (Comp_Id));
1630
1631             Create_Index_And_Data;
1632
1633             --  Step 1: Create the string name of the entry family.
1634             --  Generate:
1635             --    Temp : aliased constant String := "name ()";
1636
1637             Temp_Id := Make_Temporary (Loc, 'S');
1638             Get_Name_String (Chars (Comp_Id));
1639             Add_Char_To_Name_Buffer (' ');
1640             Add_Char_To_Name_Buffer ('(');
1641             Add_Char_To_Name_Buffer (')');
1642
1643             Append_To (Stmts, Name_Declaration (Temp_Id));
1644
1645             --  Generate:
1646             --    for Member in Family_Low .. Family_High loop
1647             --       Set_Entry_Name (...);
1648             --       Index := Index + 1;
1649             --    end loop;
1650
1651             Append_To (Stmts,
1652               Make_Loop_Statement (Loc,
1653                 Iteration_Scheme =>
1654                   Make_Iteration_Scheme (Loc,
1655                     Loop_Parameter_Specification =>
1656                       Make_Loop_Parameter_Specification (Loc,
1657                         Defining_Identifier         =>
1658                           Make_Temporary (Loc, 'L'),
1659                         Discrete_Subtype_Definition =>
1660                           Build_Range (Subt_Def))),
1661
1662                 Statements       => New_List (
1663                   Set_Entry_Name (Temp_Id),
1664                   Increment_Index),
1665                 End_Label        => Empty));
1666
1667          --  Entry
1668
1669          else
1670             Create_Index_And_Data;
1671
1672             --  Step 1: Create the string name of the entry. Generate:
1673             --    Temp : aliased constant String := "name";
1674
1675             Temp_Id := Make_Temporary (Loc, 'S');
1676             Get_Name_String (Chars (Comp_Id));
1677
1678             Append_To (Stmts, Name_Declaration (Temp_Id));
1679
1680             --  Step 2: Associate the string name with the underlying data
1681             --  structure.
1682
1683             Append_To (Stmts, Set_Entry_Name (Temp_Id));
1684             Append_To (Stmts, Increment_Index);
1685          end if;
1686       end Build_Entry_Name;
1687
1688       ----------------------
1689       -- Object_Reference --
1690       ----------------------
1691
1692       function Object_Reference return Node_Id is
1693          Conc_Typ : constant Entity_Id := Corresponding_Record_Type (Typ);
1694          Field    : Name_Id;
1695          Ref      : Node_Id;
1696
1697       begin
1698          if Is_Protected_Type (Typ) then
1699             Field := Name_uObject;
1700          else
1701             Field := Name_uTask_Id;
1702          end if;
1703
1704          Ref :=
1705            Make_Selected_Component (Loc,
1706              Prefix        =>
1707                Unchecked_Convert_To (Conc_Typ, New_Copy_Tree (Obj_Ref)),
1708              Selector_Name => Make_Identifier (Loc, Field));
1709
1710          if Is_Protected_Type (Typ) then
1711             Ref :=
1712               Make_Attribute_Reference (Loc,
1713                 Prefix         => Ref,
1714                 Attribute_Name => Name_Unchecked_Access);
1715          end if;
1716
1717          return Ref;
1718       end Object_Reference;
1719
1720       --  Local variables
1721
1722       Comp : Node_Id;
1723       Proc : RE_Id;
1724
1725    --  Start of processing for Build_Entry_Names
1726
1727    begin
1728       --  Retrieve the original concurrent type
1729
1730       if Is_Concurrent_Record_Type (Typ) then
1731          Typ := Corresponding_Concurrent_Type (Typ);
1732       end if;
1733
1734       pragma Assert (Is_Concurrent_Type (Typ));
1735
1736       --  Nothing to do if the type has no entries
1737
1738       if not Has_Entries (Typ) then
1739          return;
1740       end if;
1741
1742       --  Avoid generating entry names for a protected type with only one entry
1743
1744       if Is_Protected_Type (Typ)
1745         and then Find_Protection_Type (Base_Type (Typ)) /=
1746                    RTE (RE_Protection_Entries)
1747       then
1748          return;
1749       end if;
1750
1751       --  Step 1: Populate the array with statically generated strings denoting
1752       --  entries and entry family names.
1753
1754       Comp := First_Entity (Typ);
1755       while Present (Comp) loop
1756          if Comes_From_Source (Comp)
1757            and then Ekind_In (Comp, E_Entry, E_Entry_Family)
1758          then
1759             Build_Entry_Name (Comp);
1760          end if;
1761
1762          Next_Entity (Comp);
1763       end loop;
1764
1765       --  Step 2: Associate the array with the related concurrent object:
1766
1767       --    Set_Entry_Names (Obj_Ref, <Data>'Unchecked_Access);
1768
1769       if Present (Data) then
1770          if Is_Protected_Type (Typ) then
1771             Proc := RO_PE_Set_Entry_Names;
1772          else
1773             Proc := RO_ST_Set_Entry_Names;
1774          end if;
1775
1776          Append_To (Stmts,
1777            Make_Procedure_Call_Statement (Loc,
1778              Name                   => New_Occurrence_Of (RTE (Proc), Loc),
1779              Parameter_Associations => New_List (
1780                Object_Reference,
1781                Make_Attribute_Reference (Loc,
1782                  Prefix         => New_Occurrence_Of (Data, Loc),
1783                  Attribute_Name => Name_Unchecked_Access))));
1784       end if;
1785    end Build_Entry_Names;
1786
1787    ---------------------------
1788    -- Build_Parameter_Block --
1789    ---------------------------
1790
1791    function Build_Parameter_Block
1792      (Loc     : Source_Ptr;
1793       Actuals : List_Id;
1794       Formals : List_Id;
1795       Decls   : List_Id) return Entity_Id
1796    is
1797       Actual   : Entity_Id;
1798       Comp_Nam : Node_Id;
1799       Comps    : List_Id;
1800       Formal   : Entity_Id;
1801       Has_Comp : Boolean := False;
1802       Rec_Nam  : Node_Id;
1803
1804    begin
1805       Actual := First (Actuals);
1806       Comps  := New_List;
1807       Formal := Defining_Identifier (First (Formals));
1808
1809       while Present (Actual) loop
1810          if not Is_Controlling_Actual (Actual) then
1811
1812             --  Generate:
1813             --    type Ann is access all <actual-type>
1814
1815             Comp_Nam := Make_Temporary (Loc, 'A');
1816             Set_Is_Param_Block_Component_Type (Comp_Nam);
1817
1818             Append_To (Decls,
1819               Make_Full_Type_Declaration (Loc,
1820                 Defining_Identifier => Comp_Nam,
1821                 Type_Definition     =>
1822                   Make_Access_To_Object_Definition (Loc,
1823                     All_Present        => True,
1824                     Constant_Present   => Ekind (Formal) = E_In_Parameter,
1825                     Subtype_Indication =>
1826                       New_Occurrence_Of (Etype (Actual), Loc))));
1827
1828             --  Generate:
1829             --    Param : Ann;
1830
1831             Append_To (Comps,
1832               Make_Component_Declaration (Loc,
1833                 Defining_Identifier =>
1834                   Make_Defining_Identifier (Loc, Chars (Formal)),
1835                 Component_Definition =>
1836                   Make_Component_Definition (Loc,
1837                     Aliased_Present =>
1838                       False,
1839                     Subtype_Indication =>
1840                       New_Occurrence_Of (Comp_Nam, Loc))));
1841
1842             Has_Comp := True;
1843          end if;
1844
1845          Next_Actual (Actual);
1846          Next_Formal_With_Extras (Formal);
1847       end loop;
1848
1849       Rec_Nam := Make_Temporary (Loc, 'P');
1850
1851       if Has_Comp then
1852
1853          --  Generate:
1854          --    type Pnn is record
1855          --       Param1 : Ann1;
1856          --       ...
1857          --       ParamN : AnnN;
1858
1859          --  where Pnn is a parameter wrapping record, Param1 .. ParamN are
1860          --  the original parameter names and Ann1 .. AnnN are the access to
1861          --  actual types.
1862
1863          Append_To (Decls,
1864            Make_Full_Type_Declaration (Loc,
1865              Defining_Identifier =>
1866                Rec_Nam,
1867              Type_Definition =>
1868                Make_Record_Definition (Loc,
1869                  Component_List =>
1870                    Make_Component_List (Loc, Comps))));
1871       else
1872          --  Generate:
1873          --    type Pnn is null record;
1874
1875          Append_To (Decls,
1876            Make_Full_Type_Declaration (Loc,
1877              Defining_Identifier =>
1878                Rec_Nam,
1879              Type_Definition =>
1880                Make_Record_Definition (Loc,
1881                  Null_Present   => True,
1882                  Component_List => Empty)));
1883       end if;
1884
1885       return Rec_Nam;
1886    end Build_Parameter_Block;
1887
1888    --------------------------------------
1889    -- Build_Renamed_Formal_Declaration --
1890    --------------------------------------
1891
1892    function Build_Renamed_Formal_Declaration
1893      (New_F          : Entity_Id;
1894       Formal         : Entity_Id;
1895       Comp           : Entity_Id;
1896       Renamed_Formal : Node_Id) return Node_Id
1897    is
1898       Loc  : constant Source_Ptr := Sloc (New_F);
1899       Decl : Node_Id;
1900
1901    begin
1902       --  If the formal is a tagged incomplete type, it is already passed
1903       --  by reference, so it is sufficient to rename the pointer component
1904       --  that corresponds to the actual. Otherwise we need to dereference
1905       --  the pointer component to obtain the actual.
1906
1907       if Is_Incomplete_Type (Etype (Formal))
1908         and then Is_Tagged_Type (Etype (Formal))
1909       then
1910          Decl :=
1911            Make_Object_Renaming_Declaration (Loc,
1912              Defining_Identifier => New_F,
1913              Subtype_Mark        => New_Occurrence_Of (Etype (Comp), Loc),
1914              Name                => Renamed_Formal);
1915
1916       else
1917          Decl :=
1918            Make_Object_Renaming_Declaration (Loc,
1919              Defining_Identifier => New_F,
1920              Subtype_Mark        => New_Occurrence_Of (Etype (Formal), Loc),
1921              Name                =>
1922                Make_Explicit_Dereference (Loc, Renamed_Formal));
1923       end if;
1924
1925       return Decl;
1926    end Build_Renamed_Formal_Declaration;
1927
1928    -----------------------
1929    -- Build_PPC_Wrapper --
1930    -----------------------
1931
1932    procedure Build_PPC_Wrapper (E : Entity_Id; Decl : Node_Id) is
1933       Items      : constant Node_Id    := Contract (E);
1934       Loc        : constant Source_Ptr := Sloc (E);
1935       Synch_Type : constant Entity_Id  := Scope (E);
1936       Actuals    : List_Id;
1937       Decls      : List_Id;
1938       Entry_Call : Node_Id;
1939       Entry_Name : Node_Id;
1940       Params     : List_Id;
1941       Prag       : Node_Id;
1942       Synch_Id   : Entity_Id;
1943       Wrapper_Id : Entity_Id;
1944
1945    begin
1946       --  Only build the wrapper if entry has pre/postconditions
1947       --  Should this be done unconditionally instead ???
1948
1949       if Present (Items) then
1950          Prag := Pre_Post_Conditions (Items);
1951
1952          if No (Prag) then
1953             return;
1954          end if;
1955
1956          --  Transfer ppc pragmas to the declarations of the wrapper
1957
1958          Decls := New_List;
1959
1960          while Present (Prag) loop
1961             if Nam_In (Pragma_Name (Prag), Name_Precondition,
1962                                            Name_Postcondition)
1963             then
1964                Append (Relocate_Node (Prag), Decls);
1965                Set_Analyzed (Last (Decls), False);
1966             end if;
1967
1968             Prag := Next_Pragma (Prag);
1969          end loop;
1970       else
1971          return;
1972       end if;
1973
1974       Actuals  := New_List;
1975       Synch_Id :=
1976         Make_Defining_Identifier (Loc,
1977           Chars => New_External_Name (Chars (Scope (E)), 'A'));
1978
1979       --  First formal is synchronized object
1980
1981       Params := New_List (
1982         Make_Parameter_Specification (Loc,
1983           Defining_Identifier => Synch_Id,
1984           Out_Present         => True,
1985           In_Present          => True,
1986           Parameter_Type      => New_Occurrence_Of (Scope (E), Loc)));
1987
1988       Entry_Name :=
1989         Make_Selected_Component (Loc,
1990           Prefix        => New_Occurrence_Of (Synch_Id, Loc),
1991           Selector_Name => New_Occurrence_Of (E, Loc));
1992
1993       --  If entity is entry family, second formal is the corresponding index,
1994       --  and entry name is an indexed component.
1995
1996       if Ekind (E) = E_Entry_Family then
1997          declare
1998             Index : constant Entity_Id :=
1999                       Make_Defining_Identifier (Loc, Name_I);
2000          begin
2001             Append_To (Params,
2002               Make_Parameter_Specification (Loc,
2003                 Defining_Identifier => Index,
2004                 Parameter_Type      =>
2005                   New_Occurrence_Of (Entry_Index_Type (E), Loc)));
2006
2007             Entry_Name :=
2008               Make_Indexed_Component (Loc,
2009                 Prefix      => Entry_Name,
2010                 Expressions => New_List (New_Occurrence_Of (Index, Loc)));
2011          end;
2012       end if;
2013
2014       Entry_Call :=
2015         Make_Procedure_Call_Statement (Loc,
2016           Name                   => Entry_Name,
2017           Parameter_Associations => Actuals);
2018
2019       --  Now add formals that match those of the entry, and build actuals for
2020       --  the nested entry call.
2021
2022       declare
2023          Form      : Entity_Id;
2024          New_Form  : Entity_Id;
2025          Parm_Spec : Node_Id;
2026
2027       begin
2028          Form := First_Formal (E);
2029          while Present (Form) loop
2030             New_Form := Make_Defining_Identifier (Loc, Chars (Form));
2031             Parm_Spec :=
2032               Make_Parameter_Specification (Loc,
2033                 Defining_Identifier => New_Form,
2034                 Out_Present         => Out_Present (Parent (Form)),
2035                 In_Present          => In_Present  (Parent (Form)),
2036                 Parameter_Type      => New_Occurrence_Of (Etype (Form), Loc));
2037
2038             Append (Parm_Spec, Params);
2039             Append (New_Occurrence_Of (New_Form, Loc), Actuals);
2040             Next_Formal (Form);
2041          end loop;
2042       end;
2043
2044       --  Add renaming declarations for the discriminants of the enclosing
2045       --  type, which may be visible in the preconditions.
2046
2047       if Has_Discriminants (Synch_Type) then
2048          declare
2049             D : Entity_Id;
2050             Decl : Node_Id;
2051
2052          begin
2053             D := First_Discriminant (Synch_Type);
2054             while Present (D) loop
2055                Decl :=
2056                  Make_Object_Renaming_Declaration (Loc,
2057                    Defining_Identifier =>
2058                      Make_Defining_Identifier (Loc, Chars (D)),
2059                    Subtype_Mark        => New_Occurrence_Of (Etype (D), Loc),
2060                    Name                =>
2061                      Make_Selected_Component (Loc,
2062                        Prefix        => New_Occurrence_Of (Synch_Id, Loc),
2063                        Selector_Name => Make_Identifier (Loc, Chars (D))));
2064                Prepend (Decl, Decls);
2065                Next_Discriminant (D);
2066             end loop;
2067          end;
2068       end if;
2069
2070       Wrapper_Id :=
2071         Make_Defining_Identifier (Loc, New_External_Name (Chars (E), 'E'));
2072       Set_PPC_Wrapper (E, Wrapper_Id);
2073
2074       --  The wrapper body is analyzed when the enclosing type is frozen
2075
2076       Append_Freeze_Action (Defining_Entity (Decl),
2077         Make_Subprogram_Body (Loc,
2078           Specification              =>
2079             Make_Procedure_Specification (Loc,
2080               Defining_Unit_Name       => Wrapper_Id,
2081               Parameter_Specifications => Params),
2082           Declarations               => Decls,
2083           Handled_Statement_Sequence =>
2084             Make_Handled_Sequence_Of_Statements (Loc,
2085               Statements => New_List (Entry_Call))));
2086    end Build_PPC_Wrapper;
2087
2088    --------------------------
2089    -- Build_Wrapper_Bodies --
2090    --------------------------
2091
2092    procedure Build_Wrapper_Bodies
2093      (Loc : Source_Ptr;
2094       Typ : Entity_Id;
2095       N   : Node_Id)
2096    is
2097       Rec_Typ : Entity_Id;
2098
2099       function Build_Wrapper_Body
2100         (Loc     : Source_Ptr;
2101          Subp_Id : Entity_Id;
2102          Obj_Typ : Entity_Id;
2103          Formals : List_Id) return Node_Id;
2104       --  Ada 2005 (AI-345): Build the body that wraps a primitive operation
2105       --  associated with a protected or task type. Subp_Id is the subprogram
2106       --  name which will be wrapped. Obj_Typ is the type of the new formal
2107       --  parameter which handles dispatching and object notation. Formals are
2108       --  the original formals of Subp_Id which will be explicitly replicated.
2109
2110       ------------------------
2111       -- Build_Wrapper_Body --
2112       ------------------------
2113
2114       function Build_Wrapper_Body
2115         (Loc     : Source_Ptr;
2116          Subp_Id : Entity_Id;
2117          Obj_Typ : Entity_Id;
2118          Formals : List_Id) return Node_Id
2119       is
2120          Body_Spec : Node_Id;
2121
2122       begin
2123          Body_Spec := Build_Wrapper_Spec (Subp_Id, Obj_Typ, Formals);
2124
2125          --  The subprogram is not overriding or is not a primitive declared
2126          --  between two views.
2127
2128          if No (Body_Spec) then
2129             return Empty;
2130          end if;
2131
2132          declare
2133             Actuals    : List_Id := No_List;
2134             Conv_Id    : Node_Id;
2135             First_Form : Node_Id;
2136             Formal     : Node_Id;
2137             Nam        : Node_Id;
2138
2139          begin
2140             --  Map formals to actuals. Use the list built for the wrapper
2141             --  spec, skipping the object notation parameter.
2142
2143             First_Form := First (Parameter_Specifications (Body_Spec));
2144
2145             Formal := First_Form;
2146             Next (Formal);
2147
2148             if Present (Formal) then
2149                Actuals := New_List;
2150                while Present (Formal) loop
2151                   Append_To (Actuals,
2152                     Make_Identifier (Loc,
2153                       Chars => Chars (Defining_Identifier (Formal))));
2154                   Next (Formal);
2155                end loop;
2156             end if;
2157
2158             --  Special processing for primitives declared between a private
2159             --  type and its completion: the wrapper needs a properly typed
2160             --  parameter if the wrapped operation has a controlling first
2161             --  parameter. Note that this might not be the case for a function
2162             --  with a controlling result.
2163
2164             if Is_Private_Primitive_Subprogram (Subp_Id) then
2165                if No (Actuals) then
2166                   Actuals := New_List;
2167                end if;
2168
2169                if Is_Controlling_Formal (First_Formal (Subp_Id)) then
2170                   Prepend_To (Actuals,
2171                     Unchecked_Convert_To
2172                       (Corresponding_Concurrent_Type (Obj_Typ),
2173                        Make_Identifier (Loc, Name_uO)));
2174
2175                else
2176                   Prepend_To (Actuals,
2177                     Make_Identifier (Loc,
2178                       Chars => Chars (Defining_Identifier (First_Form))));
2179                end if;
2180
2181                Nam := New_Occurrence_Of (Subp_Id, Loc);
2182             else
2183                --  An access-to-variable object parameter requires an explicit
2184                --  dereference in the unchecked conversion. This case occurs
2185                --  when a protected entry wrapper must override an interface
2186                --  level procedure with interface access as first parameter.
2187
2188                --     O.all.Subp_Id (Formal_1, ..., Formal_N)
2189
2190                if Nkind (Parameter_Type (First_Form)) =
2191                     N_Access_Definition
2192                then
2193                   Conv_Id :=
2194                     Make_Explicit_Dereference (Loc,
2195                       Prefix => Make_Identifier (Loc, Name_uO));
2196                else
2197                   Conv_Id := Make_Identifier (Loc, Name_uO);
2198                end if;
2199
2200                Nam :=
2201                  Make_Selected_Component (Loc,
2202                    Prefix        =>
2203                      Unchecked_Convert_To
2204                        (Corresponding_Concurrent_Type (Obj_Typ), Conv_Id),
2205                    Selector_Name => New_Occurrence_Of (Subp_Id, Loc));
2206             end if;
2207
2208             --  Create the subprogram body. For a function, the call to the
2209             --  actual subprogram has to be converted to the corresponding
2210             --  record if it is a controlling result.
2211
2212             if Ekind (Subp_Id) = E_Function then
2213                declare
2214                   Res : Node_Id;
2215
2216                begin
2217                   Res :=
2218                      Make_Function_Call (Loc,
2219                        Name                   => Nam,
2220                        Parameter_Associations => Actuals);
2221
2222                   if Has_Controlling_Result (Subp_Id) then
2223                      Res :=
2224                        Unchecked_Convert_To
2225                          (Corresponding_Record_Type (Etype (Subp_Id)), Res);
2226                   end if;
2227
2228                   return
2229                     Make_Subprogram_Body (Loc,
2230                       Specification              => Body_Spec,
2231                       Declarations               => Empty_List,
2232                       Handled_Statement_Sequence =>
2233                         Make_Handled_Sequence_Of_Statements (Loc,
2234                           Statements => New_List (
2235                             Make_Simple_Return_Statement (Loc, Res))));
2236                end;
2237
2238             else
2239                return
2240                  Make_Subprogram_Body (Loc,
2241                    Specification              => Body_Spec,
2242                    Declarations               => Empty_List,
2243                    Handled_Statement_Sequence =>
2244                      Make_Handled_Sequence_Of_Statements (Loc,
2245                        Statements => New_List (
2246                          Make_Procedure_Call_Statement (Loc,
2247                            Name                   => Nam,
2248                            Parameter_Associations => Actuals))));
2249             end if;
2250          end;
2251       end Build_Wrapper_Body;
2252
2253    --  Start of processing for Build_Wrapper_Bodies
2254
2255    begin
2256       if Is_Concurrent_Type (Typ) then
2257          Rec_Typ := Corresponding_Record_Type (Typ);
2258       else
2259          Rec_Typ := Typ;
2260       end if;
2261
2262       --  Generate wrapper bodies for a concurrent type which implements an
2263       --  interface.
2264
2265       if Present (Interfaces (Rec_Typ)) then
2266          declare
2267             Insert_Nod : Node_Id;
2268             Prim       : Entity_Id;
2269             Prim_Elmt  : Elmt_Id;
2270             Prim_Decl  : Node_Id;
2271             Subp       : Entity_Id;
2272             Wrap_Body  : Node_Id;
2273             Wrap_Id    : Entity_Id;
2274
2275          begin
2276             Insert_Nod := N;
2277
2278             --  Examine all primitive operations of the corresponding record
2279             --  type, looking for wrapper specs. Generate bodies in order to
2280             --  complete them.
2281
2282             Prim_Elmt := First_Elmt (Primitive_Operations (Rec_Typ));
2283             while Present (Prim_Elmt) loop
2284                Prim := Node (Prim_Elmt);
2285
2286                if (Ekind (Prim) = E_Function
2287                     or else Ekind (Prim) = E_Procedure)
2288                  and then Is_Primitive_Wrapper (Prim)
2289                then
2290                   Subp := Wrapped_Entity (Prim);
2291                   Prim_Decl := Parent (Parent (Prim));
2292
2293                   Wrap_Body :=
2294                     Build_Wrapper_Body (Loc,
2295                       Subp_Id => Subp,
2296                       Obj_Typ => Rec_Typ,
2297                       Formals => Parameter_Specifications (Parent (Subp)));
2298                   Wrap_Id := Defining_Unit_Name (Specification (Wrap_Body));
2299
2300                   Set_Corresponding_Spec (Wrap_Body, Prim);
2301                   Set_Corresponding_Body (Prim_Decl, Wrap_Id);
2302
2303                   Insert_After (Insert_Nod, Wrap_Body);
2304                   Insert_Nod := Wrap_Body;
2305
2306                   Analyze (Wrap_Body);
2307                end if;
2308
2309                Next_Elmt (Prim_Elmt);
2310             end loop;
2311          end;
2312       end if;
2313    end Build_Wrapper_Bodies;
2314
2315    ------------------------
2316    -- Build_Wrapper_Spec --
2317    ------------------------
2318
2319    function Build_Wrapper_Spec
2320      (Subp_Id : Entity_Id;
2321       Obj_Typ : Entity_Id;
2322       Formals : List_Id) return Node_Id
2323    is
2324       Loc           : constant Source_Ptr := Sloc (Subp_Id);
2325       First_Param   : Node_Id;
2326       Iface         : Entity_Id;
2327       Iface_Elmt    : Elmt_Id;
2328       Iface_Op      : Entity_Id;
2329       Iface_Op_Elmt : Elmt_Id;
2330
2331       function Overriding_Possible
2332         (Iface_Op : Entity_Id;
2333          Wrapper  : Entity_Id) return Boolean;
2334       --  Determine whether a primitive operation can be overridden by Wrapper.
2335       --  Iface_Op is the candidate primitive operation of an interface type,
2336       --  Wrapper is the generated entry wrapper.
2337
2338       function Replicate_Formals
2339         (Loc     : Source_Ptr;
2340          Formals : List_Id) return List_Id;
2341       --  An explicit parameter replication is required due to the Is_Entry_
2342       --  Formal flag being set for all the formals of an entry. The explicit
2343       --  replication removes the flag that would otherwise cause a different
2344       --  path of analysis.
2345
2346       -------------------------
2347       -- Overriding_Possible --
2348       -------------------------
2349
2350       function Overriding_Possible
2351         (Iface_Op : Entity_Id;
2352          Wrapper  : Entity_Id) return Boolean
2353       is
2354          Iface_Op_Spec : constant Node_Id := Parent (Iface_Op);
2355          Wrapper_Spec  : constant Node_Id := Parent (Wrapper);
2356
2357          function Type_Conformant_Parameters
2358            (Iface_Op_Params : List_Id;
2359             Wrapper_Params  : List_Id) return Boolean;
2360          --  Determine whether the parameters of the generated entry wrapper
2361          --  and those of a primitive operation are type conformant. During
2362          --  this check, the first parameter of the primitive operation is
2363          --  skipped if it is a controlling argument: protected functions
2364          --  may have a controlling result.
2365
2366          --------------------------------
2367          -- Type_Conformant_Parameters --
2368          --------------------------------
2369
2370          function Type_Conformant_Parameters
2371            (Iface_Op_Params : List_Id;
2372             Wrapper_Params  : List_Id) return Boolean
2373          is
2374             Iface_Op_Param : Node_Id;
2375             Iface_Op_Typ   : Entity_Id;
2376             Wrapper_Param  : Node_Id;
2377             Wrapper_Typ    : Entity_Id;
2378
2379          begin
2380             --  Skip the first (controlling) parameter of primitive operation
2381
2382             Iface_Op_Param := First (Iface_Op_Params);
2383
2384             if Present (First_Formal (Iface_Op))
2385               and then Is_Controlling_Formal (First_Formal (Iface_Op))
2386             then
2387                Iface_Op_Param := Next (Iface_Op_Param);
2388             end if;
2389
2390             Wrapper_Param  := First (Wrapper_Params);
2391             while Present (Iface_Op_Param)
2392               and then Present (Wrapper_Param)
2393             loop
2394                Iface_Op_Typ := Find_Parameter_Type (Iface_Op_Param);
2395                Wrapper_Typ  := Find_Parameter_Type (Wrapper_Param);
2396
2397                --  The two parameters must be mode conformant
2398
2399                if not Conforming_Types
2400                         (Iface_Op_Typ, Wrapper_Typ, Mode_Conformant)
2401                then
2402                   return False;
2403                end if;
2404
2405                Next (Iface_Op_Param);
2406                Next (Wrapper_Param);
2407             end loop;
2408
2409             --  One of the lists is longer than the other
2410
2411             if Present (Iface_Op_Param) or else Present (Wrapper_Param) then
2412                return False;
2413             end if;
2414
2415             return True;
2416          end Type_Conformant_Parameters;
2417
2418       --  Start of processing for Overriding_Possible
2419
2420       begin
2421          if Chars (Iface_Op) /= Chars (Wrapper) then
2422             return False;
2423          end if;
2424
2425          --  If an inherited subprogram is implemented by a protected procedure
2426          --  or an entry, then the first parameter of the inherited subprogram
2427          --  must be of mode OUT or IN OUT, or access-to-variable parameter.
2428
2429          if Ekind (Iface_Op) = E_Procedure
2430            and then Present (Parameter_Specifications (Iface_Op_Spec))
2431          then
2432             declare
2433                Obj_Param : constant Node_Id :=
2434                              First (Parameter_Specifications (Iface_Op_Spec));
2435             begin
2436                if not Out_Present (Obj_Param)
2437                  and then Nkind (Parameter_Type (Obj_Param)) /=
2438                                                          N_Access_Definition
2439                then
2440                   return False;
2441                end if;
2442             end;
2443          end if;
2444
2445          return
2446            Type_Conformant_Parameters (
2447              Parameter_Specifications (Iface_Op_Spec),
2448              Parameter_Specifications (Wrapper_Spec));
2449       end Overriding_Possible;
2450
2451       -----------------------
2452       -- Replicate_Formals --
2453       -----------------------
2454
2455       function Replicate_Formals
2456         (Loc     : Source_Ptr;
2457          Formals : List_Id) return List_Id
2458       is
2459          New_Formals : constant List_Id := New_List;
2460          Formal      : Node_Id;
2461          Param_Type  : Node_Id;
2462
2463       begin
2464          Formal := First (Formals);
2465
2466          --  Skip the object parameter when dealing with primitives declared
2467          --  between two views.
2468
2469          if Is_Private_Primitive_Subprogram (Subp_Id)
2470            and then not Has_Controlling_Result (Subp_Id)
2471          then
2472             Formal := Next (Formal);
2473          end if;
2474
2475          while Present (Formal) loop
2476
2477             --  Create an explicit copy of the entry parameter
2478
2479             --  When creating the wrapper subprogram for a primitive operation
2480             --  of a protected interface we must construct an equivalent
2481             --  signature to that of the overriding operation. For regular
2482             --  parameters we can just use the type of the formal, but for
2483             --  access to subprogram parameters we need to reanalyze the
2484             --  parameter type to create local entities for the signature of
2485             --  the subprogram type. Using the entities of the overriding
2486             --  subprogram will result in out-of-scope errors in the back-end.
2487
2488             if Nkind (Parameter_Type (Formal)) = N_Access_Definition then
2489                Param_Type := Copy_Separate_Tree (Parameter_Type (Formal));
2490             else
2491                Param_Type :=
2492                  New_Occurrence_Of (Etype (Parameter_Type (Formal)), Loc);
2493             end if;
2494
2495             Append_To (New_Formals,
2496               Make_Parameter_Specification (Loc,
2497                 Defining_Identifier =>
2498                   Make_Defining_Identifier (Loc,
2499                     Chars                  => Chars
2500                                              (Defining_Identifier (Formal))),
2501                     In_Present             => In_Present  (Formal),
2502                     Out_Present            => Out_Present (Formal),
2503                     Null_Exclusion_Present => Null_Exclusion_Present (Formal),
2504                     Parameter_Type         => Param_Type));
2505
2506             Next (Formal);
2507          end loop;
2508
2509          return New_Formals;
2510       end Replicate_Formals;
2511
2512    --  Start of processing for Build_Wrapper_Spec
2513
2514    begin
2515       --  No point in building wrappers for untagged concurrent types
2516
2517       pragma Assert (Is_Tagged_Type (Obj_Typ));
2518
2519       --  An entry or a protected procedure can override a routine where the
2520       --  controlling formal is either IN OUT, OUT or is of access-to-variable
2521       --  type. Since the wrapper must have the exact same signature as that of
2522       --  the overridden subprogram, we try to find the overriding candidate
2523       --  and use its controlling formal.
2524
2525       First_Param := Empty;
2526
2527       --  Check every implemented interface
2528
2529       if Present (Interfaces (Obj_Typ)) then
2530          Iface_Elmt := First_Elmt (Interfaces (Obj_Typ));
2531          Search : while Present (Iface_Elmt) loop
2532             Iface := Node (Iface_Elmt);
2533
2534             --  Check every interface primitive
2535
2536             if Present (Primitive_Operations (Iface)) then
2537                Iface_Op_Elmt := First_Elmt (Primitive_Operations (Iface));
2538                while Present (Iface_Op_Elmt) loop
2539                   Iface_Op := Node (Iface_Op_Elmt);
2540
2541                   --  Ignore predefined primitives
2542
2543                   if not Is_Predefined_Dispatching_Operation (Iface_Op) then
2544                      Iface_Op := Ultimate_Alias (Iface_Op);
2545
2546                      --  The current primitive operation can be overridden by
2547                      --  the generated entry wrapper.
2548
2549                      if Overriding_Possible (Iface_Op, Subp_Id) then
2550                         First_Param :=
2551                           First (Parameter_Specifications (Parent (Iface_Op)));
2552
2553                         exit Search;
2554                      end if;
2555                   end if;
2556
2557                   Next_Elmt (Iface_Op_Elmt);
2558                end loop;
2559             end if;
2560
2561             Next_Elmt (Iface_Elmt);
2562          end loop Search;
2563       end if;
2564
2565       --  Ada 2012 (AI05-0090-1): If no interface primitive is covered by
2566       --  this subprogram and this is not a primitive declared between two
2567       --  views then force the generation of a wrapper. As an optimization,
2568       --  previous versions of the frontend avoid generating the wrapper;
2569       --  however, the wrapper facilitates locating and reporting an error
2570       --  when a duplicate declaration is found later. See example in
2571       --  AI05-0090-1.
2572
2573       if No (First_Param)
2574         and then not Is_Private_Primitive_Subprogram (Subp_Id)
2575       then
2576          if Is_Task_Type
2577               (Corresponding_Concurrent_Type (Obj_Typ))
2578          then
2579             First_Param :=
2580               Make_Parameter_Specification (Loc,
2581                 Defining_Identifier => Make_Defining_Identifier (Loc, Name_uO),
2582                 In_Present          => True,
2583                 Out_Present         => False,
2584                 Parameter_Type      => New_Occurrence_Of (Obj_Typ, Loc));
2585
2586          --  For entries and procedures of protected types the mode of
2587          --  the controlling argument must be in-out.
2588
2589          else
2590             First_Param :=
2591               Make_Parameter_Specification (Loc,
2592                 Defining_Identifier =>
2593                   Make_Defining_Identifier (Loc,
2594                     Chars => Name_uO),
2595                 In_Present     => True,
2596                 Out_Present    => (Ekind (Subp_Id) /= E_Function),
2597                 Parameter_Type => New_Occurrence_Of (Obj_Typ, Loc));
2598          end if;
2599       end if;
2600
2601       declare
2602          Wrapper_Id    : constant Entity_Id :=
2603                            Make_Defining_Identifier (Loc, Chars (Subp_Id));
2604          New_Formals   : List_Id;
2605          Obj_Param     : Node_Id;
2606          Obj_Param_Typ : Entity_Id;
2607
2608       begin
2609          --  Minimum decoration is needed to catch the entity in
2610          --  Sem_Ch6.Override_Dispatching_Operation.
2611
2612          if Ekind (Subp_Id) = E_Function then
2613             Set_Ekind (Wrapper_Id, E_Function);
2614          else
2615             Set_Ekind (Wrapper_Id, E_Procedure);
2616          end if;
2617
2618          Set_Is_Primitive_Wrapper (Wrapper_Id);
2619          Set_Wrapped_Entity       (Wrapper_Id, Subp_Id);
2620          Set_Is_Private_Primitive (Wrapper_Id,
2621            Is_Private_Primitive_Subprogram (Subp_Id));
2622
2623          --  Process the formals
2624
2625          New_Formals := Replicate_Formals (Loc, Formals);
2626
2627          --  A function with a controlling result and no first controlling
2628          --  formal needs no additional parameter.
2629
2630          if Has_Controlling_Result (Subp_Id)
2631            and then
2632              (No (First_Formal (Subp_Id))
2633                or else not Is_Controlling_Formal (First_Formal (Subp_Id)))
2634          then
2635             null;
2636
2637          --  Routine Subp_Id has been found to override an interface primitive.
2638          --  If the interface operation has an access parameter, create a copy
2639          --  of it, with the same null exclusion indicator if present.
2640
2641          elsif Present (First_Param) then
2642             if Nkind (Parameter_Type (First_Param)) = N_Access_Definition then
2643                Obj_Param_Typ :=
2644                  Make_Access_Definition (Loc,
2645                    Subtype_Mark           =>
2646                      New_Occurrence_Of (Obj_Typ, Loc),
2647                    Null_Exclusion_Present =>
2648                      Null_Exclusion_Present (Parameter_Type (First_Param)),
2649                    Constant_Present       =>
2650                      Constant_Present (Parameter_Type (First_Param)));
2651             else
2652                Obj_Param_Typ := New_Occurrence_Of (Obj_Typ, Loc);
2653             end if;
2654
2655             Obj_Param :=
2656               Make_Parameter_Specification (Loc,
2657                 Defining_Identifier =>
2658                   Make_Defining_Identifier (Loc,
2659                     Chars => Name_uO),
2660                 In_Present          => In_Present  (First_Param),
2661                 Out_Present         => Out_Present (First_Param),
2662                 Parameter_Type      => Obj_Param_Typ);
2663
2664             Prepend_To (New_Formals, Obj_Param);
2665
2666          --  If we are dealing with a primitive declared between two views,
2667          --  implemented by a synchronized operation, we need to create
2668          --  a default parameter. The mode of the parameter must match that
2669          --  of the primitive operation.
2670
2671          else
2672             pragma Assert (Is_Private_Primitive_Subprogram (Subp_Id));
2673             Obj_Param :=
2674               Make_Parameter_Specification (Loc,
2675                 Defining_Identifier =>
2676                   Make_Defining_Identifier (Loc, Name_uO),
2677                 In_Present  => In_Present (Parent (First_Entity (Subp_Id))),
2678                 Out_Present => Ekind (Subp_Id) /= E_Function,
2679                   Parameter_Type => New_Occurrence_Of (Obj_Typ, Loc));
2680             Prepend_To (New_Formals, Obj_Param);
2681          end if;
2682
2683          --  Build the final spec. If it is a function with a controlling
2684          --  result, it is a primitive operation of the corresponding
2685          --  record type, so mark the spec accordingly.
2686
2687          if Ekind (Subp_Id) = E_Function then
2688             declare
2689                Res_Def : Node_Id;
2690
2691             begin
2692                if Has_Controlling_Result (Subp_Id) then
2693                   Res_Def :=
2694                     New_Occurrence_Of
2695                       (Corresponding_Record_Type (Etype (Subp_Id)), Loc);
2696                else
2697                   Res_Def := New_Copy (Result_Definition (Parent (Subp_Id)));
2698                end if;
2699
2700                return
2701                  Make_Function_Specification (Loc,
2702                    Defining_Unit_Name       => Wrapper_Id,
2703                    Parameter_Specifications => New_Formals,
2704                    Result_Definition        => Res_Def);
2705             end;
2706          else
2707             return
2708               Make_Procedure_Specification (Loc,
2709                 Defining_Unit_Name       => Wrapper_Id,
2710                 Parameter_Specifications => New_Formals);
2711          end if;
2712       end;
2713    end Build_Wrapper_Spec;
2714
2715    -------------------------
2716    -- Build_Wrapper_Specs --
2717    -------------------------
2718
2719    procedure Build_Wrapper_Specs
2720      (Loc : Source_Ptr;
2721       Typ : Entity_Id;
2722       N   : in out Node_Id)
2723    is
2724       Def     : Node_Id;
2725       Rec_Typ : Entity_Id;
2726       procedure Scan_Declarations (L : List_Id);
2727       --  Common processing for visible and private declarations
2728       --  of a protected type.
2729
2730       procedure Scan_Declarations (L : List_Id) is
2731          Decl      : Node_Id;
2732          Wrap_Decl : Node_Id;
2733          Wrap_Spec : Node_Id;
2734
2735       begin
2736          if No (L) then
2737             return;
2738          end if;
2739
2740          Decl := First (L);
2741          while Present (Decl) loop
2742             Wrap_Spec := Empty;
2743
2744             if Nkind (Decl) = N_Entry_Declaration
2745               and then Ekind (Defining_Identifier (Decl)) = E_Entry
2746             then
2747                Wrap_Spec :=
2748                  Build_Wrapper_Spec
2749                    (Subp_Id => Defining_Identifier (Decl),
2750                     Obj_Typ => Rec_Typ,
2751                     Formals => Parameter_Specifications (Decl));
2752
2753             elsif Nkind (Decl) = N_Subprogram_Declaration then
2754                Wrap_Spec :=
2755                  Build_Wrapper_Spec
2756                    (Subp_Id => Defining_Unit_Name (Specification (Decl)),
2757                     Obj_Typ => Rec_Typ,
2758                     Formals =>
2759                       Parameter_Specifications (Specification (Decl)));
2760             end if;
2761
2762             if Present (Wrap_Spec) then
2763                Wrap_Decl :=
2764                  Make_Subprogram_Declaration (Loc,
2765                    Specification => Wrap_Spec);
2766
2767                Insert_After (N, Wrap_Decl);
2768                N := Wrap_Decl;
2769
2770                Analyze (Wrap_Decl);
2771             end if;
2772
2773             Next (Decl);
2774          end loop;
2775       end Scan_Declarations;
2776
2777       --  start of processing for Build_Wrapper_Specs
2778
2779    begin
2780       if Is_Protected_Type (Typ) then
2781          Def := Protected_Definition (Parent (Typ));
2782       else pragma Assert (Is_Task_Type (Typ));
2783          Def := Task_Definition (Parent (Typ));
2784       end if;
2785
2786       Rec_Typ := Corresponding_Record_Type (Typ);
2787
2788       --  Generate wrapper specs for a concurrent type which implements an
2789       --  interface. Operations in both the visible and private parts may
2790       --  implement progenitor operations.
2791
2792       if Present (Interfaces (Rec_Typ)) and then Present (Def) then
2793          Scan_Declarations (Visible_Declarations (Def));
2794          Scan_Declarations (Private_Declarations (Def));
2795       end if;
2796    end Build_Wrapper_Specs;
2797
2798    ---------------------------
2799    -- Build_Find_Body_Index --
2800    ---------------------------
2801
2802    function Build_Find_Body_Index (Typ : Entity_Id) return Node_Id is
2803       Loc   : constant Source_Ptr := Sloc (Typ);
2804       Ent   : Entity_Id;
2805       E_Typ : Entity_Id;
2806       Has_F : Boolean := False;
2807       Index : Nat;
2808       If_St : Node_Id := Empty;
2809       Lo    : Node_Id;
2810       Hi    : Node_Id;
2811       Decls : List_Id := New_List;
2812       Ret   : Node_Id;
2813       Spec  : Node_Id;
2814       Siz   : Node_Id := Empty;
2815
2816       procedure Add_If_Clause (Expr : Node_Id);
2817       --  Add test for range of current entry
2818
2819       function Convert_Discriminant_Ref (Bound : Node_Id) return Node_Id;
2820       --  If a bound of an entry is given by a discriminant, retrieve the
2821       --  actual value of the discriminant from the enclosing object.
2822
2823       -------------------
2824       -- Add_If_Clause --
2825       -------------------
2826
2827       procedure Add_If_Clause (Expr : Node_Id) is
2828          Cond  : Node_Id;
2829          Stats : constant List_Id :=
2830                    New_List (
2831                      Make_Simple_Return_Statement (Loc,
2832                        Expression => Make_Integer_Literal (Loc, Index + 1)));
2833
2834       begin
2835          --  Index for current entry body
2836
2837          Index := Index + 1;
2838
2839          --  Compute total length of entry queues so far
2840
2841          if No (Siz) then
2842             Siz := Expr;
2843          else
2844             Siz :=
2845               Make_Op_Add (Loc,
2846                 Left_Opnd  => Siz,
2847                 Right_Opnd => Expr);
2848          end if;
2849
2850          Cond :=
2851            Make_Op_Le (Loc,
2852              Left_Opnd  => Make_Identifier (Loc, Name_uE),
2853              Right_Opnd => Siz);
2854
2855          --  Map entry queue indexes in the range of the current family
2856          --  into the current index, that designates the entry body.
2857
2858          if No (If_St) then
2859             If_St :=
2860               Make_Implicit_If_Statement (Typ,
2861                 Condition       => Cond,
2862                 Then_Statements => Stats,
2863                 Elsif_Parts     => New_List);
2864             Ret := If_St;
2865
2866          else
2867             Append_To (Elsif_Parts (If_St),
2868               Make_Elsif_Part (Loc,
2869                 Condition => Cond,
2870                 Then_Statements => Stats));
2871          end if;
2872       end Add_If_Clause;
2873
2874       ------------------------------
2875       -- Convert_Discriminant_Ref --
2876       ------------------------------
2877
2878       function Convert_Discriminant_Ref (Bound : Node_Id) return Node_Id is
2879          B   : Node_Id;
2880
2881       begin
2882          if Is_Entity_Name (Bound)
2883            and then Ekind (Entity (Bound)) = E_Discriminant
2884          then
2885             B :=
2886               Make_Selected_Component (Loc,
2887                Prefix =>
2888                  Unchecked_Convert_To (Corresponding_Record_Type (Typ),
2889                    Make_Explicit_Dereference (Loc,
2890                      Make_Identifier (Loc, Name_uObject))),
2891                Selector_Name => Make_Identifier (Loc, Chars (Bound)));
2892             Set_Etype (B, Etype (Entity (Bound)));
2893          else
2894             B := New_Copy_Tree (Bound);
2895          end if;
2896
2897          return B;
2898       end Convert_Discriminant_Ref;
2899
2900    --  Start of processing for Build_Find_Body_Index
2901
2902    begin
2903       Spec := Build_Find_Body_Index_Spec (Typ);
2904
2905       Ent := First_Entity (Typ);
2906       while Present (Ent) loop
2907          if Ekind (Ent) = E_Entry_Family then
2908             Has_F := True;
2909             exit;
2910          end if;
2911
2912          Next_Entity (Ent);
2913       end loop;
2914
2915       if not Has_F then
2916
2917          --  If the protected type has no entry families, there is a one-one
2918          --  correspondence between entry queue and entry body.
2919
2920          Ret :=
2921            Make_Simple_Return_Statement (Loc,
2922              Expression => Make_Identifier (Loc, Name_uE));
2923
2924       else
2925          --  Suppose entries e1, e2, ... have size l1, l2, ... we generate
2926          --  the following:
2927
2928          --  if E <= l1 then return 1;
2929          --  elsif E <= l1 + l2 then return 2;
2930          --  ...
2931
2932          Index := 0;
2933          Siz   := Empty;
2934          Ent   := First_Entity (Typ);
2935
2936          Add_Object_Pointer (Loc, Typ, Decls);
2937
2938          while Present (Ent) loop
2939             if Ekind (Ent) = E_Entry then
2940                Add_If_Clause (Make_Integer_Literal (Loc, 1));
2941
2942             elsif Ekind (Ent) = E_Entry_Family then
2943                E_Typ := Etype (Discrete_Subtype_Definition (Parent (Ent)));
2944                Hi := Convert_Discriminant_Ref (Type_High_Bound (E_Typ));
2945                Lo := Convert_Discriminant_Ref (Type_Low_Bound  (E_Typ));
2946                Add_If_Clause (Family_Size (Loc, Hi, Lo, Typ, False));
2947             end if;
2948
2949             Next_Entity (Ent);
2950          end loop;
2951
2952          if Index = 1 then
2953             Decls := New_List;
2954             Ret :=
2955               Make_Simple_Return_Statement (Loc,
2956                 Expression => Make_Integer_Literal (Loc, 1));
2957
2958          elsif Nkind (Ret) = N_If_Statement then
2959
2960             --  Ranges are in increasing order, so last one doesn't need guard
2961
2962             declare
2963                Nod : constant Node_Id := Last (Elsif_Parts (Ret));
2964             begin
2965                Remove (Nod);
2966                Set_Else_Statements (Ret, Then_Statements (Nod));
2967             end;
2968          end if;
2969       end if;
2970
2971       return
2972         Make_Subprogram_Body (Loc,
2973           Specification              => Spec,
2974           Declarations               => Decls,
2975           Handled_Statement_Sequence =>
2976             Make_Handled_Sequence_Of_Statements (Loc,
2977               Statements => New_List (Ret)));
2978    end Build_Find_Body_Index;
2979
2980    --------------------------------
2981    -- Build_Find_Body_Index_Spec --
2982    --------------------------------
2983
2984    function Build_Find_Body_Index_Spec (Typ : Entity_Id) return Node_Id is
2985       Loc   : constant Source_Ptr := Sloc (Typ);
2986       Id    : constant Entity_Id :=
2987                Make_Defining_Identifier (Loc,
2988                  Chars => New_External_Name (Chars (Typ), 'F'));
2989       Parm1 : constant Entity_Id := Make_Defining_Identifier (Loc, Name_uO);
2990       Parm2 : constant Entity_Id := Make_Defining_Identifier (Loc, Name_uE);
2991
2992    begin
2993       return
2994         Make_Function_Specification (Loc,
2995           Defining_Unit_Name       => Id,
2996           Parameter_Specifications => New_List (
2997             Make_Parameter_Specification (Loc,
2998               Defining_Identifier => Parm1,
2999               Parameter_Type      =>
3000                 New_Occurrence_Of (RTE (RE_Address), Loc)),
3001
3002             Make_Parameter_Specification (Loc,
3003               Defining_Identifier => Parm2,
3004               Parameter_Type      =>
3005                 New_Occurrence_Of (RTE (RE_Protected_Entry_Index), Loc))),
3006
3007           Result_Definition        => New_Occurrence_Of (
3008             RTE (RE_Protected_Entry_Index), Loc));
3009    end Build_Find_Body_Index_Spec;
3010
3011    -----------------------------------------------
3012    -- Build_Lock_Free_Protected_Subprogram_Body --
3013    -----------------------------------------------
3014
3015    function Build_Lock_Free_Protected_Subprogram_Body
3016      (N           : Node_Id;
3017       Prot_Typ    : Node_Id;
3018       Unprot_Spec : Node_Id) return Node_Id
3019    is
3020       Actuals   : constant List_Id    := New_List;
3021       Loc       : constant Source_Ptr := Sloc (N);
3022       Spec      : constant Node_Id    := Specification (N);
3023       Unprot_Id : constant Entity_Id  := Defining_Unit_Name (Unprot_Spec);
3024       Formal    : Node_Id;
3025       Prot_Spec : Node_Id;
3026       Stmt      : Node_Id;
3027
3028    begin
3029       --  Create the protected version of the body
3030
3031       Prot_Spec :=
3032         Build_Protected_Sub_Specification (N, Prot_Typ, Protected_Mode);
3033
3034       --  Build the actual parameters which appear in the call to the
3035       --  unprotected version of the body.
3036
3037       Formal := First (Parameter_Specifications (Prot_Spec));
3038       while Present (Formal) loop
3039          Append_To (Actuals,
3040            Make_Identifier (Loc, Chars (Defining_Identifier (Formal))));
3041
3042          Next (Formal);
3043       end loop;
3044
3045       --  Function case, generate:
3046       --    return <Unprot_Func_Call>;
3047
3048       if Nkind (Spec) = N_Function_Specification then
3049          Stmt :=
3050            Make_Simple_Return_Statement (Loc,
3051              Expression =>
3052                Make_Function_Call (Loc,
3053                  Name                   =>
3054                    Make_Identifier (Loc, Chars (Unprot_Id)),
3055                  Parameter_Associations => Actuals));
3056
3057       --  Procedure case, call the unprotected version
3058
3059       else
3060          Stmt :=
3061            Make_Procedure_Call_Statement (Loc,
3062              Name                   =>
3063                Make_Identifier (Loc, Chars (Unprot_Id)),
3064              Parameter_Associations => Actuals);
3065       end if;
3066
3067       return
3068         Make_Subprogram_Body (Loc,
3069           Declarations               => Empty_List,
3070           Specification              => Prot_Spec,
3071           Handled_Statement_Sequence =>
3072             Make_Handled_Sequence_Of_Statements (Loc,
3073               Statements => New_List (Stmt)));
3074    end Build_Lock_Free_Protected_Subprogram_Body;
3075
3076    -------------------------------------------------
3077    -- Build_Lock_Free_Unprotected_Subprogram_Body --
3078    -------------------------------------------------
3079
3080    --  Procedures which meet the lock-free implementation requirements and
3081    --  reference a unique scalar component Comp are expanded in the following
3082    --  manner:
3083
3084    --    procedure P (...) is
3085    --       Expected_Comp : constant Comp_Type :=
3086    --                         Comp_Type
3087    --                           (System.Atomic_Primitives.Lock_Free_Read_N
3088    --                              (_Object.Comp'Address));
3089    --    begin
3090    --       loop
3091    --          declare
3092    --             <original declarations before the object renaming declaration
3093    --              of Comp>
3094    --
3095    --             Desired_Comp : Comp_Type := Expected_Comp;
3096    --             Comp         : Comp_Type renames Desired_Comp;
3097    --
3098    --             <original delarations after the object renaming declaration
3099    --              of Comp>
3100    --
3101    --          begin
3102    --             <original statements>
3103    --             exit when System.Atomic_Primitives.Lock_Free_Try_Write_N
3104    --                         (_Object.Comp'Address,
3105    --                          Interfaces.Unsigned_N (Expected_Comp),
3106    --                          Interfaces.Unsigned_N (Desired_Comp));
3107    --          end;
3108    --       end loop;
3109    --    end P;
3110
3111    --  Each return and raise statement of P is transformed into an atomic
3112    --  status check:
3113
3114    --    if System.Atomic_Primitives.Lock_Free_Try_Write_N
3115    --         (_Object.Comp'Address,
3116    --          Interfaces.Unsigned_N (Expected_Comp),
3117    --          Interfaces.Unsigned_N (Desired_Comp));
3118    --    then
3119    --       <original statement>
3120    --    else
3121    --       goto L0;
3122    --    end if;
3123
3124    --  Functions which meet the lock-free implementation requirements and
3125    --  reference a unique scalar component Comp are expanded in the following
3126    --  manner:
3127
3128    --    function F (...) return ... is
3129    --       <original declarations before the object renaming declaration
3130    --        of Comp>
3131    --
3132    --       Expected_Comp : constant Comp_Type :=
3133    --                         Comp_Type
3134    --                           (System.Atomic_Primitives.Lock_Free_Read_N
3135    --                              (_Object.Comp'Address));
3136    --       Comp          : Comp_Type renames Expected_Comp;
3137    --
3138    --       <original delarations after the object renaming declaration of
3139    --        Comp>
3140    --
3141    --    begin
3142    --       <original statements>
3143    --    end F;
3144
3145    function Build_Lock_Free_Unprotected_Subprogram_Body
3146      (N        : Node_Id;
3147       Prot_Typ : Node_Id) return Node_Id
3148    is
3149       function Referenced_Component (N : Node_Id) return Entity_Id;
3150       --  Subprograms which meet the lock-free implementation criteria are
3151       --  allowed to reference only one unique component. Return the prival
3152       --  of the said component.
3153
3154       --------------------------
3155       -- Referenced_Component --
3156       --------------------------
3157
3158       function Referenced_Component (N : Node_Id) return Entity_Id is
3159          Comp        : Entity_Id;
3160          Decl        : Node_Id;
3161          Source_Comp : Entity_Id := Empty;
3162
3163       begin
3164          --  Find the unique source component which N references in its
3165          --  statements.
3166
3167          for Index in 1 .. Lock_Free_Subprogram_Table.Last loop
3168             declare
3169                Element : Lock_Free_Subprogram renames
3170                          Lock_Free_Subprogram_Table.Table (Index);
3171             begin
3172                if Element.Sub_Body = N then
3173                   Source_Comp := Element.Comp_Id;
3174                   exit;
3175                end if;
3176             end;
3177          end loop;
3178
3179          if No (Source_Comp) then
3180             return Empty;
3181          end if;
3182
3183          --  Find the prival which corresponds to the source component within
3184          --  the declarations of N.
3185
3186          Decl := First (Declarations (N));
3187          while Present (Decl) loop
3188
3189             --  Privals appear as object renamings
3190
3191             if Nkind (Decl) = N_Object_Renaming_Declaration then
3192                Comp := Defining_Identifier (Decl);
3193
3194                if Present (Prival_Link (Comp))
3195                  and then Prival_Link (Comp) = Source_Comp
3196                then
3197                   return Comp;
3198                end if;
3199             end if;
3200
3201             Next (Decl);
3202          end loop;
3203
3204          return Empty;
3205       end Referenced_Component;
3206
3207       --  Local variables
3208
3209       Comp          : constant Entity_Id  := Referenced_Component (N);
3210       Loc           : constant Source_Ptr := Sloc (N);
3211       Hand_Stmt_Seq : Node_Id             := Handled_Statement_Sequence (N);
3212       Decls         : List_Id             := Declarations (N);
3213
3214    --  Start of processing for Build_Lock_Free_Unprotected_Subprogram_Body
3215
3216    begin
3217       --  Add renamings for the protection object, discriminals, privals and
3218       --  the entry index constant for use by debugger.
3219
3220       Debug_Private_Data_Declarations (Decls);
3221
3222       --  Perform the lock-free expansion when the subprogram references a
3223       --  protected component.
3224
3225       if Present (Comp) then
3226          Protected_Component_Ref : declare
3227             Comp_Decl    : constant Node_Id   := Parent (Comp);
3228             Comp_Sel_Nam : constant Node_Id   := Name (Comp_Decl);
3229             Comp_Type    : constant Entity_Id := Etype (Comp);
3230
3231             Is_Procedure : constant Boolean :=
3232                              Ekind (Corresponding_Spec (N)) = E_Procedure;
3233             --  Indicates if N is a protected procedure body
3234
3235             Block_Decls   : List_Id;
3236             Try_Write     : Entity_Id;
3237             Desired_Comp  : Entity_Id;
3238             Decl          : Node_Id;
3239             Label         : Node_Id;
3240             Label_Id      : Entity_Id := Empty;
3241             Read          : Entity_Id;
3242             Expected_Comp : Entity_Id;
3243             Stmt          : Node_Id;
3244             Stmts         : List_Id :=
3245                               New_Copy_List (Statements (Hand_Stmt_Seq));
3246             Typ_Size      : Int;
3247             Unsigned      : Entity_Id;
3248
3249             function Process_Node (N : Node_Id) return Traverse_Result;
3250             --  Transform a single node if it is a return statement, a raise
3251             --  statement or a reference to Comp.
3252
3253             procedure Process_Stmts (Stmts : List_Id);
3254             --  Given a statement sequence Stmts, wrap any return or raise
3255             --  statements in the following manner:
3256             --
3257             --    if System.Atomic_Primitives.Lock_Free_Try_Write_N
3258             --         (_Object.Comp'Address,
3259             --          Interfaces.Unsigned_N (Expected_Comp),
3260             --          Interfaces.Unsigned_N (Desired_Comp))
3261             --    then
3262             --       <Stmt>;
3263             --    else
3264             --       goto L0;
3265             --    end if;
3266
3267             ------------------
3268             -- Process_Node --
3269             ------------------
3270
3271             function Process_Node (N : Node_Id) return Traverse_Result is
3272
3273                procedure Wrap_Statement (Stmt : Node_Id);
3274                --  Wrap an arbitrary statement inside an if statement where the
3275                --  condition does an atomic check on the state of the object.
3276
3277                --------------------
3278                -- Wrap_Statement --
3279                --------------------
3280
3281                procedure Wrap_Statement (Stmt : Node_Id) is
3282                begin
3283                   --  The first time through, create the declaration of a label
3284                   --  which is used to skip the remainder of source statements
3285                   --  if the state of the object has changed.
3286
3287                   if No (Label_Id) then
3288                      Label_Id :=
3289                        Make_Identifier (Loc, New_External_Name ('L', 0));
3290                      Set_Entity (Label_Id,
3291                        Make_Defining_Identifier (Loc, Chars (Label_Id)));
3292                   end if;
3293
3294                   --  Generate:
3295                   --    if System.Atomic_Primitives.Lock_Free_Try_Write_N
3296                   --         (_Object.Comp'Address,
3297                   --          Interfaces.Unsigned_N (Expected_Comp),
3298                   --          Interfaces.Unsigned_N (Desired_Comp))
3299                   --    then
3300                   --       <Stmt>;
3301                   --    else
3302                   --       goto L0;
3303                   --    end if;
3304
3305                   Rewrite (Stmt,
3306                     Make_Implicit_If_Statement (N,
3307                       Condition       =>
3308                         Make_Function_Call (Loc,
3309                           Name                   =>
3310                             New_Occurrence_Of (Try_Write, Loc),
3311                           Parameter_Associations => New_List (
3312                             Make_Attribute_Reference (Loc,
3313                               Prefix         => Relocate_Node (Comp_Sel_Nam),
3314                               Attribute_Name => Name_Address),
3315
3316                             Unchecked_Convert_To (Unsigned,
3317                               New_Occurrence_Of (Expected_Comp, Loc)),
3318
3319                             Unchecked_Convert_To (Unsigned,
3320                               New_Occurrence_Of (Desired_Comp, Loc)))),
3321
3322                       Then_Statements => New_List (Relocate_Node (Stmt)),
3323
3324                       Else_Statements => New_List (
3325                         Make_Goto_Statement (Loc,
3326                           Name =>
3327                             New_Occurrence_Of (Entity (Label_Id), Loc)))));
3328                end Wrap_Statement;
3329
3330             --  Start of processing for Process_Node
3331
3332             begin
3333                --  Wrap each return and raise statement that appear inside a
3334                --  procedure. Skip the last return statement which is added by
3335                --  default since it is transformed into an exit statement.
3336
3337                if Is_Procedure
3338                  and then ((Nkind (N) = N_Simple_Return_Statement
3339                              and then N /= Last (Stmts))
3340                             or else Nkind (N) = N_Extended_Return_Statement
3341                             or else (Nkind_In (N, N_Raise_Constraint_Error,
3342                                                   N_Raise_Program_Error,
3343                                                   N_Raise_Statement,
3344                                                   N_Raise_Storage_Error)
3345                                       and then Comes_From_Source (N)))
3346                then
3347                   Wrap_Statement (N);
3348                   return Skip;
3349                end if;
3350
3351                --  Force reanalysis
3352
3353                Set_Analyzed (N, False);
3354
3355                return OK;
3356             end Process_Node;
3357
3358             procedure Process_Nodes is new Traverse_Proc (Process_Node);
3359
3360             -------------------
3361             -- Process_Stmts --
3362             -------------------
3363
3364             procedure Process_Stmts (Stmts : List_Id) is
3365                Stmt : Node_Id;
3366             begin
3367                Stmt := First (Stmts);
3368                while Present (Stmt) loop
3369                   Process_Nodes (Stmt);
3370                   Next (Stmt);
3371                end loop;
3372             end Process_Stmts;
3373
3374          --  Start of processing for Protected_Component_Ref
3375
3376          begin
3377             --  Get the type size
3378
3379             if Known_Static_Esize (Comp_Type) then
3380                Typ_Size := UI_To_Int (Esize (Comp_Type));
3381
3382             --  If the Esize (Object_Size) is unknown at compile time, look at
3383             --  the RM_Size (Value_Size) since it may have been set by an
3384             --  explicit representation clause.
3385
3386             elsif Known_Static_RM_Size (Comp_Type) then
3387                Typ_Size := UI_To_Int (RM_Size (Comp_Type));
3388
3389             --  Should not happen since this has already been checked in
3390             --  Allows_Lock_Free_Implementation (see Sem_Ch9).
3391
3392             else
3393                raise Program_Error;
3394             end if;
3395
3396             --  Retrieve all relevant atomic routines and types
3397
3398             case Typ_Size is
3399                when 8 =>
3400                   Try_Write := RTE (RE_Lock_Free_Try_Write_8);
3401                   Read      := RTE (RE_Lock_Free_Read_8);
3402                   Unsigned  := RTE (RE_Uint8);
3403
3404                when 16 =>
3405                   Try_Write := RTE (RE_Lock_Free_Try_Write_16);
3406                   Read      := RTE (RE_Lock_Free_Read_16);
3407                   Unsigned  := RTE (RE_Uint16);
3408
3409                when 32 =>
3410                   Try_Write := RTE (RE_Lock_Free_Try_Write_32);
3411                   Read      := RTE (RE_Lock_Free_Read_32);
3412                   Unsigned  := RTE (RE_Uint32);
3413
3414                when 64 =>
3415                   Try_Write := RTE (RE_Lock_Free_Try_Write_64);
3416                   Read      := RTE (RE_Lock_Free_Read_64);
3417                   Unsigned  := RTE (RE_Uint64);
3418
3419                when others =>
3420                   raise Program_Error;
3421             end case;
3422
3423             --  Generate:
3424             --  Expected_Comp : constant Comp_Type :=
3425             --                    Comp_Type
3426             --                      (System.Atomic_Primitives.Lock_Free_Read_N
3427             --                         (_Object.Comp'Address));
3428
3429             Expected_Comp :=
3430               Make_Defining_Identifier (Loc,
3431                 New_External_Name (Chars (Comp), Suffix => "_saved"));
3432
3433             Decl :=
3434               Make_Object_Declaration (Loc,
3435                 Defining_Identifier => Expected_Comp,
3436                 Object_Definition   => New_Occurrence_Of (Comp_Type, Loc),
3437                 Constant_Present    => True,
3438                 Expression          =>
3439                   Unchecked_Convert_To (Comp_Type,
3440                     Make_Function_Call (Loc,
3441                       Name                   => New_Occurrence_Of (Read, Loc),
3442                       Parameter_Associations => New_List (
3443                         Make_Attribute_Reference (Loc,
3444                           Prefix         => Relocate_Node (Comp_Sel_Nam),
3445                           Attribute_Name => Name_Address)))));
3446
3447             --  Protected procedures
3448
3449             if Is_Procedure then
3450                --  Move the original declarations inside the generated block
3451
3452                Block_Decls := Decls;
3453
3454                --  Reset the declarations list of the protected procedure to
3455                --  contain only Decl.
3456
3457                Decls := New_List (Decl);
3458
3459                --  Generate:
3460                --    Desired_Comp : Comp_Type := Expected_Comp;
3461
3462                Desired_Comp :=
3463                  Make_Defining_Identifier (Loc,
3464                    New_External_Name (Chars (Comp), Suffix => "_current"));
3465
3466                --  Insert the declarations of Expected_Comp and Desired_Comp in
3467                --  the block declarations right before the renaming of the
3468                --  protected component.
3469
3470                Insert_Before (Comp_Decl,
3471                  Make_Object_Declaration (Loc,
3472                    Defining_Identifier => Desired_Comp,
3473                    Object_Definition   => New_Occurrence_Of (Comp_Type, Loc),
3474                    Expression          =>
3475                      New_Occurrence_Of (Expected_Comp, Loc)));
3476
3477             --  Protected function
3478
3479             else
3480                Desired_Comp := Expected_Comp;
3481
3482                --  Insert the declaration of Expected_Comp in the function
3483                --  declarations right before the renaming of the protected
3484                --  component.
3485
3486                Insert_Before (Comp_Decl, Decl);
3487             end if;
3488
3489             --  Rewrite the protected component renaming declaration to be a
3490             --  renaming of Desired_Comp.
3491
3492             --  Generate:
3493             --    Comp : Comp_Type renames Desired_Comp;
3494
3495             Rewrite (Comp_Decl,
3496               Make_Object_Renaming_Declaration (Loc,
3497                 Defining_Identifier =>
3498                   Defining_Identifier (Comp_Decl),
3499                 Subtype_Mark        =>
3500                   New_Occurrence_Of (Comp_Type, Loc),
3501                 Name                =>
3502                   New_Occurrence_Of (Desired_Comp, Loc)));
3503
3504             --  Wrap any return or raise statements in Stmts in same the manner
3505             --  described in Process_Stmts.
3506
3507             Process_Stmts (Stmts);
3508
3509             --  Generate:
3510             --    exit when System.Atomic_Primitives.Lock_Free_Try_Write_N
3511             --                (_Object.Comp'Address,
3512             --                 Interfaces.Unsigned_N (Expected_Comp),
3513             --                 Interfaces.Unsigned_N (Desired_Comp))
3514
3515             if Is_Procedure then
3516                Stmt :=
3517                  Make_Exit_Statement (Loc,
3518                    Condition =>
3519                      Make_Function_Call (Loc,
3520                        Name                   =>
3521                          New_Occurrence_Of (Try_Write, Loc),
3522                        Parameter_Associations => New_List (
3523                          Make_Attribute_Reference (Loc,
3524                            Prefix         => Relocate_Node (Comp_Sel_Nam),
3525                            Attribute_Name => Name_Address),
3526
3527                          Unchecked_Convert_To (Unsigned,
3528                            New_Occurrence_Of (Expected_Comp, Loc)),
3529
3530                          Unchecked_Convert_To (Unsigned,
3531                            New_Occurrence_Of (Desired_Comp, Loc)))));
3532
3533                --  Small optimization: transform the default return statement
3534                --  of a procedure into the atomic exit statement.
3535
3536                if Nkind (Last (Stmts)) = N_Simple_Return_Statement then
3537                   Rewrite (Last (Stmts), Stmt);
3538                else
3539                   Append_To (Stmts, Stmt);
3540                end if;
3541             end if;
3542
3543             --  Create the declaration of the label used to skip the rest of
3544             --  the source statements when the object state changes.
3545
3546             if Present (Label_Id) then
3547                Label := Make_Label (Loc, Label_Id);
3548                Append_To (Decls,
3549                  Make_Implicit_Label_Declaration (Loc,
3550                    Defining_Identifier => Entity (Label_Id),
3551                    Label_Construct     => Label));
3552                Append_To (Stmts, Label);
3553             end if;
3554
3555             --  Generate:
3556             --    loop
3557             --       declare
3558             --          <Decls>
3559             --       begin
3560             --          <Stmts>
3561             --       end;
3562             --    end loop;
3563
3564             if Is_Procedure then
3565                Stmts :=
3566                  New_List (
3567                    Make_Loop_Statement (Loc,
3568                      Statements => New_List (
3569                        Make_Block_Statement (Loc,
3570                          Declarations               => Block_Decls,
3571                          Handled_Statement_Sequence =>
3572                            Make_Handled_Sequence_Of_Statements (Loc,
3573                              Statements => Stmts))),
3574                      End_Label  => Empty));
3575             end if;
3576
3577             Hand_Stmt_Seq :=
3578               Make_Handled_Sequence_Of_Statements (Loc, Statements => Stmts);
3579          end Protected_Component_Ref;
3580       end if;
3581
3582       --  Make an unprotected version of the subprogram for use within the same
3583       --  object, with new name and extra parameter representing the object.
3584
3585       return
3586         Make_Subprogram_Body (Loc,
3587           Specification              =>
3588             Build_Protected_Sub_Specification (N, Prot_Typ, Unprotected_Mode),
3589           Declarations               => Decls,
3590           Handled_Statement_Sequence => Hand_Stmt_Seq);
3591    end Build_Lock_Free_Unprotected_Subprogram_Body;
3592
3593    -------------------------
3594    -- Build_Master_Entity --
3595    -------------------------
3596
3597    procedure Build_Master_Entity (Obj_Or_Typ : Entity_Id) is
3598       Loc        : constant Source_Ptr := Sloc (Obj_Or_Typ);
3599       Context    : Node_Id;
3600       Context_Id : Entity_Id;
3601       Decl       : Node_Id;
3602       Decls      : List_Id;
3603       Par        : Node_Id;
3604
3605    begin
3606       if Is_Itype (Obj_Or_Typ) then
3607          Par := Associated_Node_For_Itype (Obj_Or_Typ);
3608       else
3609          Par := Parent (Obj_Or_Typ);
3610       end if;
3611
3612       --  When creating a master for a record component which is either a task
3613       --  or access-to-task, the enclosing record is the master scope and the
3614       --  proper insertion point is the component list.
3615
3616       if Is_Record_Type (Current_Scope) then
3617          Context    := Par;
3618          Context_Id := Current_Scope;
3619          Decls      := List_Containing (Context);
3620
3621       --  Default case for object declarations and access types. Note that the
3622       --  context is updated to the nearest enclosing body, block, package or
3623       --  return statement.
3624
3625       else
3626          Find_Enclosing_Context (Par, Context, Context_Id, Decls);
3627       end if;
3628
3629       --  Do not create a master if one already exists or there is no task
3630       --  hierarchy.
3631
3632       if Has_Master_Entity (Context_Id)
3633         or else Restriction_Active (No_Task_Hierarchy)
3634       then
3635          return;
3636       end if;
3637
3638       --  Create a master, generate:
3639       --    _Master : constant Master_Id := Current_Master.all;
3640
3641       Decl :=
3642         Make_Object_Declaration (Loc,
3643           Defining_Identifier =>
3644             Make_Defining_Identifier (Loc, Name_uMaster),
3645           Constant_Present    => True,
3646           Object_Definition   => New_Occurrence_Of (RTE (RE_Master_Id), Loc),
3647           Expression          =>
3648             Make_Explicit_Dereference (Loc,
3649               New_Occurrence_Of (RTE (RE_Current_Master), Loc)));
3650
3651       --  The master is inserted at the start of the declarative list of the
3652       --  context.
3653
3654       Prepend_To (Decls, Decl);
3655
3656       --  In certain cases where transient scopes are involved, the immediate
3657       --  scope is not always the proper master scope. Ensure that the master
3658       --  declaration and entity appear in the same context.
3659
3660       if Context_Id /= Current_Scope then
3661          Push_Scope (Context_Id);
3662          Analyze (Decl);
3663          Pop_Scope;
3664       else
3665          Analyze (Decl);
3666       end if;
3667
3668       --  Mark the enclosing scope and its associated construct as being task
3669       --  masters.
3670
3671       Set_Has_Master_Entity (Context_Id);
3672
3673       while Present (Context)
3674         and then Nkind (Context) /= N_Compilation_Unit
3675       loop
3676          if Nkind_In (Context, N_Block_Statement,
3677                                N_Subprogram_Body,
3678                                N_Task_Body)
3679          then
3680             Set_Is_Task_Master (Context);
3681             exit;
3682
3683          elsif Nkind (Parent (Context)) = N_Subunit then
3684             Context := Corresponding_Stub (Parent (Context));
3685          end if;
3686
3687          Context := Parent (Context);
3688       end loop;
3689    end Build_Master_Entity;
3690
3691    ---------------------------
3692    -- Build_Master_Renaming --
3693    ---------------------------
3694
3695    procedure Build_Master_Renaming
3696      (Ptr_Typ : Entity_Id;
3697       Ins_Nod : Node_Id := Empty)
3698    is
3699       Loc         : constant Source_Ptr := Sloc (Ptr_Typ);
3700       Context     : Node_Id;
3701       Master_Decl : Node_Id;
3702       Master_Id   : Entity_Id;
3703
3704    begin
3705       --  Nothing to do if there is no task hierarchy
3706
3707       if Restriction_Active (No_Task_Hierarchy) then
3708          return;
3709       end if;
3710
3711       --  Determine the proper context to insert the master renaming
3712
3713       if Present (Ins_Nod) then
3714          Context := Ins_Nod;
3715       elsif Is_Itype (Ptr_Typ) then
3716          Context := Associated_Node_For_Itype (Ptr_Typ);
3717       else
3718          Context := Parent (Ptr_Typ);
3719       end if;
3720
3721       --  Generate:
3722       --    <Ptr_Typ>M : Master_Id renames _Master;
3723
3724       Master_Id :=
3725         Make_Defining_Identifier (Loc,
3726           New_External_Name (Chars (Ptr_Typ), 'M'));
3727
3728       Master_Decl :=
3729         Make_Object_Renaming_Declaration (Loc,
3730           Defining_Identifier => Master_Id,
3731           Subtype_Mark        => New_Occurrence_Of (RTE (RE_Master_Id), Loc),
3732           Name                => Make_Identifier (Loc, Name_uMaster));
3733
3734       Insert_Action (Context, Master_Decl);
3735
3736       --  The renamed master now services the access type
3737
3738       Set_Master_Id (Ptr_Typ, Master_Id);
3739    end Build_Master_Renaming;
3740
3741    -----------------------------------------
3742    -- Build_Private_Protected_Declaration --
3743    -----------------------------------------
3744
3745    function Build_Private_Protected_Declaration
3746      (N : Node_Id) return Entity_Id
3747    is
3748       Loc      : constant Source_Ptr := Sloc (N);
3749       Body_Id  : constant Entity_Id := Defining_Entity (N);
3750       Decl     : Node_Id;
3751       Plist    : List_Id;
3752       Formal   : Entity_Id;
3753       New_Spec : Node_Id;
3754       Spec_Id  : Entity_Id;
3755
3756    begin
3757       Formal := First_Formal (Body_Id);
3758
3759       --  The protected operation always has at least one formal, namely the
3760       --  object itself, but it is only placed in the parameter list if
3761       --  expansion is enabled.
3762
3763       if Present (Formal) or else Expander_Active then
3764          Plist := Copy_Parameter_List (Body_Id);
3765       else
3766          Plist := No_List;
3767       end if;
3768
3769       if Nkind (Specification (N)) = N_Procedure_Specification then
3770          New_Spec :=
3771            Make_Procedure_Specification (Loc,
3772               Defining_Unit_Name       =>
3773                 Make_Defining_Identifier (Sloc (Body_Id),
3774                   Chars => Chars (Body_Id)),
3775               Parameter_Specifications =>
3776                 Plist);
3777       else
3778          New_Spec :=
3779            Make_Function_Specification (Loc,
3780              Defining_Unit_Name       =>
3781                Make_Defining_Identifier (Sloc (Body_Id),
3782                  Chars => Chars (Body_Id)),
3783              Parameter_Specifications => Plist,
3784              Result_Definition        =>
3785                New_Occurrence_Of (Etype (Body_Id), Loc));
3786       end if;
3787
3788       Decl := Make_Subprogram_Declaration (Loc, Specification => New_Spec);
3789       Insert_Before (N, Decl);
3790       Spec_Id := Defining_Unit_Name (New_Spec);
3791
3792       --  Indicate that the entity comes from source, to ensure that cross-
3793       --  reference information is properly generated. The body itself is
3794       --  rewritten during expansion, and the body entity will not appear in
3795       --  calls to the operation.
3796
3797       Set_Comes_From_Source (Spec_Id, True);
3798       Analyze (Decl);
3799       Set_Has_Completion (Spec_Id);
3800       Set_Convention (Spec_Id, Convention_Protected);
3801       return Spec_Id;
3802    end Build_Private_Protected_Declaration;
3803
3804    ---------------------------
3805    -- Build_Protected_Entry --
3806    ---------------------------
3807
3808    function Build_Protected_Entry
3809      (N   : Node_Id;
3810       Ent : Entity_Id;
3811       Pid : Node_Id) return Node_Id
3812    is
3813       Loc : constant Source_Ptr := Sloc (N);
3814
3815       Decls   : constant List_Id := Declarations (N);
3816       End_Lab : constant Node_Id :=
3817                   End_Label (Handled_Statement_Sequence (N));
3818       End_Loc : constant Source_Ptr :=
3819                   Sloc (Last (Statements (Handled_Statement_Sequence (N))));
3820       --  Used for the generated call to Complete_Entry_Body
3821
3822       Han_Loc : Source_Ptr;
3823       --  Used for the exception handler, inserted at end of the body
3824
3825       Op_Decls : constant List_Id := New_List;
3826       Complete : Node_Id;
3827       Edef     : Entity_Id;
3828       Espec    : Node_Id;
3829       Ohandle  : Node_Id;
3830       Op_Stats : List_Id;
3831
3832    begin
3833       --  Set the source location on the exception handler only when debugging
3834       --  the expanded code (see Make_Implicit_Exception_Handler).
3835
3836       if Debug_Generated_Code then
3837          Han_Loc := End_Loc;
3838
3839       --  Otherwise the inserted code should not be visible to the debugger
3840
3841       else
3842          Han_Loc := No_Location;
3843       end if;
3844
3845       Edef :=
3846         Make_Defining_Identifier (Loc,
3847           Chars => Chars (Protected_Body_Subprogram (Ent)));
3848       Espec :=
3849         Build_Protected_Entry_Specification (Loc, Edef, Empty);
3850
3851       --  Add the following declarations:
3852
3853       --    type poVP is access poV;
3854       --    _object : poVP := poVP (_O);
3855
3856       --  where _O is the formal parameter associated with the concurrent
3857       --  object. These declarations are needed for Complete_Entry_Body.
3858
3859       Add_Object_Pointer (Loc, Pid, Op_Decls);
3860
3861       --  Add renamings for all formals, the Protection object, discriminals,
3862       --  privals and the entry index constant for use by debugger.
3863
3864       Add_Formal_Renamings (Espec, Op_Decls, Ent, Loc);
3865       Debug_Private_Data_Declarations (Decls);
3866
3867       --  Put the declarations and the statements from the entry
3868
3869       Op_Stats :=
3870         New_List (
3871           Make_Block_Statement (Loc,
3872             Declarations => Decls,
3873             Handled_Statement_Sequence =>
3874               Handled_Statement_Sequence (N)));
3875
3876       case Corresponding_Runtime_Package (Pid) is
3877          when System_Tasking_Protected_Objects_Entries =>
3878             Append_To (Op_Stats,
3879               Make_Procedure_Call_Statement (End_Loc,
3880                 Name                   =>
3881                   New_Occurrence_Of (RTE (RE_Complete_Entry_Body), Loc),
3882                 Parameter_Associations => New_List (
3883                   Make_Attribute_Reference (End_Loc,
3884                     Prefix         =>
3885                       Make_Selected_Component (End_Loc,
3886                         Prefix        =>
3887                           Make_Identifier (End_Loc, Name_uObject),
3888                         Selector_Name =>
3889                           Make_Identifier (End_Loc, Name_uObject)),
3890                     Attribute_Name => Name_Unchecked_Access))));
3891
3892          when System_Tasking_Protected_Objects_Single_Entry =>
3893
3894             --  Historically, a call to Complete_Single_Entry_Body was
3895             --  inserted, but it was a null procedure.
3896
3897             null;
3898
3899          when others =>
3900             raise Program_Error;
3901       end case;
3902
3903       --  When exceptions can not be propagated, we never need to call
3904       --  Exception_Complete_Entry_Body
3905
3906       if No_Exception_Handlers_Set then
3907          return
3908            Make_Subprogram_Body (Loc,
3909              Specification => Espec,
3910              Declarations => Op_Decls,
3911              Handled_Statement_Sequence =>
3912                Make_Handled_Sequence_Of_Statements (Loc,
3913                  Statements => Op_Stats,
3914                  End_Label  => End_Lab));
3915
3916       else
3917          Ohandle := Make_Others_Choice (Loc);
3918          Set_All_Others (Ohandle);
3919
3920          case Corresponding_Runtime_Package (Pid) is
3921             when System_Tasking_Protected_Objects_Entries =>
3922                Complete :=
3923                  New_Occurrence_Of
3924                    (RTE (RE_Exceptional_Complete_Entry_Body), Loc);
3925
3926             when System_Tasking_Protected_Objects_Single_Entry =>
3927                Complete :=
3928                  New_Occurrence_Of
3929                    (RTE (RE_Exceptional_Complete_Single_Entry_Body), Loc);
3930
3931             when others =>
3932                raise Program_Error;
3933          end case;
3934
3935          --  Establish link between subprogram body entity and source entry
3936
3937          Set_Corresponding_Protected_Entry (Edef, Ent);
3938
3939          --  Create body of entry procedure. The renaming declarations are
3940          --  placed ahead of the block that contains the actual entry body.
3941
3942          return
3943            Make_Subprogram_Body (Loc,
3944              Specification => Espec,
3945              Declarations => Op_Decls,
3946              Handled_Statement_Sequence =>
3947                Make_Handled_Sequence_Of_Statements (Loc,
3948                  Statements => Op_Stats,
3949                  End_Label  => End_Lab,
3950                  Exception_Handlers => New_List (
3951                    Make_Implicit_Exception_Handler (Han_Loc,
3952                      Exception_Choices => New_List (Ohandle),
3953
3954                      Statements =>  New_List (
3955                        Make_Procedure_Call_Statement (Han_Loc,
3956                          Name => Complete,
3957                          Parameter_Associations => New_List (
3958                            Make_Attribute_Reference (Han_Loc,
3959                              Prefix =>
3960                                Make_Selected_Component (Han_Loc,
3961                                  Prefix        =>
3962                                    Make_Identifier (Han_Loc, Name_uObject),
3963                                  Selector_Name =>
3964                                    Make_Identifier (Han_Loc, Name_uObject)),
3965                                Attribute_Name => Name_Unchecked_Access),
3966
3967                            Make_Function_Call (Han_Loc,
3968                              Name => New_Occurrence_Of (
3969                                RTE (RE_Get_GNAT_Exception), Loc)))))))));
3970       end if;
3971    end Build_Protected_Entry;
3972
3973    -----------------------------------------
3974    -- Build_Protected_Entry_Specification --
3975    -----------------------------------------
3976
3977    function Build_Protected_Entry_Specification
3978      (Loc    : Source_Ptr;
3979       Def_Id : Entity_Id;
3980       Ent_Id : Entity_Id) return Node_Id
3981    is
3982       P : constant Entity_Id := Make_Defining_Identifier (Loc, Name_uP);
3983
3984    begin
3985       Set_Debug_Info_Needed (Def_Id);
3986
3987       if Present (Ent_Id) then
3988          Append_Elmt (P, Accept_Address (Ent_Id));
3989       end if;
3990
3991       return
3992         Make_Procedure_Specification (Loc,
3993           Defining_Unit_Name => Def_Id,
3994           Parameter_Specifications => New_List (
3995             Make_Parameter_Specification (Loc,
3996               Defining_Identifier =>
3997                 Make_Defining_Identifier (Loc, Name_uO),
3998               Parameter_Type =>
3999                 New_Occurrence_Of (RTE (RE_Address), Loc)),
4000
4001             Make_Parameter_Specification (Loc,
4002               Defining_Identifier => P,
4003               Parameter_Type =>
4004                 New_Occurrence_Of (RTE (RE_Address), Loc)),
4005
4006             Make_Parameter_Specification (Loc,
4007               Defining_Identifier =>
4008                 Make_Defining_Identifier (Loc, Name_uE),
4009               Parameter_Type =>
4010                 New_Occurrence_Of (RTE (RE_Protected_Entry_Index), Loc))));
4011    end Build_Protected_Entry_Specification;
4012
4013    --------------------------
4014    -- Build_Protected_Spec --
4015    --------------------------
4016
4017    function Build_Protected_Spec
4018      (N           : Node_Id;
4019       Obj_Type    : Entity_Id;
4020       Ident       : Entity_Id;
4021       Unprotected : Boolean := False) return List_Id
4022    is
4023       Loc       : constant Source_Ptr := Sloc (N);
4024       Decl      : Node_Id;
4025       Formal    : Entity_Id;
4026       New_Plist : List_Id;
4027       New_Param : Node_Id;
4028
4029    begin
4030       New_Plist := New_List;
4031
4032       Formal := First_Formal (Ident);
4033       while Present (Formal) loop
4034          New_Param :=
4035            Make_Parameter_Specification (Loc,
4036              Defining_Identifier =>
4037                Make_Defining_Identifier (Sloc (Formal), Chars (Formal)),
4038              Aliased_Present     => Aliased_Present (Parent (Formal)),
4039              In_Present          => In_Present      (Parent (Formal)),
4040              Out_Present         => Out_Present     (Parent (Formal)),
4041              Parameter_Type      => New_Occurrence_Of (Etype (Formal), Loc));
4042
4043          if Unprotected then
4044             Set_Protected_Formal (Formal, Defining_Identifier (New_Param));
4045          end if;
4046
4047          Append (New_Param, New_Plist);
4048          Next_Formal (Formal);
4049       end loop;
4050
4051       --  If the subprogram is a procedure and the context is not an access
4052       --  to protected subprogram, the parameter is in-out. Otherwise it is
4053       --  an in parameter.
4054
4055       Decl :=
4056         Make_Parameter_Specification (Loc,
4057           Defining_Identifier =>
4058             Make_Defining_Identifier (Loc, Name_uObject),
4059           In_Present => True,
4060           Out_Present =>
4061             (Etype (Ident) = Standard_Void_Type
4062               and then not Is_RTE (Obj_Type, RE_Address)),
4063           Parameter_Type =>
4064             New_Occurrence_Of (Obj_Type, Loc));
4065       Set_Debug_Info_Needed (Defining_Identifier (Decl));
4066       Prepend_To (New_Plist, Decl);
4067
4068       return New_Plist;
4069    end Build_Protected_Spec;
4070
4071    ---------------------------------------
4072    -- Build_Protected_Sub_Specification --
4073    ---------------------------------------
4074
4075    function Build_Protected_Sub_Specification
4076      (N        : Node_Id;
4077       Prot_Typ : Entity_Id;
4078       Mode     : Subprogram_Protection_Mode) return Node_Id
4079    is
4080       Loc       : constant Source_Ptr := Sloc (N);
4081       Decl      : Node_Id;
4082       Def_Id    : Entity_Id;
4083       New_Id    : Entity_Id;
4084       New_Plist : List_Id;
4085       New_Spec  : Node_Id;
4086
4087       Append_Chr : constant array (Subprogram_Protection_Mode) of Character :=
4088                      (Dispatching_Mode => ' ',
4089                       Protected_Mode   => 'P',
4090                       Unprotected_Mode => 'N');
4091
4092    begin
4093       if Ekind (Defining_Unit_Name (Specification (N))) =
4094            E_Subprogram_Body
4095       then
4096          Decl := Unit_Declaration_Node (Corresponding_Spec (N));
4097       else
4098          Decl := N;
4099       end if;
4100
4101       Def_Id := Defining_Unit_Name (Specification (Decl));
4102
4103       New_Plist :=
4104         Build_Protected_Spec
4105           (Decl, Corresponding_Record_Type (Prot_Typ), Def_Id,
4106            Mode = Unprotected_Mode);
4107       New_Id :=
4108         Make_Defining_Identifier (Loc,
4109           Chars => Build_Selected_Name (Prot_Typ, Def_Id, Append_Chr (Mode)));
4110
4111       --  The unprotected operation carries the user code, and debugging
4112       --  information must be generated for it, even though this spec does
4113       --  not come from source. It is also convenient to allow gdb to step
4114       --  into the protected operation, even though it only contains lock/
4115       --  unlock calls.
4116
4117       Set_Debug_Info_Needed (New_Id);
4118
4119       --  If a pragma Eliminate applies to the source entity, the internal
4120       --  subprograms will be eliminated as well.
4121
4122       Set_Is_Eliminated (New_Id, Is_Eliminated (Def_Id));
4123
4124       if Nkind (Specification (Decl)) = N_Procedure_Specification then
4125          New_Spec :=
4126            Make_Procedure_Specification (Loc,
4127              Defining_Unit_Name => New_Id,
4128              Parameter_Specifications => New_Plist);
4129
4130       --  Create a new specification for the anonymous subprogram type
4131
4132       else
4133          New_Spec :=
4134            Make_Function_Specification (Loc,
4135              Defining_Unit_Name => New_Id,
4136              Parameter_Specifications => New_Plist,
4137              Result_Definition =>
4138                Copy_Result_Type (Result_Definition (Specification (Decl))));
4139
4140          Set_Return_Present (Defining_Unit_Name (New_Spec));
4141       end if;
4142
4143       return New_Spec;
4144    end Build_Protected_Sub_Specification;
4145
4146    -------------------------------------
4147    -- Build_Protected_Subprogram_Body --
4148    -------------------------------------
4149
4150    function Build_Protected_Subprogram_Body
4151      (N         : Node_Id;
4152       Pid       : Node_Id;
4153       N_Op_Spec : Node_Id) return Node_Id
4154    is
4155       Loc          : constant Source_Ptr := Sloc (N);
4156       Op_Spec      : Node_Id;
4157       P_Op_Spec    : Node_Id;
4158       Uactuals     : List_Id;
4159       Pformal      : Node_Id;
4160       Unprot_Call  : Node_Id;
4161       Sub_Body     : Node_Id;
4162       Lock_Name    : Node_Id;
4163       Lock_Stmt    : Node_Id;
4164       R            : Node_Id;
4165       Return_Stmt  : Node_Id := Empty;    -- init to avoid gcc 3 warning
4166       Pre_Stmts    : List_Id := No_List;  -- init to avoid gcc 3 warning
4167       Stmts        : List_Id;
4168       Object_Parm  : Node_Id;
4169       Exc_Safe     : Boolean;
4170       Lock_Kind    : RE_Id;
4171
4172    begin
4173       Op_Spec := Specification (N);
4174       Exc_Safe := Is_Exception_Safe (N);
4175
4176       P_Op_Spec :=
4177         Build_Protected_Sub_Specification (N, Pid, Protected_Mode);
4178
4179       --  Build a list of the formal parameters of the protected version of
4180       --  the subprogram to use as the actual parameters of the unprotected
4181       --  version.
4182
4183       Uactuals := New_List;
4184       Pformal := First (Parameter_Specifications (P_Op_Spec));
4185       while Present (Pformal) loop
4186          Append_To (Uactuals,
4187            Make_Identifier (Loc, Chars (Defining_Identifier (Pformal))));
4188          Next (Pformal);
4189       end loop;
4190
4191       --  Make a call to the unprotected version of the subprogram built above
4192       --  for use by the protected version built below.
4193
4194       if Nkind (Op_Spec) = N_Function_Specification then
4195          if Exc_Safe then
4196             R := Make_Temporary (Loc, 'R');
4197             Unprot_Call :=
4198               Make_Object_Declaration (Loc,
4199                 Defining_Identifier => R,
4200                 Constant_Present => True,
4201                 Object_Definition => New_Copy (Result_Definition (N_Op_Spec)),
4202                 Expression =>
4203                   Make_Function_Call (Loc,
4204                     Name => Make_Identifier (Loc,
4205                       Chars => Chars (Defining_Unit_Name (N_Op_Spec))),
4206                     Parameter_Associations => Uactuals));
4207
4208             Return_Stmt :=
4209               Make_Simple_Return_Statement (Loc,
4210                 Expression => New_Occurrence_Of (R, Loc));
4211
4212          else
4213             Unprot_Call := Make_Simple_Return_Statement (Loc,
4214               Expression => Make_Function_Call (Loc,
4215                 Name =>
4216                   Make_Identifier (Loc,
4217                     Chars => Chars (Defining_Unit_Name (N_Op_Spec))),
4218                 Parameter_Associations => Uactuals));
4219          end if;
4220
4221          Lock_Kind := RE_Lock_Read_Only;
4222
4223       else
4224          Unprot_Call :=
4225            Make_Procedure_Call_Statement (Loc,
4226              Name =>
4227                Make_Identifier (Loc, Chars (Defining_Unit_Name (N_Op_Spec))),
4228              Parameter_Associations => Uactuals);
4229
4230          Lock_Kind := RE_Lock;
4231       end if;
4232
4233       --  Wrap call in block that will be covered by an at_end handler
4234
4235       if not Exc_Safe then
4236          Unprot_Call := Make_Block_Statement (Loc,
4237            Handled_Statement_Sequence =>
4238              Make_Handled_Sequence_Of_Statements (Loc,
4239                Statements => New_List (Unprot_Call)));
4240       end if;
4241
4242       --  Make the protected subprogram body. This locks the protected
4243       --  object and calls the unprotected version of the subprogram.
4244
4245       case Corresponding_Runtime_Package (Pid) is
4246          when System_Tasking_Protected_Objects_Entries =>
4247             Lock_Name := New_Occurrence_Of (RTE (RE_Lock_Entries), Loc);
4248
4249          when System_Tasking_Protected_Objects_Single_Entry =>
4250             Lock_Name := New_Occurrence_Of (RTE (RE_Lock_Entry), Loc);
4251
4252          when System_Tasking_Protected_Objects =>
4253             Lock_Name := New_Occurrence_Of (RTE (Lock_Kind), Loc);
4254
4255          when others =>
4256             raise Program_Error;
4257       end case;
4258
4259       Object_Parm :=
4260         Make_Attribute_Reference (Loc,
4261            Prefix =>
4262              Make_Selected_Component (Loc,
4263                Prefix        => Make_Identifier (Loc, Name_uObject),
4264                Selector_Name => Make_Identifier (Loc, Name_uObject)),
4265            Attribute_Name => Name_Unchecked_Access);
4266
4267       Lock_Stmt := Make_Procedure_Call_Statement (Loc,
4268         Name => Lock_Name,
4269         Parameter_Associations => New_List (Object_Parm));
4270
4271       if Abort_Allowed then
4272          Stmts := New_List (
4273            Make_Procedure_Call_Statement (Loc,
4274              Name => New_Occurrence_Of (RTE (RE_Abort_Defer), Loc),
4275              Parameter_Associations => Empty_List),
4276            Lock_Stmt);
4277
4278       else
4279          Stmts := New_List (Lock_Stmt);
4280       end if;
4281
4282       if not Exc_Safe then
4283          Append (Unprot_Call, Stmts);
4284       else
4285          if Nkind (Op_Spec) = N_Function_Specification then
4286             Pre_Stmts := Stmts;
4287             Stmts     := Empty_List;
4288          else
4289             Append (Unprot_Call, Stmts);
4290          end if;
4291
4292          --  Historical note: Previously, call to the cleanup was inserted
4293          --  here. This is now done by Build_Protected_Subprogram_Call_Cleanup,
4294          --  which is also shared by the 'not Exc_Safe' path.
4295
4296          Build_Protected_Subprogram_Call_Cleanup (Op_Spec, Pid, Loc, Stmts);
4297
4298          if Nkind (Op_Spec) = N_Function_Specification then
4299             Append (Return_Stmt, Stmts);
4300             Append (Make_Block_Statement (Loc,
4301               Declarations => New_List (Unprot_Call),
4302               Handled_Statement_Sequence =>
4303                 Make_Handled_Sequence_Of_Statements (Loc,
4304                   Statements => Stmts)), Pre_Stmts);
4305             Stmts := Pre_Stmts;
4306          end if;
4307       end if;
4308
4309       Sub_Body :=
4310         Make_Subprogram_Body (Loc,
4311           Declarations => Empty_List,
4312           Specification => P_Op_Spec,
4313           Handled_Statement_Sequence =>
4314             Make_Handled_Sequence_Of_Statements (Loc, Statements => Stmts));
4315
4316       --  Mark this subprogram as a protected subprogram body so that the
4317       --  cleanup will be inserted. This is done only in the 'not Exc_Safe'
4318       --  path as otherwise the cleanup has already been inserted.
4319
4320       if not Exc_Safe then
4321          Set_Is_Protected_Subprogram_Body (Sub_Body);
4322       end if;
4323
4324       return Sub_Body;
4325    end Build_Protected_Subprogram_Body;
4326
4327    -------------------------------------
4328    -- Build_Protected_Subprogram_Call --
4329    -------------------------------------
4330
4331    procedure Build_Protected_Subprogram_Call
4332      (N        : Node_Id;
4333       Name     : Node_Id;
4334       Rec      : Node_Id;
4335       External : Boolean := True)
4336    is
4337       Loc     : constant Source_Ptr := Sloc (N);
4338       Sub     : constant Entity_Id  := Entity (Name);
4339       New_Sub : Node_Id;
4340       Params  : List_Id;
4341
4342    begin
4343       if External then
4344          New_Sub := New_Occurrence_Of (External_Subprogram (Sub), Loc);
4345       else
4346          New_Sub :=
4347            New_Occurrence_Of (Protected_Body_Subprogram (Sub), Loc);
4348       end if;
4349
4350       if Present (Parameter_Associations (N)) then
4351          Params := New_Copy_List_Tree (Parameter_Associations (N));
4352       else
4353          Params := New_List;
4354       end if;
4355
4356       --  If the type is an untagged derived type, convert to the root type,
4357       --  which is the one on which the operations are defined.
4358
4359       if Nkind (Rec) = N_Unchecked_Type_Conversion
4360         and then not Is_Tagged_Type (Etype (Rec))
4361         and then Is_Derived_Type (Etype (Rec))
4362       then
4363          Set_Etype (Rec, Root_Type (Etype (Rec)));
4364          Set_Subtype_Mark (Rec,
4365            New_Occurrence_Of (Root_Type (Etype (Rec)), Sloc (N)));
4366       end if;
4367
4368       Prepend (Rec, Params);
4369
4370       if Ekind (Sub) = E_Procedure then
4371          Rewrite (N,
4372            Make_Procedure_Call_Statement (Loc,
4373              Name => New_Sub,
4374              Parameter_Associations => Params));
4375
4376       else
4377          pragma Assert (Ekind (Sub) = E_Function);
4378          Rewrite (N,
4379            Make_Function_Call (Loc,
4380              Name                   => New_Sub,
4381              Parameter_Associations => Params));
4382
4383          --  Preserve type of call for subsequent processing (required for
4384          --  call to Wrap_Transient_Expression in the case of a shared passive
4385          --  protected).
4386
4387          Set_Etype (N, Etype (New_Sub));
4388       end if;
4389
4390       if External
4391         and then Nkind (Rec) = N_Unchecked_Type_Conversion
4392         and then Is_Entity_Name (Expression (Rec))
4393         and then Is_Shared_Passive (Entity (Expression (Rec)))
4394       then
4395          Add_Shared_Var_Lock_Procs (N);
4396       end if;
4397    end Build_Protected_Subprogram_Call;
4398
4399    ---------------------------------------------
4400    -- Build_Protected_Subprogram_Call_Cleanup --
4401    ---------------------------------------------
4402
4403    procedure Build_Protected_Subprogram_Call_Cleanup
4404      (Op_Spec   : Node_Id;
4405       Conc_Typ  : Node_Id;
4406       Loc       : Source_Ptr;
4407       Stmts     : List_Id)
4408    is
4409       Nam       : Node_Id;
4410
4411    begin
4412       --  If the associated protected object has entries, a protected
4413       --  procedure has to service entry queues. In this case generate:
4414
4415       --    Service_Entries (_object._object'Access);
4416
4417       if Nkind (Op_Spec) = N_Procedure_Specification
4418         and then Has_Entries (Conc_Typ)
4419       then
4420          case Corresponding_Runtime_Package (Conc_Typ) is
4421             when System_Tasking_Protected_Objects_Entries =>
4422                Nam := New_Occurrence_Of (RTE (RE_Service_Entries), Loc);
4423
4424             when System_Tasking_Protected_Objects_Single_Entry =>
4425                Nam := New_Occurrence_Of (RTE (RE_Service_Entry), Loc);
4426
4427             when others =>
4428                raise Program_Error;
4429          end case;
4430
4431          Append_To (Stmts,
4432            Make_Procedure_Call_Statement (Loc,
4433              Name                   => Nam,
4434              Parameter_Associations => New_List (
4435                Make_Attribute_Reference (Loc,
4436                  Prefix         =>
4437                    Make_Selected_Component (Loc,
4438                      Prefix        => Make_Identifier (Loc, Name_uObject),
4439                      Selector_Name => Make_Identifier (Loc, Name_uObject)),
4440                  Attribute_Name => Name_Unchecked_Access))));
4441
4442       else
4443          --  Generate:
4444          --    Unlock (_object._object'Access);
4445
4446          case Corresponding_Runtime_Package (Conc_Typ) is
4447             when System_Tasking_Protected_Objects_Entries =>
4448                Nam := New_Occurrence_Of (RTE (RE_Unlock_Entries), Loc);
4449
4450             when System_Tasking_Protected_Objects_Single_Entry =>
4451                Nam := New_Occurrence_Of (RTE (RE_Unlock_Entry), Loc);
4452
4453             when System_Tasking_Protected_Objects =>
4454                Nam := New_Occurrence_Of (RTE (RE_Unlock), Loc);
4455
4456             when others =>
4457                raise Program_Error;
4458          end case;
4459
4460          Append_To (Stmts,
4461            Make_Procedure_Call_Statement (Loc,
4462              Name                   => Nam,
4463              Parameter_Associations => New_List (
4464                Make_Attribute_Reference (Loc,
4465                  Prefix         =>
4466                    Make_Selected_Component (Loc,
4467                      Prefix        => Make_Identifier (Loc, Name_uObject),
4468                      Selector_Name => Make_Identifier (Loc, Name_uObject)),
4469                  Attribute_Name => Name_Unchecked_Access))));
4470       end if;
4471
4472       --  Generate:
4473       --    Abort_Undefer;
4474
4475       if Abort_Allowed then
4476          Append_To (Stmts,
4477            Make_Procedure_Call_Statement (Loc,
4478              Name                   =>
4479                New_Occurrence_Of (RTE (RE_Abort_Undefer), Loc),
4480              Parameter_Associations => Empty_List));
4481       end if;
4482    end Build_Protected_Subprogram_Call_Cleanup;
4483
4484    -------------------------
4485    -- Build_Selected_Name --
4486    -------------------------
4487
4488    function Build_Selected_Name
4489      (Prefix      : Entity_Id;
4490       Selector    : Entity_Id;
4491       Append_Char : Character := ' ') return Name_Id
4492    is
4493       Select_Buffer : String (1 .. Hostparm.Max_Name_Length);
4494       Select_Len    : Natural;
4495
4496    begin
4497       Get_Name_String (Chars (Selector));
4498       Select_Len := Name_Len;
4499       Select_Buffer (1 .. Select_Len) := Name_Buffer (1 .. Name_Len);
4500       Get_Name_String (Chars (Prefix));
4501
4502       --  If scope is anonymous type, discard suffix to recover name of
4503       --  single protected object. Otherwise use protected type name.
4504
4505       if Name_Buffer (Name_Len) = 'T' then
4506          Name_Len := Name_Len - 1;
4507       end if;
4508
4509       Add_Str_To_Name_Buffer ("__");
4510       for J in 1 .. Select_Len loop
4511          Add_Char_To_Name_Buffer (Select_Buffer (J));
4512       end loop;
4513
4514       --  Now add the Append_Char if specified. The encoding to follow
4515       --  depends on the type of entity. If Append_Char is either 'N' or 'P',
4516       --  then the entity is associated to a protected type subprogram.
4517       --  Otherwise, it is a protected type entry. For each case, the
4518       --  encoding to follow for the suffix is documented in exp_dbug.ads.
4519
4520       --  It would be better to encapsulate this as a routine in Exp_Dbug ???
4521
4522       if Append_Char /= ' ' then
4523          if Append_Char = 'P' or Append_Char = 'N' then
4524             Add_Char_To_Name_Buffer (Append_Char);
4525             return Name_Find;
4526          else
4527             Add_Str_To_Name_Buffer ((1 => '_', 2 => Append_Char));
4528             return New_External_Name (Name_Find, ' ', -1);
4529          end if;
4530       else
4531          return Name_Find;
4532       end if;
4533    end Build_Selected_Name;
4534
4535    -----------------------------
4536    -- Build_Simple_Entry_Call --
4537    -----------------------------
4538
4539    --  A task entry call is converted to a call to Call_Simple
4540
4541    --    declare
4542    --       P : parms := (parm, parm, parm);
4543    --    begin
4544    --       Call_Simple (acceptor-task, entry-index, P'Address);
4545    --       parm := P.param;
4546    --       parm := P.param;
4547    --       ...
4548    --    end;
4549
4550    --  Here Pnn is an aggregate of the type constructed for the entry to hold
4551    --  the parameters, and the constructed aggregate value contains either the
4552    --  parameters or, in the case of non-elementary types, references to these
4553    --  parameters. Then the address of this aggregate is passed to the runtime
4554    --  routine, along with the task id value and the task entry index value.
4555    --  Pnn is only required if parameters are present.
4556
4557    --  The assignments after the call are present only in the case of in-out
4558    --  or out parameters for elementary types, and are used to assign back the
4559    --  resulting values of such parameters.
4560
4561    --  Note: the reason that we insert a block here is that in the context
4562    --  of selects, conditional entry calls etc. the entry call statement
4563    --  appears on its own, not as an element of a list.
4564
4565    --  A protected entry call is converted to a Protected_Entry_Call:
4566
4567    --  declare
4568    --     P   : E1_Params := (param, param, param);
4569    --     Pnn : Boolean;
4570    --     Bnn : Communications_Block;
4571
4572    --  declare
4573    --     P   : E1_Params := (param, param, param);
4574    --     Bnn : Communications_Block;
4575
4576    --  begin
4577    --     Protected_Entry_Call (
4578    --       Object => po._object'Access,
4579    --       E => <entry index>;
4580    --       Uninterpreted_Data => P'Address;
4581    --       Mode => Simple_Call;
4582    --       Block => Bnn);
4583    --     parm := P.param;
4584    --     parm := P.param;
4585    --       ...
4586    --  end;
4587
4588    procedure Build_Simple_Entry_Call
4589      (N       : Node_Id;
4590       Concval : Node_Id;
4591       Ename   : Node_Id;
4592       Index   : Node_Id)
4593    is
4594    begin
4595       Expand_Call (N);
4596
4597       --  If call has been inlined, nothing left to do
4598
4599       if Nkind (N) = N_Block_Statement then
4600          return;
4601       end if;
4602
4603       --  Convert entry call to Call_Simple call
4604
4605       declare
4606          Loc       : constant Source_Ptr := Sloc (N);
4607          Parms     : constant List_Id    := Parameter_Associations (N);
4608          Stats     : constant List_Id    := New_List;
4609          Actual    : Node_Id;
4610          Call      : Node_Id;
4611          Comm_Name : Entity_Id;
4612          Conctyp   : Node_Id;
4613          Decls     : List_Id;
4614          Ent       : Entity_Id;
4615          Ent_Acc   : Entity_Id;
4616          Formal    : Node_Id;
4617          Iface_Tag : Entity_Id;
4618          Iface_Typ : Entity_Id;
4619          N_Node    : Node_Id;
4620          N_Var     : Node_Id;
4621          P         : Entity_Id;
4622          Parm1     : Node_Id;
4623          Parm2     : Node_Id;
4624          Parm3     : Node_Id;
4625          Pdecl     : Node_Id;
4626          Plist     : List_Id;
4627          X         : Entity_Id;
4628          Xdecl     : Node_Id;
4629
4630       begin
4631          --  Simple entry and entry family cases merge here
4632
4633          Ent     := Entity (Ename);
4634          Ent_Acc := Entry_Parameters_Type (Ent);
4635          Conctyp := Etype (Concval);
4636
4637          --  If prefix is an access type, dereference to obtain the task type
4638
4639          if Is_Access_Type (Conctyp) then
4640             Conctyp := Designated_Type (Conctyp);
4641          end if;
4642
4643          --  Special case for protected subprogram calls
4644
4645          if Is_Protected_Type (Conctyp)
4646            and then Is_Subprogram (Entity (Ename))
4647          then
4648             if not Is_Eliminated (Entity (Ename)) then
4649                Build_Protected_Subprogram_Call
4650                  (N, Ename, Convert_Concurrent (Concval, Conctyp));
4651                Analyze (N);
4652             end if;
4653
4654             return;
4655          end if;
4656
4657          --  First parameter is the Task_Id value from the task value or the
4658          --  Object from the protected object value, obtained by selecting
4659          --  the _Task_Id or _Object from the result of doing an unchecked
4660          --  conversion to convert the value to the corresponding record type.
4661
4662          if Nkind (Concval) = N_Function_Call
4663            and then Is_Task_Type (Conctyp)
4664            and then Ada_Version >= Ada_2005
4665          then
4666             declare
4667                ExpR : constant Node_Id   := Relocate_Node (Concval);
4668                Obj  : constant Entity_Id := Make_Temporary (Loc, 'F', ExpR);
4669                Decl : Node_Id;
4670
4671             begin
4672                Decl :=
4673                  Make_Object_Declaration (Loc,
4674                    Defining_Identifier => Obj,
4675                    Object_Definition   => New_Occurrence_Of (Conctyp, Loc),
4676                    Expression          => ExpR);
4677                Set_Etype (Obj, Conctyp);
4678                Decls := New_List (Decl);
4679                Rewrite (Concval, New_Occurrence_Of (Obj, Loc));
4680             end;
4681
4682          else
4683             Decls := New_List;
4684          end if;
4685
4686          Parm1 := Concurrent_Ref (Concval);
4687
4688          --  Second parameter is the entry index, computed by the routine
4689          --  provided for this purpose. The value of this expression is
4690          --  assigned to an intermediate variable to assure that any entry
4691          --  family index expressions are evaluated before the entry
4692          --  parameters.
4693
4694          if not Is_Protected_Type (Conctyp)
4695            or else
4696              Corresponding_Runtime_Package (Conctyp) =
4697                System_Tasking_Protected_Objects_Entries
4698          then
4699             X := Make_Defining_Identifier (Loc, Name_uX);
4700
4701             Xdecl :=
4702               Make_Object_Declaration (Loc,
4703                 Defining_Identifier => X,
4704                 Object_Definition =>
4705                   New_Occurrence_Of (RTE (RE_Task_Entry_Index), Loc),
4706                 Expression => Actual_Index_Expression (
4707                   Loc, Entity (Ename), Index, Concval));
4708
4709             Append_To (Decls, Xdecl);
4710             Parm2 := New_Occurrence_Of (X, Loc);
4711
4712          else
4713             Xdecl := Empty;
4714             Parm2 := Empty;
4715          end if;
4716
4717          --  The third parameter is the packaged parameters. If there are
4718          --  none, then it is just the null address, since nothing is passed.
4719
4720          if No (Parms) then
4721             Parm3 := New_Occurrence_Of (RTE (RE_Null_Address), Loc);
4722             P := Empty;
4723
4724          --  Case of parameters present, where third argument is the address
4725          --  of a packaged record containing the required parameter values.
4726
4727          else
4728             --  First build a list of parameter values, which are references to
4729             --  objects of the parameter types.
4730
4731             Plist := New_List;
4732
4733             Actual := First_Actual (N);
4734             Formal := First_Formal (Ent);
4735             while Present (Actual) loop
4736
4737                --  If it is a by-copy type, copy it to a new variable. The
4738                --  packaged record has a field that points to this variable.
4739
4740                if Is_By_Copy_Type (Etype (Actual)) then
4741                   N_Node :=
4742                     Make_Object_Declaration (Loc,
4743                       Defining_Identifier => Make_Temporary (Loc, 'J'),
4744                       Aliased_Present     => True,
4745                       Object_Definition   =>
4746                         New_Occurrence_Of (Etype (Formal), Loc));
4747
4748                   --  Mark the object as not needing initialization since the
4749                   --  initialization is performed separately, avoiding errors
4750                   --  on cases such as formals of null-excluding access types.
4751
4752                   Set_No_Initialization (N_Node);
4753
4754                   --  We must make a separate assignment statement for the
4755                   --  case of limited types. We cannot assign it unless the
4756                   --  Assignment_OK flag is set first. An out formal of an
4757                   --  access type or whose type has a Default_Value must also
4758                   --  be initialized from the actual (see RM 6.4.1 (13-13.1)),
4759                   --  but no constraint, predicate, or null-exclusion check is
4760                   --  applied before the call.
4761
4762                   if Ekind (Formal) /= E_Out_Parameter
4763                     or else Is_Access_Type (Etype (Formal))
4764                     or else
4765                       (Is_Scalar_Type (Etype (Formal))
4766                         and then
4767                          Present (Default_Aspect_Value (Etype (Formal))))
4768                   then
4769                      N_Var :=
4770                        New_Occurrence_Of (Defining_Identifier (N_Node), Loc);
4771                      Set_Assignment_OK (N_Var);
4772                      Append_To (Stats,
4773                        Make_Assignment_Statement (Loc,
4774                          Name       => N_Var,
4775                          Expression => Relocate_Node (Actual)));
4776
4777                      --  Mark the object as internal, so we don't later reset
4778                      --  No_Initialization flag in Default_Initialize_Object,
4779                      --  which would lead to needless default initialization.
4780                      --  We don't set this outside the if statement, because
4781                      --  out scalar parameters without Default_Value do require
4782                      --  default initialization if Initialize_Scalars applies.
4783
4784                      Set_Is_Internal (Defining_Identifier (N_Node));
4785
4786                      --  If actual is an out parameter of a null-excluding
4787                      --  access type, there is access check on entry, so set
4788                      --  Suppress_Assignment_Checks on the generated statement
4789                      --  that assigns the actual to the parameter block
4790
4791                      Set_Suppress_Assignment_Checks (Last (Stats));
4792                   end if;
4793
4794                   Append (N_Node, Decls);
4795
4796                   Append_To (Plist,
4797                     Make_Attribute_Reference (Loc,
4798                       Attribute_Name => Name_Unchecked_Access,
4799                       Prefix         =>
4800                         New_Occurrence_Of
4801                           (Defining_Identifier (N_Node), Loc)));
4802
4803                else
4804                   --  Interface class-wide formal
4805
4806                   if Ada_Version >= Ada_2005
4807                     and then Ekind (Etype (Formal)) = E_Class_Wide_Type
4808                     and then Is_Interface (Etype (Formal))
4809                   then
4810                      Iface_Typ := Etype (Etype (Formal));
4811
4812                      --  Generate:
4813                      --    formal_iface_type! (actual.iface_tag)'reference
4814
4815                      Iface_Tag :=
4816                        Find_Interface_Tag (Etype (Actual), Iface_Typ);
4817                      pragma Assert (Present (Iface_Tag));
4818
4819                      Append_To (Plist,
4820                        Make_Reference (Loc,
4821                          Unchecked_Convert_To (Iface_Typ,
4822                            Make_Selected_Component (Loc,
4823                              Prefix        =>
4824                                Relocate_Node (Actual),
4825                              Selector_Name =>
4826                                New_Occurrence_Of (Iface_Tag, Loc)))));
4827                   else
4828                      --  Generate:
4829                      --    actual'reference
4830
4831                      Append_To (Plist,
4832                        Make_Reference (Loc, Relocate_Node (Actual)));
4833                   end if;
4834                end if;
4835
4836                Next_Actual (Actual);
4837                Next_Formal_With_Extras (Formal);
4838             end loop;
4839
4840             --  Now build the declaration of parameters initialized with the
4841             --  aggregate containing this constructed parameter list.
4842
4843             P := Make_Defining_Identifier (Loc, Name_uP);
4844
4845             Pdecl :=
4846               Make_Object_Declaration (Loc,
4847                 Defining_Identifier => P,
4848                 Object_Definition   =>
4849                   New_Occurrence_Of (Designated_Type (Ent_Acc), Loc),
4850                 Expression          =>
4851                   Make_Aggregate (Loc, Expressions => Plist));
4852
4853             Parm3 :=
4854               Make_Attribute_Reference (Loc,
4855                 Prefix         => New_Occurrence_Of (P, Loc),
4856                 Attribute_Name => Name_Address);
4857
4858             Append (Pdecl, Decls);
4859          end if;
4860
4861          --  Now we can create the call, case of protected type
4862
4863          if Is_Protected_Type (Conctyp) then
4864             case Corresponding_Runtime_Package (Conctyp) is
4865                when System_Tasking_Protected_Objects_Entries =>
4866
4867                   --  Change the type of the index declaration
4868
4869                   Set_Object_Definition (Xdecl,
4870                     New_Occurrence_Of (RTE (RE_Protected_Entry_Index), Loc));
4871
4872                   --  Some additional declarations for protected entry calls
4873
4874                   if No (Decls) then
4875                      Decls := New_List;
4876                   end if;
4877
4878                   --  Bnn : Communications_Block;
4879
4880                   Comm_Name := Make_Temporary (Loc, 'B');
4881
4882                   Append_To (Decls,
4883                     Make_Object_Declaration (Loc,
4884                       Defining_Identifier => Comm_Name,
4885                       Object_Definition   =>
4886                         New_Occurrence_Of
4887                            (RTE (RE_Communication_Block), Loc)));
4888
4889                   --  Some additional statements for protected entry calls
4890
4891                   --     Protected_Entry_Call (
4892                   --       Object => po._object'Access,
4893                   --       E => <entry index>;
4894                   --       Uninterpreted_Data => P'Address;
4895                   --       Mode => Simple_Call;
4896                   --       Block => Bnn);
4897
4898                   Call :=
4899                     Make_Procedure_Call_Statement (Loc,
4900                       Name =>
4901                         New_Occurrence_Of (RTE (RE_Protected_Entry_Call), Loc),
4902
4903                       Parameter_Associations => New_List (
4904                         Make_Attribute_Reference (Loc,
4905                           Attribute_Name => Name_Unchecked_Access,
4906                           Prefix         => Parm1),
4907                         Parm2,
4908                         Parm3,
4909                         New_Occurrence_Of (RTE (RE_Simple_Call), Loc),
4910                         New_Occurrence_Of (Comm_Name, Loc)));
4911
4912                when System_Tasking_Protected_Objects_Single_Entry =>
4913                   --     Protected_Single_Entry_Call (
4914                   --       Object => po._object'Access,
4915                   --       Uninterpreted_Data => P'Address);
4916
4917                   Call :=
4918                     Make_Procedure_Call_Statement (Loc,
4919                       Name                   =>
4920                         New_Occurrence_Of
4921                           (RTE (RE_Protected_Single_Entry_Call), Loc),
4922
4923                       Parameter_Associations => New_List (
4924                         Make_Attribute_Reference (Loc,
4925                           Attribute_Name => Name_Unchecked_Access,
4926                           Prefix         => Parm1),
4927                         Parm3));
4928
4929                when others =>
4930                   raise Program_Error;
4931             end case;
4932
4933          --  Case of task type
4934
4935          else
4936             Call :=
4937               Make_Procedure_Call_Statement (Loc,
4938                 Name                   =>
4939                   New_Occurrence_Of (RTE (RE_Call_Simple), Loc),
4940                 Parameter_Associations => New_List (Parm1, Parm2, Parm3));
4941
4942          end if;
4943
4944          Append_To (Stats, Call);
4945
4946          --  If there are out or in/out parameters by copy add assignment
4947          --  statements for the result values.
4948
4949          if Present (Parms) then
4950             Actual := First_Actual (N);
4951             Formal := First_Formal (Ent);
4952
4953             Set_Assignment_OK (Actual);
4954             while Present (Actual) loop
4955                if Is_By_Copy_Type (Etype (Actual))
4956                  and then Ekind (Formal) /= E_In_Parameter
4957                then
4958                   N_Node :=
4959                     Make_Assignment_Statement (Loc,
4960                       Name       => New_Copy (Actual),
4961                       Expression =>
4962                         Make_Explicit_Dereference (Loc,
4963                           Make_Selected_Component (Loc,
4964                             Prefix        => New_Occurrence_Of (P, Loc),
4965                             Selector_Name =>
4966                               Make_Identifier (Loc, Chars (Formal)))));
4967
4968                   --  In all cases (including limited private types) we want
4969                   --  the assignment to be valid.
4970
4971                   Set_Assignment_OK (Name (N_Node));
4972
4973                   --  If the call is the triggering alternative in an
4974                   --  asynchronous select, or the entry_call alternative of a
4975                   --  conditional entry call, the assignments for in-out
4976                   --  parameters are incorporated into the statement list that
4977                   --  follows, so that there are executed only if the entry
4978                   --  call succeeds.
4979
4980                   if (Nkind (Parent (N)) = N_Triggering_Alternative
4981                        and then N = Triggering_Statement (Parent (N)))
4982                     or else
4983                      (Nkind (Parent (N)) = N_Entry_Call_Alternative
4984                        and then N = Entry_Call_Statement (Parent (N)))
4985                   then
4986                      if No (Statements (Parent (N))) then
4987                         Set_Statements (Parent (N), New_List);
4988                      end if;
4989
4990                      Prepend (N_Node, Statements (Parent (N)));
4991
4992                   else
4993                      Insert_After (Call, N_Node);
4994                   end if;
4995                end if;
4996
4997                Next_Actual (Actual);
4998                Next_Formal_With_Extras (Formal);
4999             end loop;
5000          end if;
5001
5002          --  Finally, create block and analyze it
5003
5004          Rewrite (N,
5005            Make_Block_Statement (Loc,
5006              Declarations               => Decls,
5007              Handled_Statement_Sequence =>
5008                Make_Handled_Sequence_Of_Statements (Loc,
5009                  Statements => Stats)));
5010
5011          Analyze (N);
5012       end;
5013    end Build_Simple_Entry_Call;
5014
5015    --------------------------------
5016    -- Build_Task_Activation_Call --
5017    --------------------------------
5018
5019    procedure Build_Task_Activation_Call (N : Node_Id) is
5020       Loc   : constant Source_Ptr := Sloc (N);
5021       Chain : Entity_Id;
5022       Call  : Node_Id;
5023       Name  : Node_Id;
5024       P     : Node_Id;
5025
5026    begin
5027       --  For sequential elaboration policy, all the tasks will be activated at
5028       --  the end of the elaboration.
5029
5030       if Partition_Elaboration_Policy = 'S' then
5031          return;
5032       end if;
5033
5034       --  Get the activation chain entity. Except in the case of a package
5035       --  body, this is in the node that was passed. For a package body, we
5036       --  have to find the corresponding package declaration node.
5037
5038       if Nkind (N) = N_Package_Body then
5039          P := Corresponding_Spec (N);
5040          loop
5041             P := Parent (P);
5042             exit when Nkind (P) = N_Package_Declaration;
5043          end loop;
5044
5045          Chain := Activation_Chain_Entity (P);
5046
5047       else
5048          Chain := Activation_Chain_Entity (N);
5049       end if;
5050
5051       if Present (Chain) then
5052          if Restricted_Profile then
5053             Name := New_Occurrence_Of
5054                       (RTE (RE_Activate_Restricted_Tasks), Loc);
5055          else
5056             Name := New_Occurrence_Of
5057                       (RTE (RE_Activate_Tasks), Loc);
5058          end if;
5059
5060          Call :=
5061            Make_Procedure_Call_Statement (Loc,
5062              Name                   => Name,
5063              Parameter_Associations =>
5064                New_List (Make_Attribute_Reference (Loc,
5065                  Prefix         => New_Occurrence_Of (Chain, Loc),
5066                  Attribute_Name => Name_Unchecked_Access)));
5067
5068          if Nkind (N) = N_Package_Declaration then
5069             if Present (Corresponding_Body (N)) then
5070                null;
5071
5072             elsif Present (Private_Declarations (Specification (N))) then
5073                Append (Call, Private_Declarations (Specification (N)));
5074
5075             else
5076                Append (Call, Visible_Declarations (Specification (N)));
5077             end if;
5078
5079          else
5080             if Present (Handled_Statement_Sequence (N)) then
5081
5082                --  The call goes at the start of the statement sequence after
5083                --  the start of exception range label if one is present.
5084
5085                declare
5086                   Stm : Node_Id;
5087
5088                begin
5089                   Stm := First (Statements (Handled_Statement_Sequence (N)));
5090
5091                   --  A special case, skip exception range label if one is
5092                   --  present (from front end zcx processing).
5093
5094                   if Nkind (Stm) = N_Label and then Exception_Junk (Stm) then
5095                      Next (Stm);
5096                   end if;
5097
5098                   --  Another special case, if the first statement is a block
5099                   --  from optimization of a local raise to a goto, then the
5100                   --  call goes inside this block.
5101
5102                   if Nkind (Stm) = N_Block_Statement
5103                     and then Exception_Junk (Stm)
5104                   then
5105                      Stm :=
5106                        First (Statements (Handled_Statement_Sequence (Stm)));
5107                   end if;
5108
5109                   --  Insertion point is after any exception label pushes,
5110                   --  since we want it covered by any local handlers.
5111
5112                   while Nkind (Stm) in N_Push_xxx_Label loop
5113                      Next (Stm);
5114                   end loop;
5115
5116                   --  Now we have the proper insertion point
5117
5118                   Insert_Before (Stm, Call);
5119                end;
5120
5121             else
5122                Set_Handled_Statement_Sequence (N,
5123                   Make_Handled_Sequence_Of_Statements (Loc,
5124                     Statements => New_List (Call)));
5125             end if;
5126          end if;
5127
5128          Analyze (Call);
5129          Check_Task_Activation (N);
5130       end if;
5131    end Build_Task_Activation_Call;
5132
5133    -------------------------------
5134    -- Build_Task_Allocate_Block --
5135    -------------------------------
5136
5137    procedure Build_Task_Allocate_Block
5138      (Actions : List_Id;
5139       N       : Node_Id;
5140       Args    : List_Id)
5141    is
5142       T      : constant Entity_Id  := Entity (Expression (N));
5143       Init   : constant Entity_Id  := Base_Init_Proc (T);
5144       Loc    : constant Source_Ptr := Sloc (N);
5145       Chain  : constant Entity_Id  :=
5146                  Make_Defining_Identifier (Loc, Name_uChain);
5147       Blkent : constant Entity_Id  := Make_Temporary (Loc, 'A');
5148       Block  : Node_Id;
5149
5150    begin
5151       Block :=
5152         Make_Block_Statement (Loc,
5153           Identifier   => New_Occurrence_Of (Blkent, Loc),
5154           Declarations => New_List (
5155
5156             --  _Chain  : Activation_Chain;
5157
5158             Make_Object_Declaration (Loc,
5159               Defining_Identifier => Chain,
5160               Aliased_Present     => True,
5161               Object_Definition   =>
5162                 New_Occurrence_Of (RTE (RE_Activation_Chain), Loc))),
5163
5164           Handled_Statement_Sequence =>
5165             Make_Handled_Sequence_Of_Statements (Loc,
5166
5167               Statements => New_List (
5168
5169                 --  Init (Args);
5170
5171                 Make_Procedure_Call_Statement (Loc,
5172                   Name                   => New_Occurrence_Of (Init, Loc),
5173                   Parameter_Associations => Args),
5174
5175                 --  Activate_Tasks (_Chain);
5176
5177                 Make_Procedure_Call_Statement (Loc,
5178                   Name => New_Occurrence_Of (RTE (RE_Activate_Tasks), Loc),
5179                   Parameter_Associations => New_List (
5180                     Make_Attribute_Reference (Loc,
5181                       Prefix         => New_Occurrence_Of (Chain, Loc),
5182                       Attribute_Name => Name_Unchecked_Access))))),
5183
5184           Has_Created_Identifier => True,
5185           Is_Task_Allocation_Block => True);
5186
5187       Append_To (Actions,
5188         Make_Implicit_Label_Declaration (Loc,
5189           Defining_Identifier => Blkent,
5190           Label_Construct     => Block));
5191
5192       Append_To (Actions, Block);
5193
5194       Set_Activation_Chain_Entity (Block, Chain);
5195    end Build_Task_Allocate_Block;
5196
5197    -----------------------------------------------
5198    -- Build_Task_Allocate_Block_With_Init_Stmts --
5199    -----------------------------------------------
5200
5201    procedure Build_Task_Allocate_Block_With_Init_Stmts
5202      (Actions    : List_Id;
5203       N          : Node_Id;
5204       Init_Stmts : List_Id)
5205    is
5206       Loc    : constant Source_Ptr := Sloc (N);
5207       Chain  : constant Entity_Id  :=
5208                  Make_Defining_Identifier (Loc, Name_uChain);
5209       Blkent : constant Entity_Id  := Make_Temporary (Loc, 'A');
5210       Block  : Node_Id;
5211
5212    begin
5213       Append_To (Init_Stmts,
5214         Make_Procedure_Call_Statement (Loc,
5215           Name => New_Occurrence_Of (RTE (RE_Activate_Tasks), Loc),
5216           Parameter_Associations => New_List (
5217             Make_Attribute_Reference (Loc,
5218               Prefix         => New_Occurrence_Of (Chain, Loc),
5219               Attribute_Name => Name_Unchecked_Access))));
5220
5221       Block :=
5222         Make_Block_Statement (Loc,
5223           Identifier => New_Occurrence_Of (Blkent, Loc),
5224           Declarations => New_List (
5225
5226             --  _Chain  : Activation_Chain;
5227
5228             Make_Object_Declaration (Loc,
5229               Defining_Identifier => Chain,
5230               Aliased_Present     => True,
5231               Object_Definition   =>
5232                 New_Occurrence_Of (RTE (RE_Activation_Chain), Loc))),
5233
5234           Handled_Statement_Sequence =>
5235             Make_Handled_Sequence_Of_Statements (Loc, Init_Stmts),
5236
5237           Has_Created_Identifier => True,
5238           Is_Task_Allocation_Block => True);
5239
5240       Append_To (Actions,
5241         Make_Implicit_Label_Declaration (Loc,
5242           Defining_Identifier => Blkent,
5243           Label_Construct     => Block));
5244
5245       Append_To (Actions, Block);
5246
5247       Set_Activation_Chain_Entity (Block, Chain);
5248    end Build_Task_Allocate_Block_With_Init_Stmts;
5249
5250    -----------------------------------
5251    -- Build_Task_Proc_Specification --
5252    -----------------------------------
5253
5254    function Build_Task_Proc_Specification (T : Entity_Id) return Node_Id is
5255       Loc     : constant Source_Ptr := Sloc (T);
5256       Spec_Id : Entity_Id;
5257
5258    begin
5259       --  Case of explicit task type, suffix TB
5260
5261       if Comes_From_Source (T) then
5262          Spec_Id :=
5263            Make_Defining_Identifier (Loc, New_External_Name (Chars (T), "TB"));
5264
5265       --  Case of anonymous task type, suffix B
5266
5267       else
5268          Spec_Id :=
5269            Make_Defining_Identifier (Loc, New_External_Name (Chars (T), 'B'));
5270       end if;
5271
5272       Set_Is_Internal (Spec_Id);
5273
5274       --  Associate the procedure with the task, if this is the declaration
5275       --  (and not the body) of the procedure.
5276
5277       if No (Task_Body_Procedure (T)) then
5278          Set_Task_Body_Procedure (T, Spec_Id);
5279       end if;
5280
5281       return
5282         Make_Procedure_Specification (Loc,
5283           Defining_Unit_Name       => Spec_Id,
5284           Parameter_Specifications => New_List (
5285             Make_Parameter_Specification (Loc,
5286               Defining_Identifier =>
5287                 Make_Defining_Identifier (Loc, Name_uTask),
5288               Parameter_Type      =>
5289                 Make_Access_Definition (Loc,
5290                   Subtype_Mark =>
5291                     New_Occurrence_Of (Corresponding_Record_Type (T), Loc)))));
5292    end Build_Task_Proc_Specification;
5293
5294    ---------------------------------------
5295    -- Build_Unprotected_Subprogram_Body --
5296    ---------------------------------------
5297
5298    function Build_Unprotected_Subprogram_Body
5299      (N   : Node_Id;
5300       Pid : Node_Id) return Node_Id
5301    is
5302       Decls : constant List_Id := Declarations (N);
5303
5304    begin
5305       --  Add renamings for the Protection object, discriminals, privals and
5306       --  the entry index constant for use by debugger.
5307
5308       Debug_Private_Data_Declarations (Decls);
5309
5310       --  Make an unprotected version of the subprogram for use within the same
5311       --  object, with a new name and an additional parameter representing the
5312       --  object.
5313
5314       return
5315         Make_Subprogram_Body (Sloc (N),
5316           Specification              =>
5317             Build_Protected_Sub_Specification (N, Pid, Unprotected_Mode),
5318           Declarations               => Decls,
5319           Handled_Statement_Sequence => Handled_Statement_Sequence (N));
5320    end Build_Unprotected_Subprogram_Body;
5321
5322    ----------------------------
5323    -- Collect_Entry_Families --
5324    ----------------------------
5325
5326    procedure Collect_Entry_Families
5327      (Loc          : Source_Ptr;
5328       Cdecls       : List_Id;
5329       Current_Node : in out Node_Id;
5330       Conctyp      : Entity_Id)
5331    is
5332       Efam      : Entity_Id;
5333       Efam_Decl : Node_Id;
5334       Efam_Type : Entity_Id;
5335
5336    begin
5337       Efam := First_Entity (Conctyp);
5338       while Present (Efam) loop
5339          if Ekind (Efam) = E_Entry_Family then
5340             Efam_Type := Make_Temporary (Loc, 'F');
5341
5342             declare
5343                Bas : Entity_Id :=
5344                        Base_Type
5345                          (Etype (Discrete_Subtype_Definition (Parent (Efam))));
5346
5347                Bas_Decl : Node_Id := Empty;
5348                Lo, Hi   : Node_Id;
5349
5350             begin
5351                Get_Index_Bounds
5352                  (Discrete_Subtype_Definition (Parent (Efam)), Lo, Hi);
5353
5354                if Is_Potentially_Large_Family (Bas, Conctyp, Lo, Hi) then
5355                   Bas := Make_Temporary (Loc, 'B');
5356
5357                   Bas_Decl :=
5358                     Make_Subtype_Declaration (Loc,
5359                        Defining_Identifier => Bas,
5360                        Subtype_Indication  =>
5361                          Make_Subtype_Indication (Loc,
5362                            Subtype_Mark =>
5363                              New_Occurrence_Of (Standard_Integer, Loc),
5364                            Constraint   =>
5365                              Make_Range_Constraint (Loc,
5366                                Range_Expression => Make_Range (Loc,
5367                                  Make_Integer_Literal
5368                                    (Loc, -Entry_Family_Bound),
5369                                  Make_Integer_Literal
5370                                    (Loc, Entry_Family_Bound - 1)))));
5371
5372                   Insert_After (Current_Node, Bas_Decl);
5373                   Current_Node := Bas_Decl;
5374                   Analyze (Bas_Decl);
5375                end if;
5376
5377                Efam_Decl :=
5378                  Make_Full_Type_Declaration (Loc,
5379                    Defining_Identifier => Efam_Type,
5380                    Type_Definition =>
5381                      Make_Unconstrained_Array_Definition (Loc,
5382                        Subtype_Marks =>
5383                          (New_List (New_Occurrence_Of (Bas, Loc))),
5384
5385                     Component_Definition =>
5386                       Make_Component_Definition (Loc,
5387                         Aliased_Present    => False,
5388                         Subtype_Indication =>
5389                           New_Occurrence_Of (Standard_Character, Loc))));
5390             end;
5391
5392             Insert_After (Current_Node, Efam_Decl);
5393             Current_Node := Efam_Decl;
5394             Analyze (Efam_Decl);
5395
5396             Append_To (Cdecls,
5397               Make_Component_Declaration (Loc,
5398                 Defining_Identifier  =>
5399                   Make_Defining_Identifier (Loc, Chars (Efam)),
5400
5401                 Component_Definition =>
5402                   Make_Component_Definition (Loc,
5403                     Aliased_Present    => False,
5404                     Subtype_Indication =>
5405                       Make_Subtype_Indication (Loc,
5406                         Subtype_Mark =>
5407                           New_Occurrence_Of (Efam_Type, Loc),
5408
5409                         Constraint   =>
5410                           Make_Index_Or_Discriminant_Constraint (Loc,
5411                             Constraints => New_List (
5412                               New_Occurrence_Of
5413                                 (Etype (Discrete_Subtype_Definition
5414                                           (Parent (Efam))), Loc)))))));
5415
5416          end if;
5417
5418          Next_Entity (Efam);
5419       end loop;
5420    end Collect_Entry_Families;
5421
5422    -----------------------
5423    -- Concurrent_Object --
5424    -----------------------
5425
5426    function Concurrent_Object
5427      (Spec_Id  : Entity_Id;
5428       Conc_Typ : Entity_Id) return Entity_Id
5429    is
5430    begin
5431       --  Parameter _O or _object
5432
5433       if Is_Protected_Type (Conc_Typ) then
5434          return First_Formal (Protected_Body_Subprogram (Spec_Id));
5435
5436       --  Parameter _task
5437
5438       else
5439          pragma Assert (Is_Task_Type (Conc_Typ));
5440          return First_Formal (Task_Body_Procedure (Conc_Typ));
5441       end if;
5442    end Concurrent_Object;
5443
5444    ----------------------
5445    -- Copy_Result_Type --
5446    ----------------------
5447
5448    function Copy_Result_Type (Res : Node_Id) return Node_Id is
5449       New_Res  : constant Node_Id := New_Copy_Tree (Res);
5450       Par_Spec : Node_Id;
5451       Formal   : Entity_Id;
5452
5453    begin
5454       --  If the result type is an access_to_subprogram, we must create new
5455       --  entities for its spec.
5456
5457       if Nkind (New_Res) = N_Access_Definition
5458         and then Present (Access_To_Subprogram_Definition (New_Res))
5459       then
5460          --  Provide new entities for the formals
5461
5462          Par_Spec := First (Parameter_Specifications
5463                               (Access_To_Subprogram_Definition (New_Res)));
5464          while Present (Par_Spec) loop
5465             Formal := Defining_Identifier (Par_Spec);
5466             Set_Defining_Identifier (Par_Spec,
5467               Make_Defining_Identifier (Sloc (Formal), Chars (Formal)));
5468             Next (Par_Spec);
5469          end loop;
5470       end if;
5471
5472       return New_Res;
5473    end Copy_Result_Type;
5474
5475    --------------------
5476    -- Concurrent_Ref --
5477    --------------------
5478
5479    --  The expression returned for a reference to a concurrent object has the
5480    --  form:
5481
5482    --    taskV!(name)._Task_Id
5483
5484    --  for a task, and
5485
5486    --    objectV!(name)._Object
5487
5488    --  for a protected object. For the case of an access to a concurrent
5489    --  object, there is an extra explicit dereference:
5490
5491    --    taskV!(name.all)._Task_Id
5492    --    objectV!(name.all)._Object
5493
5494    --  here taskV and objectV are the types for the associated records, which
5495    --  contain the required _Task_Id and _Object fields for tasks and protected
5496    --  objects, respectively.
5497
5498    --  For the case of a task type name, the expression is
5499
5500    --    Self;
5501
5502    --  i.e. a call to the Self function which returns precisely this Task_Id
5503
5504    --  For the case of a protected type name, the expression is
5505
5506    --    objectR
5507
5508    --  which is a renaming of the _object field of the current object
5509    --  record, passed into protected operations as a parameter.
5510
5511    function Concurrent_Ref (N : Node_Id) return Node_Id is
5512       Loc  : constant Source_Ptr := Sloc (N);
5513       Ntyp : constant Entity_Id  := Etype (N);
5514       Dtyp : Entity_Id;
5515       Sel  : Name_Id;
5516
5517       function Is_Current_Task (T : Entity_Id) return Boolean;
5518       --  Check whether the reference is to the immediately enclosing task
5519       --  type, or to an outer one (rare but legal).
5520
5521       ---------------------
5522       -- Is_Current_Task --
5523       ---------------------
5524
5525       function Is_Current_Task (T : Entity_Id) return Boolean is
5526          Scop : Entity_Id;
5527
5528       begin
5529          Scop := Current_Scope;
5530          while Present (Scop) and then Scop /= Standard_Standard loop
5531             if Scop = T then
5532                return True;
5533
5534             elsif Is_Task_Type (Scop) then
5535                return False;
5536
5537             --  If this is a procedure nested within the task type, we must
5538             --  assume that it can be called from an inner task, and therefore
5539             --  cannot treat it as a local reference.
5540
5541             elsif Is_Overloadable (Scop) and then In_Open_Scopes (T) then
5542                return False;
5543
5544             else
5545                Scop := Scope (Scop);
5546             end if;
5547          end loop;
5548
5549          --  We know that we are within the task body, so should have found it
5550          --  in scope.
5551
5552          raise Program_Error;
5553       end Is_Current_Task;
5554
5555    --  Start of processing for Concurrent_Ref
5556
5557    begin
5558       if Is_Access_Type (Ntyp) then
5559          Dtyp := Designated_Type (Ntyp);
5560
5561          if Is_Protected_Type (Dtyp) then
5562             Sel := Name_uObject;
5563          else
5564             Sel := Name_uTask_Id;
5565          end if;
5566
5567          return
5568            Make_Selected_Component (Loc,
5569              Prefix        =>
5570                Unchecked_Convert_To (Corresponding_Record_Type (Dtyp),
5571                  Make_Explicit_Dereference (Loc, N)),
5572              Selector_Name => Make_Identifier (Loc, Sel));
5573
5574       elsif Is_Entity_Name (N) and then Is_Concurrent_Type (Entity (N)) then
5575          if Is_Task_Type (Entity (N)) then
5576
5577             if Is_Current_Task (Entity (N)) then
5578                return
5579                  Make_Function_Call (Loc,
5580                    Name => New_Occurrence_Of (RTE (RE_Self), Loc));
5581
5582             else
5583                declare
5584                   Decl   : Node_Id;
5585                   T_Self : constant Entity_Id := Make_Temporary (Loc, 'T');
5586                   T_Body : constant Node_Id :=
5587                              Parent (Corresponding_Body (Parent (Entity (N))));
5588
5589                begin
5590                   Decl :=
5591                     Make_Object_Declaration (Loc,
5592                       Defining_Identifier => T_Self,
5593                       Object_Definition   =>
5594                         New_Occurrence_Of (RTE (RO_ST_Task_Id), Loc),
5595                       Expression          =>
5596                         Make_Function_Call (Loc,
5597                           Name => New_Occurrence_Of (RTE (RE_Self), Loc)));
5598                   Prepend (Decl, Declarations (T_Body));
5599                   Analyze (Decl);
5600                   Set_Scope (T_Self, Entity (N));
5601                   return New_Occurrence_Of (T_Self,  Loc);
5602                end;
5603             end if;
5604
5605          else
5606             pragma Assert (Is_Protected_Type (Entity (N)));
5607
5608             return
5609               New_Occurrence_Of (Find_Protection_Object (Current_Scope), Loc);
5610          end if;
5611
5612       else
5613          if Is_Protected_Type (Ntyp) then
5614             Sel := Name_uObject;
5615          elsif Is_Task_Type (Ntyp) then
5616             Sel := Name_uTask_Id;
5617          else
5618             raise Program_Error;
5619          end if;
5620
5621          return
5622            Make_Selected_Component (Loc,
5623              Prefix        =>
5624                Unchecked_Convert_To (Corresponding_Record_Type (Ntyp),
5625                  New_Copy_Tree (N)),
5626              Selector_Name => Make_Identifier (Loc, Sel));
5627       end if;
5628    end Concurrent_Ref;
5629
5630    ------------------------
5631    -- Convert_Concurrent --
5632    ------------------------
5633
5634    function Convert_Concurrent
5635      (N   : Node_Id;
5636       Typ : Entity_Id) return Node_Id
5637    is
5638    begin
5639       if not Is_Concurrent_Type (Typ) then
5640          return N;
5641       else
5642          return
5643            Unchecked_Convert_To
5644              (Corresponding_Record_Type (Typ), New_Copy_Tree (N));
5645       end if;
5646    end Convert_Concurrent;
5647
5648    -------------------------------------
5649    -- Debug_Private_Data_Declarations --
5650    -------------------------------------
5651
5652    procedure Debug_Private_Data_Declarations (Decls : List_Id) is
5653       Debug_Nod : Node_Id;
5654       Decl      : Node_Id;
5655
5656    begin
5657       Decl := First (Decls);
5658       while Present (Decl) and then not Comes_From_Source (Decl) loop
5659
5660          --  Declaration for concurrent entity _object and its access type,
5661          --  along with the entry index subtype:
5662          --    type prot_typVP is access prot_typV;
5663          --    _object : prot_typVP := prot_typV (_O);
5664          --    subtype Jnn is <Type of Index> range Low .. High;
5665
5666          if Nkind_In (Decl, N_Full_Type_Declaration, N_Object_Declaration) then
5667             Set_Debug_Info_Needed (Defining_Identifier (Decl));
5668
5669          --  Declaration for the Protection object, discriminals, privals and
5670          --  entry index constant:
5671          --    conc_typR   : protection_typ renames _object._object;
5672          --    discr_nameD : discr_typ renames _object.discr_name;
5673          --    discr_nameD : discr_typ renames _task.discr_name;
5674          --    prival_name : comp_typ  renames _object.comp_name;
5675          --    J : constant Jnn :=
5676          --          Jnn'Val (_E - <Index expression> + Jnn'Pos (Jnn'First));
5677
5678          elsif Nkind (Decl) = N_Object_Renaming_Declaration then
5679             Set_Debug_Info_Needed (Defining_Identifier (Decl));
5680             Debug_Nod := Debug_Renaming_Declaration (Decl);
5681
5682             if Present (Debug_Nod) then
5683                Insert_After (Decl, Debug_Nod);
5684             end if;
5685          end if;
5686
5687          Next (Decl);
5688       end loop;
5689    end Debug_Private_Data_Declarations;
5690
5691    ------------------------------
5692    -- Ensure_Statement_Present --
5693    ------------------------------
5694
5695    procedure Ensure_Statement_Present (Loc : Source_Ptr; Alt : Node_Id) is
5696       Stmt : Node_Id;
5697
5698    begin
5699       if Opt.Suppress_Control_Flow_Optimizations
5700         and then Is_Empty_List (Statements (Alt))
5701       then
5702          Stmt := Make_Null_Statement (Loc);
5703
5704          --  Mark NULL statement as coming from source so that it is not
5705          --  eliminated by GIGI.
5706
5707          --  Another covert channel. If this is a requirement, it must be
5708          --  documented in sinfo/einfo ???
5709
5710          Set_Comes_From_Source (Stmt, True);
5711
5712          Set_Statements (Alt, New_List (Stmt));
5713       end if;
5714    end Ensure_Statement_Present;
5715
5716    ----------------------------
5717    -- Entry_Index_Expression --
5718    ----------------------------
5719
5720    function Entry_Index_Expression
5721      (Sloc  : Source_Ptr;
5722       Ent   : Entity_Id;
5723       Index : Node_Id;
5724       Ttyp  : Entity_Id) return Node_Id
5725    is
5726       Expr : Node_Id;
5727       Num  : Node_Id;
5728       Lo   : Node_Id;
5729       Hi   : Node_Id;
5730       Prev : Entity_Id;
5731       S    : Node_Id;
5732
5733    begin
5734       --  The queues of entries and entry families appear in textual order in
5735       --  the associated record. The entry index is computed as the sum of the
5736       --  number of queues for all entries that precede the designated one, to
5737       --  which is added the index expression, if this expression denotes a
5738       --  member of a family.
5739
5740       --  The following is a place holder for the count of simple entries
5741
5742       Num := Make_Integer_Literal (Sloc, 1);
5743
5744       --  We construct an expression which is a series of addition operations.
5745       --  The first operand is the number of single entries that precede this
5746       --  one, the second operand is the index value relative to the start of
5747       --  the referenced family, and the remaining operands are the lengths of
5748       --  the entry families that precede this entry, i.e. the constructed
5749       --  expression is:
5750
5751       --    number_simple_entries +
5752       --      (s'pos (index-value) - s'pos (family'first)) + 1 +
5753       --      family'length + ...
5754
5755       --  where index-value is the given index value, and s is the index
5756       --  subtype (we have to use pos because the subtype might be an
5757       --  enumeration type preventing direct subtraction). Note that the task
5758       --  entry array is one-indexed.
5759
5760       --  The upper bound of the entry family may be a discriminant, so we
5761       --  retrieve the lower bound explicitly to compute offset, rather than
5762       --  using the index subtype which may mention a discriminant.
5763
5764       if Present (Index) then
5765          S := Etype (Discrete_Subtype_Definition (Declaration_Node (Ent)));
5766
5767          Expr :=
5768            Make_Op_Add (Sloc,
5769              Left_Opnd  => Num,
5770              Right_Opnd =>
5771                Family_Offset
5772                  (Sloc,
5773                   Make_Attribute_Reference (Sloc,
5774                     Attribute_Name => Name_Pos,
5775                     Prefix         => New_Occurrence_Of (Base_Type (S), Sloc),
5776                     Expressions    => New_List (Relocate_Node (Index))),
5777                   Type_Low_Bound (S),
5778                   Ttyp,
5779                   False));
5780       else
5781          Expr := Num;
5782       end if;
5783
5784       --  Now add lengths of preceding entries and entry families
5785
5786       Prev := First_Entity (Ttyp);
5787       while Chars (Prev) /= Chars (Ent)
5788         or else (Ekind (Prev) /= Ekind (Ent))
5789         or else not Sem_Ch6.Type_Conformant (Ent, Prev)
5790       loop
5791          if Ekind (Prev) = E_Entry then
5792             Set_Intval (Num, Intval (Num) + 1);
5793
5794          elsif Ekind (Prev) = E_Entry_Family then
5795             S := Etype (Discrete_Subtype_Definition (Declaration_Node (Prev)));
5796             Lo := Type_Low_Bound  (S);
5797             Hi := Type_High_Bound (S);
5798
5799             Expr :=
5800               Make_Op_Add (Sloc,
5801                 Left_Opnd  => Expr,
5802                 Right_Opnd => Family_Size (Sloc, Hi, Lo, Ttyp, False));
5803
5804          --  Other components are anonymous types to be ignored
5805
5806          else
5807             null;
5808          end if;
5809
5810          Next_Entity (Prev);
5811       end loop;
5812
5813       return Expr;
5814    end Entry_Index_Expression;
5815
5816    ---------------------------
5817    -- Establish_Task_Master --
5818    ---------------------------
5819
5820    procedure Establish_Task_Master (N : Node_Id) is
5821       Call : Node_Id;
5822
5823    begin
5824       if Restriction_Active (No_Task_Hierarchy) = False then
5825          Call := Build_Runtime_Call (Sloc (N), RE_Enter_Master);
5826
5827          --  The block may have no declarations (and nevertheless be a task
5828          --  master) if it contains a call that may return an object that
5829          --  contains tasks.
5830
5831          if No (Declarations (N)) then
5832             Set_Declarations (N, New_List (Call));
5833          else
5834             Prepend_To (Declarations (N), Call);
5835          end if;
5836
5837          Analyze (Call);
5838       end if;
5839    end Establish_Task_Master;
5840
5841    --------------------------------
5842    -- Expand_Accept_Declarations --
5843    --------------------------------
5844
5845    --  Part of the expansion of an accept statement involves the creation of
5846    --  a declaration that can be referenced from the statement sequence of
5847    --  the accept:
5848
5849    --    Ann : Address;
5850
5851    --  This declaration is inserted immediately before the accept statement
5852    --  and it is important that it be inserted before the statements of the
5853    --  statement sequence are analyzed. Thus it would be too late to create
5854    --  this declaration in the Expand_N_Accept_Statement routine, which is
5855    --  why there is a separate procedure to be called directly from Sem_Ch9.
5856
5857    --  Ann is used to hold the address of the record containing the parameters
5858    --  (see Expand_N_Entry_Call for more details on how this record is built).
5859    --  References to the parameters do an unchecked conversion of this address
5860    --  to a pointer to the required record type, and then access the field that
5861    --  holds the value of the required parameter. The entity for the address
5862    --  variable is held as the top stack element (i.e. the last element) of the
5863    --  Accept_Address stack in the corresponding entry entity, and this element
5864    --  must be set in place  before the statements are processed.
5865
5866    --  The above description applies to the case of a stand alone accept
5867    --  statement, i.e. one not appearing as part of a select alternative.
5868
5869    --  For the case of an accept that appears as part of a select alternative
5870    --  of a selective accept, we must still create the declaration right away,
5871    --  since Ann is needed immediately, but there is an important difference:
5872
5873    --    The declaration is inserted before the selective accept, not before
5874    --    the accept statement (which is not part of a list anyway, and so would
5875    --    not accommodate inserted declarations)
5876
5877    --    We only need one address variable for the entire selective accept. So
5878    --    the Ann declaration is created only for the first accept alternative,
5879    --    and subsequent accept alternatives reference the same Ann variable.
5880
5881    --  We can distinguish the two cases by seeing whether the accept statement
5882    --  is part of a list. If not, then it must be in an accept alternative.
5883
5884    --  To expand the requeue statement, a label is provided at the end of the
5885    --  accept statement or alternative of which it is a part, so that the
5886    --  statement can be skipped after the requeue is complete. This label is
5887    --  created here rather than during the expansion of the accept statement,
5888    --  because it will be needed by any requeue statements within the accept,
5889    --  which are expanded before the accept.
5890
5891    procedure Expand_Accept_Declarations (N : Node_Id; Ent : Entity_Id) is
5892       Loc    : constant Source_Ptr := Sloc (N);
5893       Stats  : constant Node_Id    := Handled_Statement_Sequence (N);
5894       Ann    : Entity_Id           := Empty;
5895       Adecl  : Node_Id;
5896       Lab    : Node_Id;
5897       Ldecl  : Node_Id;
5898       Ldecl2 : Node_Id;
5899
5900    begin
5901       if Expander_Active then
5902
5903          --  If we have no handled statement sequence, we may need to build
5904          --  a dummy sequence consisting of a null statement. This can be
5905          --  skipped if the trivial accept optimization is permitted.
5906
5907          if not Trivial_Accept_OK
5908            and then (No (Stats) or else Null_Statements (Statements (Stats)))
5909          then
5910             Set_Handled_Statement_Sequence (N,
5911               Make_Handled_Sequence_Of_Statements (Loc,
5912                 Statements => New_List (Make_Null_Statement (Loc))));
5913          end if;
5914
5915          --  Create and declare two labels to be placed at the end of the
5916          --  accept statement. The first label is used to allow requeues to
5917          --  skip the remainder of entry processing. The second label is used
5918          --  to skip the remainder of entry processing if the rendezvous
5919          --  completes in the middle of the accept body.
5920
5921          if Present (Handled_Statement_Sequence (N)) then
5922             declare
5923                Ent : Entity_Id;
5924
5925             begin
5926                Ent := Make_Temporary (Loc, 'L');
5927                Lab := Make_Label (Loc, New_Occurrence_Of (Ent, Loc));
5928                Ldecl :=
5929                  Make_Implicit_Label_Declaration (Loc,
5930                    Defining_Identifier  => Ent,
5931                    Label_Construct      => Lab);
5932                Append (Lab, Statements (Handled_Statement_Sequence (N)));
5933
5934                Ent := Make_Temporary (Loc, 'L');
5935                Lab := Make_Label (Loc, New_Occurrence_Of (Ent, Loc));
5936                Ldecl2 :=
5937                  Make_Implicit_Label_Declaration (Loc,
5938                    Defining_Identifier  => Ent,
5939                    Label_Construct      => Lab);
5940                Append (Lab, Statements (Handled_Statement_Sequence (N)));
5941             end;
5942
5943          else
5944             Ldecl  := Empty;
5945             Ldecl2 := Empty;
5946          end if;
5947
5948          --  Case of stand alone accept statement
5949
5950          if Is_List_Member (N) then
5951
5952             if Present (Handled_Statement_Sequence (N)) then
5953                Ann := Make_Temporary (Loc, 'A');
5954
5955                Adecl :=
5956                  Make_Object_Declaration (Loc,
5957                    Defining_Identifier => Ann,
5958                    Object_Definition   =>
5959                      New_Occurrence_Of (RTE (RE_Address), Loc));
5960
5961                Insert_Before_And_Analyze (N, Adecl);
5962                Insert_Before_And_Analyze (N, Ldecl);
5963                Insert_Before_And_Analyze (N, Ldecl2);
5964             end if;
5965
5966          --  Case of accept statement which is in an accept alternative
5967
5968          else
5969             declare
5970                Acc_Alt : constant Node_Id := Parent (N);
5971                Sel_Acc : constant Node_Id := Parent (Acc_Alt);
5972                Alt     : Node_Id;
5973
5974             begin
5975                pragma Assert (Nkind (Acc_Alt) = N_Accept_Alternative);
5976                pragma Assert (Nkind (Sel_Acc) = N_Selective_Accept);
5977
5978                --  ??? Consider a single label for select statements
5979
5980                if Present (Handled_Statement_Sequence (N)) then
5981                   Prepend (Ldecl2,
5982                      Statements (Handled_Statement_Sequence (N)));
5983                   Analyze (Ldecl2);
5984
5985                   Prepend (Ldecl,
5986                      Statements (Handled_Statement_Sequence (N)));
5987                   Analyze (Ldecl);
5988                end if;
5989
5990                --  Find first accept alternative of the selective accept. A
5991                --  valid selective accept must have at least one accept in it.
5992
5993                Alt := First (Select_Alternatives (Sel_Acc));
5994
5995                while Nkind (Alt) /= N_Accept_Alternative loop
5996                   Next (Alt);
5997                end loop;
5998
5999                --  If this is the first accept statement, then we have to
6000                --  create the Ann variable, as for the stand alone case, except
6001                --  that it is inserted before the selective accept. Similarly,
6002                --  a label for requeue expansion must be declared.
6003
6004                if N = Accept_Statement (Alt) then
6005                   Ann := Make_Temporary (Loc, 'A');
6006                   Adecl :=
6007                     Make_Object_Declaration (Loc,
6008                       Defining_Identifier => Ann,
6009                       Object_Definition   =>
6010                         New_Occurrence_Of (RTE (RE_Address), Loc));
6011
6012                   Insert_Before_And_Analyze (Sel_Acc, Adecl);
6013
6014                --  If this is not the first accept statement, then find the Ann
6015                --  variable allocated by the first accept and use it.
6016
6017                else
6018                   Ann :=
6019                     Node (Last_Elmt (Accept_Address
6020                       (Entity (Entry_Direct_Name (Accept_Statement (Alt))))));
6021                end if;
6022             end;
6023          end if;
6024
6025          --  Merge here with Ann either created or referenced, and Adecl
6026          --  pointing to the corresponding declaration. Remaining processing
6027          --  is the same for the two cases.
6028
6029          if Present (Ann) then
6030             Append_Elmt (Ann, Accept_Address (Ent));
6031             Set_Debug_Info_Needed (Ann);
6032          end if;
6033
6034          --  Create renaming declarations for the entry formals. Each reference
6035          --  to a formal becomes a dereference of a component of the parameter
6036          --  block, whose address is held in Ann. These declarations are
6037          --  eventually inserted into the accept block, and analyzed there so
6038          --  that they have the proper scope for gdb and do not conflict with
6039          --  other declarations.
6040
6041          if Present (Parameter_Specifications (N))
6042            and then Present (Handled_Statement_Sequence (N))
6043          then
6044             declare
6045                Comp           : Entity_Id;
6046                Decl           : Node_Id;
6047                Formal         : Entity_Id;
6048                New_F          : Entity_Id;
6049                Renamed_Formal : Node_Id;
6050
6051             begin
6052                Push_Scope (Ent);
6053                Formal := First_Formal (Ent);
6054
6055                while Present (Formal) loop
6056                   Comp  := Entry_Component (Formal);
6057                   New_F := Make_Defining_Identifier (Loc, Chars (Formal));
6058
6059                   Set_Etype (New_F, Etype (Formal));
6060                   Set_Scope (New_F, Ent);
6061
6062                   --  Now we set debug info needed on New_F even though it does
6063                   --  not come from source, so that the debugger will get the
6064                   --  right information for these generated names.
6065
6066                   Set_Debug_Info_Needed (New_F);
6067
6068                   if Ekind (Formal) = E_In_Parameter then
6069                      Set_Ekind (New_F, E_Constant);
6070                   else
6071                      Set_Ekind (New_F, E_Variable);
6072                      Set_Extra_Constrained (New_F, Extra_Constrained (Formal));
6073                   end if;
6074
6075                   Set_Actual_Subtype (New_F, Actual_Subtype (Formal));
6076
6077                   Renamed_Formal :=
6078                      Make_Selected_Component (Loc,
6079                        Prefix        =>
6080                          Unchecked_Convert_To (
6081                            Entry_Parameters_Type (Ent),
6082                            New_Occurrence_Of (Ann, Loc)),
6083                        Selector_Name =>
6084                          New_Occurrence_Of (Comp, Loc));
6085
6086                   Decl :=
6087                     Build_Renamed_Formal_Declaration
6088                       (New_F, Formal, Comp, Renamed_Formal);
6089
6090                   if No (Declarations (N)) then
6091                      Set_Declarations (N, New_List);
6092                   end if;
6093
6094                   Append (Decl, Declarations (N));
6095                   Set_Renamed_Object (Formal, New_F);
6096                   Next_Formal (Formal);
6097                end loop;
6098
6099                End_Scope;
6100             end;
6101          end if;
6102       end if;
6103    end Expand_Accept_Declarations;
6104
6105    ---------------------------------------------
6106    -- Expand_Access_Protected_Subprogram_Type --
6107    ---------------------------------------------
6108
6109    procedure Expand_Access_Protected_Subprogram_Type (N : Node_Id) is
6110       Loc    : constant Source_Ptr := Sloc (N);
6111       Comps  : List_Id;
6112       T      : constant Entity_Id  := Defining_Identifier (N);
6113       D_T    : constant Entity_Id  := Designated_Type (T);
6114       D_T2   : constant Entity_Id  := Make_Temporary (Loc, 'D');
6115       E_T    : constant Entity_Id  := Make_Temporary (Loc, 'E');
6116       P_List : constant List_Id    := Build_Protected_Spec
6117                                         (N, RTE (RE_Address), D_T, False);
6118       Decl1  : Node_Id;
6119       Decl2  : Node_Id;
6120       Def1   : Node_Id;
6121
6122    begin
6123       --  Create access to subprogram with full signature
6124
6125       if Etype (D_T) /= Standard_Void_Type then
6126          Def1 :=
6127            Make_Access_Function_Definition (Loc,
6128              Parameter_Specifications => P_List,
6129              Result_Definition =>
6130                Copy_Result_Type (Result_Definition (Type_Definition (N))));
6131
6132       else
6133          Def1 :=
6134            Make_Access_Procedure_Definition (Loc,
6135              Parameter_Specifications => P_List);
6136       end if;
6137
6138       Decl1 :=
6139         Make_Full_Type_Declaration (Loc,
6140           Defining_Identifier => D_T2,
6141           Type_Definition     => Def1);
6142
6143       Insert_After_And_Analyze (N, Decl1);
6144
6145       --  Associate the access to subprogram with its original access to
6146       --  protected subprogram type. Needed by the backend to know that this
6147       --  type corresponds with an access to protected subprogram type.
6148
6149       Set_Original_Access_Type (D_T2, T);
6150
6151       --  Create Equivalent_Type, a record with two components for an access to
6152       --  object and an access to subprogram.
6153
6154       Comps := New_List (
6155         Make_Component_Declaration (Loc,
6156           Defining_Identifier  => Make_Temporary (Loc, 'P'),
6157           Component_Definition =>
6158             Make_Component_Definition (Loc,
6159               Aliased_Present    => False,
6160               Subtype_Indication =>
6161                 New_Occurrence_Of (RTE (RE_Address), Loc))),
6162
6163         Make_Component_Declaration (Loc,
6164           Defining_Identifier  => Make_Temporary (Loc, 'S'),
6165           Component_Definition =>
6166             Make_Component_Definition (Loc,
6167               Aliased_Present    => False,
6168               Subtype_Indication => New_Occurrence_Of (D_T2, Loc))));
6169
6170       Decl2 :=
6171         Make_Full_Type_Declaration (Loc,
6172           Defining_Identifier => E_T,
6173           Type_Definition     =>
6174             Make_Record_Definition (Loc,
6175               Component_List =>
6176                 Make_Component_List (Loc, Component_Items => Comps)));
6177
6178       Insert_After_And_Analyze (Decl1, Decl2);
6179       Set_Equivalent_Type (T, E_T);
6180    end Expand_Access_Protected_Subprogram_Type;
6181
6182    --------------------------
6183    -- Expand_Entry_Barrier --
6184    --------------------------
6185
6186    procedure Expand_Entry_Barrier (N : Node_Id; Ent : Entity_Id) is
6187       Cond      : constant Node_Id   :=
6188                     Condition (Entry_Body_Formal_Part (N));
6189       Prot      : constant Entity_Id := Scope (Ent);
6190       Spec_Decl : constant Node_Id   := Parent (Prot);
6191       Func      : Entity_Id          := Empty;
6192       B_F       : Node_Id;
6193       Body_Decl : Node_Id;
6194
6195       function Is_Global_Entity (N : Node_Id) return Traverse_Result;
6196       --  Check whether entity in Barrier is external to protected type.
6197       --  If so, barrier may not be properly synchronized.
6198
6199       ----------------------
6200       -- Is_Global_Entity --
6201       ----------------------
6202
6203       function Is_Global_Entity (N : Node_Id) return Traverse_Result is
6204          E : Entity_Id;
6205          S : Entity_Id;
6206
6207       begin
6208          if Is_Entity_Name (N) and then Present (Entity (N)) then
6209             E := Entity (N);
6210             S := Scope  (E);
6211
6212             if Ekind (E) = E_Variable then
6213
6214                --  If the variable is local to the barrier function generated
6215                --  during expansion, it is ok. If expansion is not performed,
6216                --  then Func is Empty so this test cannot succeed.
6217
6218                if Scope (E) = Func then
6219                   null;
6220
6221                --  A protected call from a barrier to another object is ok
6222
6223                elsif Ekind (Etype (E)) = E_Protected_Type then
6224                   null;
6225
6226                --  If the variable is within the package body we consider
6227                --  this safe. This is a common (if dubious) idiom.
6228
6229                elsif S = Scope (Prot)
6230                  and then Ekind_In (S, E_Package, E_Generic_Package)
6231                  and then Nkind (Parent (E)) = N_Object_Declaration
6232                  and then Nkind (Parent (Parent (E))) = N_Package_Body
6233                then
6234                   null;
6235
6236                else
6237                   Error_Msg_N ("potentially unsynchronized barrier??", N);
6238                   Error_Msg_N ("\& should be private component of type??", N);
6239                end if;
6240             end if;
6241          end if;
6242
6243          return OK;
6244       end Is_Global_Entity;
6245
6246       procedure Check_Unprotected_Barrier is
6247         new Traverse_Proc (Is_Global_Entity);
6248
6249    --  Start of processing for Expand_Entry_Barrier
6250
6251    begin
6252       if No_Run_Time_Mode then
6253          Error_Msg_CRT ("entry barrier", N);
6254          return;
6255       end if;
6256
6257       --  The body of the entry barrier must be analyzed in the context of the
6258       --  protected object, but its scope is external to it, just as any other
6259       --  unprotected version of a protected operation. The specification has
6260       --  been produced when the protected type declaration was elaborated. We
6261       --  build the body, insert it in the enclosing scope, but analyze it in
6262       --  the current context. A more uniform approach would be to treat the
6263       --  barrier just as a protected function, and discard the protected
6264       --  version of it because it is never called.
6265
6266       if Expander_Active then
6267          B_F  := Build_Barrier_Function (N, Ent, Prot);
6268          Func := Barrier_Function (Ent);
6269          Set_Corresponding_Spec (B_F, Func);
6270
6271          Body_Decl := Parent (Corresponding_Body (Spec_Decl));
6272
6273          if Nkind (Parent (Body_Decl)) = N_Subunit then
6274             Body_Decl := Corresponding_Stub (Parent (Body_Decl));
6275          end if;
6276
6277          Insert_Before_And_Analyze (Body_Decl, B_F);
6278
6279          Set_Discriminals (Spec_Decl);
6280          Set_Scope (Func, Scope (Prot));
6281
6282       else
6283          Analyze_And_Resolve (Cond, Any_Boolean);
6284       end if;
6285
6286       --  The Ravenscar profile restricts barriers to simple variables declared
6287       --  within the protected object. We also allow Boolean constants, since
6288       --  these appear in several published examples and are also allowed by
6289       --  other compilers.
6290
6291       --  Note that after analysis variables in this context will be replaced
6292       --  by the corresponding prival, that is to say a renaming of a selected
6293       --  component of the form _Object.Var. If expansion is disabled, as
6294       --  within a generic, we check that the entity appears in the current
6295       --  scope.
6296
6297       if Is_Entity_Name (Cond) then
6298
6299          --  A small optimization of useless renamings. If the scope of the
6300          --  entity of the condition is not the barrier function, then the
6301          --  condition does not reference any of the generated renamings
6302          --  within the function.
6303
6304          if Expander_Active and then Scope (Entity (Cond)) /= Func then
6305             Set_Declarations (B_F, Empty_List);
6306          end if;
6307
6308          if Entity (Cond) = Standard_False
6309               or else
6310             Entity (Cond) = Standard_True
6311          then
6312             return;
6313
6314          elsif not Expander_Active
6315            and then Scope (Entity (Cond)) = Current_Scope
6316          then
6317             return;
6318
6319          --  Check for case of _object.all.field (note that the explicit
6320          --  dereference gets inserted by analyze/expand of _object.field)
6321
6322          elsif Present (Renamed_Object (Entity (Cond)))
6323            and then
6324              Nkind (Renamed_Object (Entity (Cond))) = N_Selected_Component
6325            and then
6326              Chars
6327                (Prefix
6328                  (Prefix (Renamed_Object (Entity (Cond))))) = Name_uObject
6329          then
6330             return;
6331          end if;
6332       end if;
6333
6334       --  It is not a boolean variable or literal, so check the restriction.
6335       --  Note that it is safe to be calling Check_Restriction from here, even
6336       --  though this is part of the expander, since Expand_Entry_Barrier is
6337       --  called from Sem_Ch9 even in -gnatc mode.
6338
6339       Check_Restriction (Simple_Barriers, Cond);
6340
6341       --  Emit warning if barrier contains global entities and is thus
6342       --  potentially unsynchronized.
6343
6344       Check_Unprotected_Barrier (Cond);
6345    end Expand_Entry_Barrier;
6346
6347    ------------------------------
6348    -- Expand_N_Abort_Statement --
6349    ------------------------------
6350
6351    --  Expand abort T1, T2, .. Tn; into:
6352    --    Abort_Tasks (Task_List'(1 => T1.Task_Id, 2 => T2.Task_Id ...))
6353
6354    procedure Expand_N_Abort_Statement (N : Node_Id) is
6355       Loc    : constant Source_Ptr := Sloc (N);
6356       Tlist  : constant List_Id    := Names (N);
6357       Count  : Nat;
6358       Aggr   : Node_Id;
6359       Tasknm : Node_Id;
6360
6361    begin
6362       Aggr := Make_Aggregate (Loc, Component_Associations => New_List);
6363       Count := 0;
6364
6365       Tasknm := First (Tlist);
6366
6367       while Present (Tasknm) loop
6368          Count := Count + 1;
6369
6370          --  A task interface class-wide type object is being aborted. Retrieve
6371          --  its _task_id by calling a dispatching routine.
6372
6373          if Ada_Version >= Ada_2005
6374            and then Ekind (Etype (Tasknm)) = E_Class_Wide_Type
6375            and then Is_Interface (Etype (Tasknm))
6376            and then Is_Task_Interface (Etype (Tasknm))
6377          then
6378             Append_To (Component_Associations (Aggr),
6379               Make_Component_Association (Loc,
6380                 Choices    => New_List (Make_Integer_Literal (Loc, Count)),
6381                 Expression =>
6382
6383                   --  Task_Id (Tasknm._disp_get_task_id)
6384
6385                   Make_Unchecked_Type_Conversion (Loc,
6386                     Subtype_Mark =>
6387                       New_Occurrence_Of (RTE (RO_ST_Task_Id), Loc),
6388                     Expression   =>
6389                       Make_Selected_Component (Loc,
6390                         Prefix        => New_Copy_Tree (Tasknm),
6391                         Selector_Name =>
6392                           Make_Identifier (Loc, Name_uDisp_Get_Task_Id)))));
6393
6394          else
6395             Append_To (Component_Associations (Aggr),
6396               Make_Component_Association (Loc,
6397                 Choices    => New_List (Make_Integer_Literal (Loc, Count)),
6398                 Expression => Concurrent_Ref (Tasknm)));
6399          end if;
6400
6401          Next (Tasknm);
6402       end loop;
6403
6404       Rewrite (N,
6405         Make_Procedure_Call_Statement (Loc,
6406           Name => New_Occurrence_Of (RTE (RE_Abort_Tasks), Loc),
6407           Parameter_Associations => New_List (
6408             Make_Qualified_Expression (Loc,
6409               Subtype_Mark => New_Occurrence_Of (RTE (RE_Task_List), Loc),
6410               Expression   => Aggr))));
6411
6412       Analyze (N);
6413    end Expand_N_Abort_Statement;
6414
6415    -------------------------------
6416    -- Expand_N_Accept_Statement --
6417    -------------------------------
6418
6419    --  This procedure handles expansion of accept statements that stand alone,
6420    --  i.e. they are not part of an accept alternative. The expansion of
6421    --  accept statement in accept alternatives is handled by the routines
6422    --  Expand_N_Accept_Alternative and Expand_N_Selective_Accept. The
6423    --  following description applies only to stand alone accept statements.
6424
6425    --  If there is no handled statement sequence, or only null statements, then
6426    --  this is called a trivial accept, and the expansion is:
6427
6428    --    Accept_Trivial (entry-index)
6429
6430    --  If there is a handled statement sequence, then the expansion is:
6431
6432    --    Ann : Address;
6433    --    {Lnn : Label}
6434
6435    --    begin
6436    --       begin
6437    --          Accept_Call (entry-index, Ann);
6438    --          Renaming_Declarations for formals
6439    --          <statement sequence from N_Accept_Statement node>
6440    --          Complete_Rendezvous;
6441    --          <<Lnn>>
6442    --
6443    --       exception
6444    --          when ... =>
6445    --             <exception handler from N_Accept_Statement node>
6446    --             Complete_Rendezvous;
6447    --          when ... =>
6448    --             <exception handler from N_Accept_Statement node>
6449    --             Complete_Rendezvous;
6450    --          ...
6451    --       end;
6452
6453    --    exception
6454    --       when all others =>
6455    --          Exceptional_Complete_Rendezvous (Get_GNAT_Exception);
6456    --    end;
6457
6458    --  The first three declarations were already inserted ahead of the accept
6459    --  statement by the Expand_Accept_Declarations procedure, which was called
6460    --  directly from the semantics during analysis of the accept statement,
6461    --  before analyzing its contained statements.
6462
6463    --  The declarations from the N_Accept_Statement, as noted in Sinfo, come
6464    --  from possible expansion activity (the original source of course does
6465    --  not have any declarations associated with the accept statement, since
6466    --  an accept statement has no declarative part). In particular, if the
6467    --  expander is active, the first such declaration is the declaration of
6468    --  the Accept_Params_Ptr entity (see Sem_Ch9.Analyze_Accept_Statement).
6469
6470    --  The two blocks are merged into a single block if the inner block has
6471    --  no exception handlers, but otherwise two blocks are required, since
6472    --  exceptions might be raised in the exception handlers of the inner
6473    --  block, and Exceptional_Complete_Rendezvous must be called.
6474
6475    procedure Expand_N_Accept_Statement (N : Node_Id) is
6476       Loc     : constant Source_Ptr := Sloc (N);
6477       Stats   : constant Node_Id    := Handled_Statement_Sequence (N);
6478       Ename   : constant Node_Id    := Entry_Direct_Name (N);
6479       Eindx   : constant Node_Id    := Entry_Index (N);
6480       Eent    : constant Entity_Id  := Entity (Ename);
6481       Acstack : constant Elist_Id   := Accept_Address (Eent);
6482       Ann     : constant Entity_Id  := Node (Last_Elmt (Acstack));
6483       Ttyp    : constant Entity_Id  := Etype (Scope (Eent));
6484       Blkent  : Entity_Id;
6485       Call    : Node_Id;
6486       Block   : Node_Id;
6487
6488    begin
6489       --  If the accept statement is not part of a list, then its parent must
6490       --  be an accept alternative, and, as described above, we do not do any
6491       --  expansion for such accept statements at this level.
6492
6493       if not Is_List_Member (N) then
6494          pragma Assert (Nkind (Parent (N)) = N_Accept_Alternative);
6495          return;
6496
6497       --  Trivial accept case (no statement sequence, or null statements).
6498       --  If the accept statement has declarations, then just insert them
6499       --  before the procedure call.
6500
6501       elsif Trivial_Accept_OK
6502         and then (No (Stats) or else Null_Statements (Statements (Stats)))
6503       then
6504          --  Remove declarations for renamings, because the parameter block
6505          --  will not be assigned.
6506
6507          declare
6508             D      : Node_Id;
6509             Next_D : Node_Id;
6510
6511          begin
6512             D := First (Declarations (N));
6513             while Present (D) loop
6514                Next_D := Next (D);
6515                if Nkind (D) = N_Object_Renaming_Declaration then
6516                   Remove (D);
6517                end if;
6518
6519                D := Next_D;
6520             end loop;
6521          end;
6522
6523          if Present (Declarations (N)) then
6524             Insert_Actions (N, Declarations (N));
6525          end if;
6526
6527          Rewrite (N,
6528            Make_Procedure_Call_Statement (Loc,
6529              Name => New_Occurrence_Of (RTE (RE_Accept_Trivial), Loc),
6530              Parameter_Associations => New_List (
6531                Entry_Index_Expression (Loc, Entity (Ename), Eindx, Ttyp))));
6532
6533          Analyze (N);
6534
6535          --  Discard Entry_Address that was created for it, so it will not be
6536          --  emitted if this accept statement is in the statement part of a
6537          --  delay alternative.
6538
6539          if Present (Stats) then
6540             Remove_Last_Elmt (Acstack);
6541          end if;
6542
6543       --  Case of statement sequence present
6544
6545       else
6546          --  Construct the block, using the declarations from the accept
6547          --  statement if any to initialize the declarations of the block.
6548
6549          Blkent := Make_Temporary (Loc, 'A');
6550          Set_Ekind (Blkent, E_Block);
6551          Set_Etype (Blkent, Standard_Void_Type);
6552          Set_Scope (Blkent, Current_Scope);
6553
6554          Block :=
6555            Make_Block_Statement (Loc,
6556              Identifier                 => New_Occurrence_Of (Blkent, Loc),
6557              Declarations               => Declarations (N),
6558              Handled_Statement_Sequence => Build_Accept_Body (N));
6559
6560          --  For the analysis of the generated declarations, the parent node
6561          --  must be properly set.
6562
6563          Set_Parent (Block, Parent (N));
6564
6565          --  Prepend call to Accept_Call to main statement sequence If the
6566          --  accept has exception handlers, the statement sequence is wrapped
6567          --  in a block. Insert call and renaming declarations in the
6568          --  declarations of the block, so they are elaborated before the
6569          --  handlers.
6570
6571          Call :=
6572            Make_Procedure_Call_Statement (Loc,
6573              Name => New_Occurrence_Of (RTE (RE_Accept_Call), Loc),
6574              Parameter_Associations => New_List (
6575                Entry_Index_Expression (Loc, Entity (Ename), Eindx, Ttyp),
6576                New_Occurrence_Of (Ann, Loc)));
6577
6578          if Parent (Stats) = N then
6579             Prepend (Call, Statements (Stats));
6580          else
6581             Set_Declarations (Parent (Stats), New_List (Call));
6582          end if;
6583
6584          Analyze (Call);
6585
6586          Push_Scope (Blkent);
6587
6588          declare
6589             D      : Node_Id;
6590             Next_D : Node_Id;
6591             Typ    : Entity_Id;
6592
6593          begin
6594             D := First (Declarations (N));
6595             while Present (D) loop
6596                Next_D := Next (D);
6597
6598                if Nkind (D) = N_Object_Renaming_Declaration then
6599
6600                   --  The renaming declarations for the formals were created
6601                   --  during analysis of the accept statement, and attached to
6602                   --  the list of declarations. Place them now in the context
6603                   --  of the accept block or subprogram.
6604
6605                   Remove (D);
6606                   Typ := Entity (Subtype_Mark (D));
6607                   Insert_After (Call, D);
6608                   Analyze (D);
6609
6610                   --  If the formal is class_wide, it does not have an actual
6611                   --  subtype. The analysis of the renaming declaration creates
6612                   --  one, but we need to retain the class-wide nature of the
6613                   --  entity.
6614
6615                   if Is_Class_Wide_Type (Typ) then
6616                      Set_Etype (Defining_Identifier (D), Typ);
6617                   end if;
6618
6619                end if;
6620
6621                D := Next_D;
6622             end loop;
6623          end;
6624
6625          End_Scope;
6626
6627          --  Replace the accept statement by the new block
6628
6629          Rewrite (N, Block);
6630          Analyze (N);
6631
6632          --  Last step is to unstack the Accept_Address value
6633
6634          Remove_Last_Elmt (Acstack);
6635       end if;
6636    end Expand_N_Accept_Statement;
6637
6638    ----------------------------------
6639    -- Expand_N_Asynchronous_Select --
6640    ----------------------------------
6641
6642    --  This procedure assumes that the trigger statement is an entry call or
6643    --  a dispatching procedure call. A delay alternative should already have
6644    --  been expanded into an entry call to the appropriate delay object Wait
6645    --  entry.
6646
6647    --  If the trigger is a task entry call, the select is implemented with
6648    --  a Task_Entry_Call:
6649
6650    --    declare
6651    --       B : Boolean;
6652    --       C : Boolean;
6653    --       P : parms := (parm, parm, parm);
6654
6655    --        --  Clean is added by Exp_Ch7.Expand_Cleanup_Actions
6656
6657    --       procedure _clean is
6658    --       begin
6659    --          ...
6660    --          Cancel_Task_Entry_Call (C);
6661    --          ...
6662    --       end _clean;
6663
6664    --    begin
6665    --       Abort_Defer;
6666    --       Task_Entry_Call
6667    --         (<acceptor-task>,    --  Acceptor
6668    --          <entry-index>,      --  E
6669    --          P'Address,          --  Uninterpreted_Data
6670    --          Asynchronous_Call,  --  Mode
6671    --          B);                 --  Rendezvous_Successful
6672
6673    --       begin
6674    --          begin
6675    --             Abort_Undefer;
6676    --             <abortable-part>
6677    --          at end
6678    --             _clean;  --  Added by Exp_Ch7.Expand_Cleanup_Actions
6679    --          end;
6680    --       exception
6681    --          when Abort_Signal => Abort_Undefer;
6682    --       end;
6683
6684    --       parm := P.param;
6685    --       parm := P.param;
6686    --       ...
6687    --       if not C then
6688    --          <triggered-statements>
6689    --       end if;
6690    --    end;
6691
6692    --  Note that Build_Simple_Entry_Call is used to expand the entry of the
6693    --  asynchronous entry call (by Expand_N_Entry_Call_Statement procedure)
6694    --  as follows:
6695
6696    --    declare
6697    --       P : parms := (parm, parm, parm);
6698    --    begin
6699    --       Call_Simple (acceptor-task, entry-index, P'Address);
6700    --       parm := P.param;
6701    --       parm := P.param;
6702    --       ...
6703    --    end;
6704
6705    --  so the task at hand is to convert the latter expansion into the former
6706
6707    --  If the trigger is a protected entry call, the select is implemented
6708    --  with Protected_Entry_Call:
6709
6710    --  declare
6711    --     P   : E1_Params := (param, param, param);
6712    --     Bnn : Communications_Block;
6713
6714    --  begin
6715    --     declare
6716
6717    --        --  Clean is added by Exp_Ch7.Expand_Cleanup_Actions
6718
6719    --        procedure _clean is
6720    --        begin
6721    --           ...
6722    --           if Enqueued (Bnn) then
6723    --              Cancel_Protected_Entry_Call (Bnn);
6724    --           end if;
6725    --           ...
6726    --        end _clean;
6727
6728    --     begin
6729    --        begin
6730    --           Protected_Entry_Call
6731    --             (po._object'Access,  --  Object
6732    --              <entry index>,      --  E
6733    --              P'Address,          --  Uninterpreted_Data
6734    --              Asynchronous_Call,  --  Mode
6735    --              Bnn);               --  Block
6736
6737    --           if Enqueued (Bnn) then
6738    --              <abortable-part>
6739    --           end if;
6740    --        at end
6741    --           _clean;  --  Added by Exp_Ch7.Expand_Cleanup_Actions
6742    --        end;
6743    --     exception
6744    --        when Abort_Signal => Abort_Undefer;
6745    --     end;
6746
6747    --     if not Cancelled (Bnn) then
6748    --        <triggered-statements>
6749    --     end if;
6750    --  end;
6751
6752    --  Build_Simple_Entry_Call is used to expand the all to a simple protected
6753    --  entry call:
6754
6755    --  declare
6756    --     P   : E1_Params := (param, param, param);
6757    --     Bnn : Communications_Block;
6758
6759    --  begin
6760    --     Protected_Entry_Call
6761    --       (po._object'Access,  --  Object
6762    --        <entry index>,      --  E
6763    --        P'Address,          --  Uninterpreted_Data
6764    --        Simple_Call,        --  Mode
6765    --        Bnn);               --  Block
6766    --     parm := P.param;
6767    --     parm := P.param;
6768    --       ...
6769    --  end;
6770
6771    --  Ada 2005 (AI-345): If the trigger is a dispatching call, the select is
6772    --  expanded into:
6773
6774    --    declare
6775    --       B   : Boolean := False;
6776    --       Bnn : Communication_Block;
6777    --       C   : Ada.Tags.Prim_Op_Kind;
6778    --       D   : System.Storage_Elements.Dummy_Communication_Block;
6779    --       K   : Ada.Tags.Tagged_Kind :=
6780    --               Ada.Tags.Get_Tagged_Kind (Ada.Tags.Tag (<object>));
6781    --       P   : Parameters := (Param1 .. ParamN);
6782    --       S   : Integer;
6783    --       U   : Boolean;
6784
6785    --    begin
6786    --       if K = Ada.Tags.TK_Limited_Tagged
6787    --         or else K = Ada.Tags.TK_Tagged
6788    --       then
6789    --          <dispatching-call>;
6790    --          <triggering-statements>;
6791
6792    --       else
6793    --          S :=
6794    --            Ada.Tags.Get_Offset_Index
6795    --              (Ada.Tags.Tag (<object>), DT_Position (<dispatching-call>));
6796
6797    --          _Disp_Get_Prim_Op_Kind (<object>, S, C);
6798
6799    --          if C = POK_Protected_Entry then
6800    --             declare
6801    --                procedure _clean is
6802    --                begin
6803    --                   if Enqueued (Bnn) then
6804    --                      Cancel_Protected_Entry_Call (Bnn);
6805    --                   end if;
6806    --                end _clean;
6807
6808    --             begin
6809    --                begin
6810    --                   _Disp_Asynchronous_Select
6811    --                     (<object>, S, P'Address, D, B);
6812    --                   Bnn := Communication_Block (D);
6813
6814    --                   Param1 := P.Param1;
6815    --                   ...
6816    --                   ParamN := P.ParamN;
6817
6818    --                   if Enqueued (Bnn) then
6819    --                      <abortable-statements>
6820    --                   end if;
6821    --                at end
6822    --                   _clean;  --  Added by Exp_Ch7.Expand_Cleanup_Actions
6823    --                end;
6824    --             exception
6825    --                when Abort_Signal => Abort_Undefer;
6826    --             end;
6827
6828    --             if not Cancelled (Bnn) then
6829    --                <triggering-statements>
6830    --             end if;
6831
6832    --          elsif C = POK_Task_Entry then
6833    --             declare
6834    --                procedure _clean is
6835    --                begin
6836    --                   Cancel_Task_Entry_Call (U);
6837    --                end _clean;
6838
6839    --             begin
6840    --                Abort_Defer;
6841
6842    --                _Disp_Asynchronous_Select
6843    --                  (<object>, S, P'Address, D, B);
6844    --                Bnn := Communication_Bloc (D);
6845
6846    --                Param1 := P.Param1;
6847    --                ...
6848    --                ParamN := P.ParamN;
6849
6850    --                begin
6851    --                   begin
6852    --                      Abort_Undefer;
6853    --                      <abortable-statements>
6854    --                   at end
6855    --                      _clean;  --  Added by Exp_Ch7.Expand_Cleanup_Actions
6856    --                   end;
6857    --                exception
6858    --                   when Abort_Signal => Abort_Undefer;
6859    --                end;
6860
6861    --                if not U then
6862    --                   <triggering-statements>
6863    --                end if;
6864    --             end;
6865
6866    --          else
6867    --             <dispatching-call>;
6868    --             <triggering-statements>
6869    --          end if;
6870    --       end if;
6871    --    end;
6872
6873    --  The job is to convert this to the asynchronous form
6874
6875    --  If the trigger is a delay statement, it will have been expanded into
6876    --  a call to one of the GNARL delay procedures. This routine will convert
6877    --  this into a protected entry call on a delay object and then continue
6878    --  processing as for a protected entry call trigger. This requires
6879    --  declaring a Delay_Block object and adding a pointer to this object to
6880    --  the parameter list of the delay procedure to form the parameter list of
6881    --  the entry call. This object is used by the runtime to queue the delay
6882    --  request.
6883
6884    --  For a description of the use of P and the assignments after the call,
6885    --  see Expand_N_Entry_Call_Statement.
6886
6887    procedure Expand_N_Asynchronous_Select (N : Node_Id) is
6888       Loc  : constant Source_Ptr := Sloc (N);
6889       Abrt : constant Node_Id    := Abortable_Part (N);
6890       Trig : constant Node_Id    := Triggering_Alternative (N);
6891
6892       Abort_Block_Ent   : Entity_Id;
6893       Abortable_Block   : Node_Id;
6894       Actuals           : List_Id;
6895       Astats            : List_Id;
6896       Blk_Ent           : constant Entity_Id := Make_Temporary (Loc, 'A');
6897       Blk_Typ           : Entity_Id;
6898       Call              : Node_Id;
6899       Call_Ent          : Entity_Id;
6900       Cancel_Param      : Entity_Id;
6901       Cleanup_Block     : Node_Id;
6902       Cleanup_Block_Ent : Entity_Id;
6903       Cleanup_Stmts     : List_Id;
6904       Conc_Typ_Stmts    : List_Id;
6905       Concval           : Node_Id;
6906       Dblock_Ent        : Entity_Id;
6907       Decl              : Node_Id;
6908       Decls             : List_Id;
6909       Ecall             : Node_Id;
6910       Ename             : Node_Id;
6911       Enqueue_Call      : Node_Id;
6912       Formals           : List_Id;
6913       Hdle              : List_Id;
6914       Handler_Stmt      : Node_Id;
6915       Index             : Node_Id;
6916       Lim_Typ_Stmts     : List_Id;
6917       N_Orig            : Node_Id;
6918       Obj               : Entity_Id;
6919       Param             : Node_Id;
6920       Params            : List_Id;
6921       Pdef              : Entity_Id;
6922       ProtE_Stmts       : List_Id;
6923       ProtP_Stmts       : List_Id;
6924       Stmt              : Node_Id;
6925       Stmts             : List_Id;
6926       TaskE_Stmts       : List_Id;
6927       Tstats            : List_Id;
6928
6929       B   : Entity_Id;  --  Call status flag
6930       Bnn : Entity_Id;  --  Communication block
6931       C   : Entity_Id;  --  Call kind
6932       K   : Entity_Id;  --  Tagged kind
6933       P   : Entity_Id;  --  Parameter block
6934       S   : Entity_Id;  --  Primitive operation slot
6935       T   : Entity_Id;  --  Additional status flag
6936
6937       procedure Rewrite_Abortable_Part;
6938       --  If the trigger is a dispatching call, the expansion inserts multiple
6939       --  copies of the abortable part. This is both inefficient, and may lead
6940       --  to duplicate definitions that the back-end will reject, when the
6941       --  abortable part includes loops. This procedure rewrites the abortable
6942       --  part into a call to a generated procedure.
6943
6944       ----------------------------
6945       -- Rewrite_Abortable_Part --
6946       ----------------------------
6947
6948       procedure Rewrite_Abortable_Part is
6949          Proc : constant Entity_Id := Make_Defining_Identifier (Loc, Name_uA);
6950          Decl : Node_Id;
6951
6952       begin
6953          Decl :=
6954            Make_Subprogram_Body (Loc,
6955              Specification              =>
6956                Make_Procedure_Specification (Loc, Defining_Unit_Name => Proc),
6957              Declarations               => New_List,
6958              Handled_Statement_Sequence =>
6959                Make_Handled_Sequence_Of_Statements (Loc, Astats));
6960          Insert_Before (N, Decl);
6961          Analyze (Decl);
6962
6963          --  Rewrite abortable part into a call to this procedure.
6964
6965          Astats :=
6966            New_List (
6967              Make_Procedure_Call_Statement (Loc,
6968                Name => New_Occurrence_Of (Proc, Loc)));
6969       end Rewrite_Abortable_Part;
6970
6971    begin
6972       Process_Statements_For_Controlled_Objects (Trig);
6973       Process_Statements_For_Controlled_Objects (Abrt);
6974
6975       Ecall := Triggering_Statement (Trig);
6976
6977       Ensure_Statement_Present (Sloc (Ecall), Trig);
6978
6979       --  Retrieve Astats and Tstats now because the finalization machinery may
6980       --  wrap them in blocks.
6981
6982       Astats := Statements (Abrt);
6983       Tstats := Statements (Trig);
6984
6985       --  The arguments in the call may require dynamic allocation, and the
6986       --  call statement may have been transformed into a block. The block
6987       --  may contain additional declarations for internal entities, and the
6988       --  original call is found by sequential search.
6989
6990       if Nkind (Ecall) = N_Block_Statement then
6991          Ecall := First (Statements (Handled_Statement_Sequence (Ecall)));
6992          while not Nkind_In (Ecall, N_Procedure_Call_Statement,
6993                                     N_Entry_Call_Statement)
6994          loop
6995             Next (Ecall);
6996          end loop;
6997       end if;
6998
6999       --  This is either a dispatching call or a delay statement used as a
7000       --  trigger which was expanded into a procedure call.
7001
7002       if Nkind (Ecall) = N_Procedure_Call_Statement then
7003          if Ada_Version >= Ada_2005
7004            and then
7005              (No (Original_Node (Ecall))
7006                or else not Nkind_In (Original_Node (Ecall),
7007                                      N_Delay_Relative_Statement,
7008                                      N_Delay_Until_Statement))
7009          then
7010             Extract_Dispatching_Call (Ecall, Call_Ent, Obj, Actuals, Formals);
7011
7012             Rewrite_Abortable_Part;
7013             Decls := New_List;
7014             Stmts := New_List;
7015
7016             --  Call status flag processing, generate:
7017             --    B : Boolean := False;
7018
7019             B := Build_B (Loc, Decls);
7020
7021             --  Communication block processing, generate:
7022             --    Bnn : Communication_Block;
7023
7024             Bnn := Make_Temporary (Loc, 'B');
7025             Append_To (Decls,
7026               Make_Object_Declaration (Loc,
7027                 Defining_Identifier => Bnn,
7028                 Object_Definition   =>
7029                   New_Occurrence_Of (RTE (RE_Communication_Block), Loc)));
7030
7031             --  Call kind processing, generate:
7032             --    C : Ada.Tags.Prim_Op_Kind;
7033
7034             C := Build_C (Loc, Decls);
7035
7036             --  Tagged kind processing, generate:
7037             --    K : Ada.Tags.Tagged_Kind :=
7038             --          Ada.Tags.Get_Tagged_Kind (Ada.Tags.Tag (<object>));
7039
7040             --  Dummy communication block, generate:
7041             --    D : Dummy_Communication_Block;
7042
7043             Append_To (Decls,
7044               Make_Object_Declaration (Loc,
7045                 Defining_Identifier =>
7046                   Make_Defining_Identifier (Loc, Name_uD),
7047                 Object_Definition   =>
7048                   New_Occurrence_Of
7049                     (RTE (RE_Dummy_Communication_Block), Loc)));
7050
7051             K := Build_K (Loc, Decls, Obj);
7052
7053             --  Parameter block processing
7054
7055             Blk_Typ := Build_Parameter_Block
7056                          (Loc, Actuals, Formals, Decls);
7057             P       := Parameter_Block_Pack
7058                          (Loc, Blk_Typ, Actuals, Formals, Decls, Stmts);
7059
7060             --  Dispatch table slot processing, generate:
7061             --    S : Integer;
7062
7063             S := Build_S (Loc, Decls);
7064
7065             --  Additional status flag processing, generate:
7066             --    Tnn : Boolean;
7067
7068             T := Make_Temporary (Loc, 'T');
7069             Append_To (Decls,
7070               Make_Object_Declaration (Loc,
7071                 Defining_Identifier => T,
7072                 Object_Definition   =>
7073                   New_Occurrence_Of (Standard_Boolean, Loc)));
7074
7075             ------------------------------
7076             -- Protected entry handling --
7077             ------------------------------
7078
7079             --  Generate:
7080             --    Param1 := P.Param1;
7081             --    ...
7082             --    ParamN := P.ParamN;
7083
7084             Cleanup_Stmts := Parameter_Block_Unpack (Loc, P, Actuals, Formals);
7085
7086             --  Generate:
7087             --    Bnn := Communication_Block (D);
7088
7089             Prepend_To (Cleanup_Stmts,
7090               Make_Assignment_Statement (Loc,
7091                 Name       => New_Occurrence_Of (Bnn, Loc),
7092                 Expression =>
7093                   Make_Unchecked_Type_Conversion (Loc,
7094                     Subtype_Mark =>
7095                       New_Occurrence_Of (RTE (RE_Communication_Block), Loc),
7096                     Expression   => Make_Identifier (Loc, Name_uD))));
7097
7098             --  Generate:
7099             --    _Disp_Asynchronous_Select (<object>, S, P'Address, D, B);
7100
7101             Prepend_To (Cleanup_Stmts,
7102               Make_Procedure_Call_Statement (Loc,
7103                 Name =>
7104                   New_Occurrence_Of
7105                     (Find_Prim_Op
7106                        (Etype (Etype (Obj)), Name_uDisp_Asynchronous_Select),
7107                      Loc),
7108                 Parameter_Associations =>
7109                   New_List (
7110                     New_Copy_Tree (Obj),             --  <object>
7111                     New_Occurrence_Of (S, Loc),       --  S
7112                     Make_Attribute_Reference (Loc,   --  P'Address
7113                       Prefix         => New_Occurrence_Of (P, Loc),
7114                       Attribute_Name => Name_Address),
7115                     Make_Identifier (Loc, Name_uD),  --  D
7116                     New_Occurrence_Of (B, Loc))));    --  B
7117
7118             --  Generate:
7119             --    if Enqueued (Bnn) then
7120             --       <abortable-statements>
7121             --    end if;
7122
7123             Append_To (Cleanup_Stmts,
7124               Make_Implicit_If_Statement (N,
7125                 Condition =>
7126                   Make_Function_Call (Loc,
7127                     Name =>
7128                       New_Occurrence_Of (RTE (RE_Enqueued), Loc),
7129                     Parameter_Associations =>
7130                       New_List (New_Occurrence_Of (Bnn, Loc))),
7131
7132                 Then_Statements =>
7133                   New_Copy_List_Tree (Astats)));
7134
7135             --  Wrap the statements in a block. Exp_Ch7.Expand_Cleanup_Actions
7136             --  will then generate a _clean for the communication block Bnn.
7137
7138             --  Generate:
7139             --    declare
7140             --       procedure _clean is
7141             --       begin
7142             --          if Enqueued (Bnn) then
7143             --             Cancel_Protected_Entry_Call (Bnn);
7144             --          end if;
7145             --       end _clean;
7146             --    begin
7147             --       Cleanup_Stmts
7148             --    at end
7149             --       _clean;
7150             --    end;
7151
7152             Cleanup_Block_Ent := Make_Temporary (Loc, 'C');
7153             Cleanup_Block :=
7154               Build_Cleanup_Block (Loc, Cleanup_Block_Ent, Cleanup_Stmts, Bnn);
7155
7156             --  Wrap the cleanup block in an exception handling block
7157
7158             --  Generate:
7159             --    begin
7160             --       Cleanup_Block
7161             --    exception
7162             --       when Abort_Signal => Abort_Undefer;
7163             --    end;
7164
7165             Abort_Block_Ent := Make_Temporary (Loc, 'A');
7166             ProtE_Stmts :=
7167               New_List (
7168                 Make_Implicit_Label_Declaration (Loc,
7169                   Defining_Identifier => Abort_Block_Ent),
7170
7171                 Build_Abort_Block
7172                   (Loc, Abort_Block_Ent, Cleanup_Block_Ent, Cleanup_Block));
7173
7174             --  Generate:
7175             --    if not Cancelled (Bnn) then
7176             --       <triggering-statements>
7177             --    end if;
7178
7179             Append_To (ProtE_Stmts,
7180               Make_Implicit_If_Statement (N,
7181                 Condition =>
7182                   Make_Op_Not (Loc,
7183                     Right_Opnd =>
7184                       Make_Function_Call (Loc,
7185                         Name =>
7186                           New_Occurrence_Of (RTE (RE_Cancelled), Loc),
7187                         Parameter_Associations =>
7188                           New_List (New_Occurrence_Of (Bnn, Loc)))),
7189
7190                 Then_Statements =>
7191                   New_Copy_List_Tree (Tstats)));
7192
7193             -------------------------
7194             -- Task entry handling --
7195             -------------------------
7196
7197             --  Generate:
7198             --    Param1 := P.Param1;
7199             --    ...
7200             --    ParamN := P.ParamN;
7201
7202             TaskE_Stmts := Parameter_Block_Unpack (Loc, P, Actuals, Formals);
7203
7204             --  Generate:
7205             --    Bnn := Communication_Block (D);
7206
7207             Append_To (TaskE_Stmts,
7208               Make_Assignment_Statement (Loc,
7209                 Name =>
7210                   New_Occurrence_Of (Bnn, Loc),
7211                 Expression =>
7212                   Make_Unchecked_Type_Conversion (Loc,
7213                     Subtype_Mark =>
7214                       New_Occurrence_Of (RTE (RE_Communication_Block), Loc),
7215                     Expression   => Make_Identifier (Loc, Name_uD))));
7216
7217             --  Generate:
7218             --    _Disp_Asynchronous_Select (<object>, S, P'Address, D, B);
7219
7220             Prepend_To (TaskE_Stmts,
7221               Make_Procedure_Call_Statement (Loc,
7222                 Name =>
7223                   New_Occurrence_Of (
7224                     Find_Prim_Op (Etype (Etype (Obj)),
7225                       Name_uDisp_Asynchronous_Select),
7226                     Loc),
7227
7228                 Parameter_Associations =>
7229                   New_List (
7230                     New_Copy_Tree (Obj),             --  <object>
7231                     New_Occurrence_Of (S, Loc),       --  S
7232                     Make_Attribute_Reference (Loc,   --  P'Address
7233                       Prefix         => New_Occurrence_Of (P, Loc),
7234                       Attribute_Name => Name_Address),
7235                     Make_Identifier (Loc, Name_uD),  --  D
7236                     New_Occurrence_Of (B, Loc))));    --  B
7237
7238             --  Generate:
7239             --    Abort_Defer;
7240
7241             Prepend_To (TaskE_Stmts,
7242               Make_Procedure_Call_Statement (Loc,
7243                 Name => New_Occurrence_Of (RTE (RE_Abort_Defer), Loc),
7244                 Parameter_Associations => No_List));
7245
7246             --  Generate:
7247             --    Abort_Undefer;
7248             --    <abortable-statements>
7249
7250             Cleanup_Stmts := New_Copy_List_Tree (Astats);
7251
7252             Prepend_To (Cleanup_Stmts,
7253               Make_Procedure_Call_Statement (Loc,
7254                 Name => New_Occurrence_Of (RTE (RE_Abort_Undefer), Loc),
7255                 Parameter_Associations => No_List));
7256
7257             --  Wrap the statements in a block. Exp_Ch7.Expand_Cleanup_Actions
7258             --  will generate a _clean for the additional status flag.
7259
7260             --  Generate:
7261             --    declare
7262             --       procedure _clean is
7263             --       begin
7264             --          Cancel_Task_Entry_Call (U);
7265             --       end _clean;
7266             --    begin
7267             --       Cleanup_Stmts
7268             --    at end
7269             --       _clean;
7270             --    end;
7271
7272             Cleanup_Block_Ent := Make_Temporary (Loc, 'C');
7273             Cleanup_Block :=
7274               Build_Cleanup_Block (Loc, Cleanup_Block_Ent, Cleanup_Stmts, T);
7275
7276             --  Wrap the cleanup block in an exception handling block
7277
7278             --  Generate:
7279             --    begin
7280             --       Cleanup_Block
7281             --    exception
7282             --       when Abort_Signal => Abort_Undefer;
7283             --    end;
7284
7285             Abort_Block_Ent := Make_Temporary (Loc, 'A');
7286
7287             Append_To (TaskE_Stmts,
7288               Make_Implicit_Label_Declaration (Loc,
7289                 Defining_Identifier => Abort_Block_Ent));
7290
7291             Append_To (TaskE_Stmts,
7292               Build_Abort_Block
7293                 (Loc, Abort_Block_Ent, Cleanup_Block_Ent, Cleanup_Block));
7294
7295             --  Generate:
7296             --    if not T then
7297             --       <triggering-statements>
7298             --    end if;
7299
7300             Append_To (TaskE_Stmts,
7301               Make_Implicit_If_Statement (N,
7302                 Condition =>
7303                   Make_Op_Not (Loc, Right_Opnd => New_Occurrence_Of (T, Loc)),
7304
7305                 Then_Statements =>
7306                   New_Copy_List_Tree (Tstats)));
7307
7308             ----------------------------------
7309             -- Protected procedure handling --
7310             ----------------------------------
7311
7312             --  Generate:
7313             --    <dispatching-call>;
7314             --    <triggering-statements>
7315
7316             ProtP_Stmts := New_Copy_List_Tree (Tstats);
7317             Prepend_To (ProtP_Stmts, New_Copy_Tree (Ecall));
7318
7319             --  Generate:
7320             --    S := Ada.Tags.Get_Offset_Index
7321             --           (Ada.Tags.Tag (<object>), DT_Position (Call_Ent));
7322
7323             Conc_Typ_Stmts :=
7324               New_List (Build_S_Assignment (Loc, S, Obj, Call_Ent));
7325
7326             --  Generate:
7327             --    _Disp_Get_Prim_Op_Kind (<object>, S, C);
7328
7329             Append_To (Conc_Typ_Stmts,
7330               Make_Procedure_Call_Statement (Loc,
7331                 Name =>
7332                   New_Occurrence_Of
7333                     (Find_Prim_Op (Etype (Etype (Obj)),
7334                                    Name_uDisp_Get_Prim_Op_Kind),
7335                      Loc),
7336                 Parameter_Associations =>
7337                   New_List (
7338                     New_Copy_Tree (Obj),
7339                     New_Occurrence_Of (S, Loc),
7340                     New_Occurrence_Of (C, Loc))));
7341
7342             --  Generate:
7343             --    if C = POK_Procedure_Entry then
7344             --       ProtE_Stmts
7345             --    elsif C = POK_Task_Entry then
7346             --       TaskE_Stmts
7347             --    else
7348             --       ProtP_Stmts
7349             --    end if;
7350
7351             Append_To (Conc_Typ_Stmts,
7352               Make_Implicit_If_Statement (N,
7353                 Condition =>
7354                   Make_Op_Eq (Loc,
7355                     Left_Opnd  =>
7356                       New_Occurrence_Of (C, Loc),
7357                     Right_Opnd =>
7358                       New_Occurrence_Of (RTE (RE_POK_Protected_Entry), Loc)),
7359
7360                 Then_Statements =>
7361                   ProtE_Stmts,
7362
7363                 Elsif_Parts =>
7364                   New_List (
7365                     Make_Elsif_Part (Loc,
7366                       Condition =>
7367                         Make_Op_Eq (Loc,
7368                           Left_Opnd  =>
7369                             New_Occurrence_Of (C, Loc),
7370                           Right_Opnd =>
7371                             New_Occurrence_Of (RTE (RE_POK_Task_Entry), Loc)),
7372
7373                       Then_Statements =>
7374                         TaskE_Stmts)),
7375
7376                 Else_Statements =>
7377                   ProtP_Stmts));
7378
7379             --  Generate:
7380             --    <dispatching-call>;
7381             --    <triggering-statements>
7382
7383             Lim_Typ_Stmts := New_Copy_List_Tree (Tstats);
7384             Prepend_To (Lim_Typ_Stmts, New_Copy_Tree (Ecall));
7385
7386             --  Generate:
7387             --    if K = Ada.Tags.TK_Limited_Tagged
7388             --         or else K = Ada.Tags.TK_Tagged
7389             --       then
7390             --       Lim_Typ_Stmts
7391             --    else
7392             --       Conc_Typ_Stmts
7393             --    end if;
7394
7395             Append_To (Stmts,
7396               Make_Implicit_If_Statement (N,
7397                 Condition       => Build_Dispatching_Tag_Check (K, N),
7398                 Then_Statements => Lim_Typ_Stmts,
7399                 Else_Statements => Conc_Typ_Stmts));
7400
7401             Rewrite (N,
7402               Make_Block_Statement (Loc,
7403                 Declarations =>
7404                   Decls,
7405                 Handled_Statement_Sequence =>
7406                   Make_Handled_Sequence_Of_Statements (Loc, Stmts)));
7407
7408             Analyze (N);
7409             return;
7410
7411          --  Delay triggering statement processing
7412
7413          else
7414             --  Add a Delay_Block object to the parameter list of the delay
7415             --  procedure to form the parameter list of the Wait entry call.
7416
7417             Dblock_Ent := Make_Temporary (Loc, 'D');
7418
7419             Pdef := Entity (Name (Ecall));
7420
7421             if Is_RTE (Pdef, RO_CA_Delay_For) then
7422                Enqueue_Call :=
7423                  New_Occurrence_Of (RTE (RE_Enqueue_Duration), Loc);
7424
7425             elsif Is_RTE (Pdef, RO_CA_Delay_Until) then
7426                Enqueue_Call :=
7427                  New_Occurrence_Of (RTE (RE_Enqueue_Calendar), Loc);
7428
7429             else pragma Assert (Is_RTE (Pdef, RO_RT_Delay_Until));
7430                Enqueue_Call := New_Occurrence_Of (RTE (RE_Enqueue_RT), Loc);
7431             end if;
7432
7433             Append_To (Parameter_Associations (Ecall),
7434               Make_Attribute_Reference (Loc,
7435                 Prefix         => New_Occurrence_Of (Dblock_Ent, Loc),
7436                 Attribute_Name => Name_Unchecked_Access));
7437
7438             --  Create the inner block to protect the abortable part
7439
7440             Hdle := New_List (Build_Abort_Block_Handler (Loc));
7441
7442             Prepend_To (Astats,
7443               Make_Procedure_Call_Statement (Loc,
7444                 Name => New_Occurrence_Of (RTE (RE_Abort_Undefer), Loc)));
7445
7446             Abortable_Block :=
7447               Make_Block_Statement (Loc,
7448                 Identifier                 => New_Occurrence_Of (Blk_Ent, Loc),
7449                 Handled_Statement_Sequence =>
7450                   Make_Handled_Sequence_Of_Statements (Loc,
7451                     Statements => Astats),
7452                 Has_Created_Identifier     => True,
7453                 Is_Asynchronous_Call_Block => True);
7454
7455             --  Append call to if Enqueue (When, DB'Unchecked_Access) then
7456
7457             Rewrite (Ecall,
7458               Make_Implicit_If_Statement (N,
7459                 Condition =>
7460                   Make_Function_Call (Loc,
7461                     Name => Enqueue_Call,
7462                     Parameter_Associations => Parameter_Associations (Ecall)),
7463                 Then_Statements =>
7464                   New_List (Make_Block_Statement (Loc,
7465                     Handled_Statement_Sequence =>
7466                       Make_Handled_Sequence_Of_Statements (Loc,
7467                         Statements => New_List (
7468                           Make_Implicit_Label_Declaration (Loc,
7469                             Defining_Identifier => Blk_Ent,
7470                             Label_Construct     => Abortable_Block),
7471                           Abortable_Block),
7472                         Exception_Handlers => Hdle)))));
7473
7474             Stmts := New_List (Ecall);
7475
7476             --  Construct statement sequence for new block
7477
7478             Append_To (Stmts,
7479               Make_Implicit_If_Statement (N,
7480                 Condition =>
7481                   Make_Function_Call (Loc,
7482                     Name => New_Occurrence_Of (
7483                       RTE (RE_Timed_Out), Loc),
7484                     Parameter_Associations => New_List (
7485                       Make_Attribute_Reference (Loc,
7486                         Prefix         => New_Occurrence_Of (Dblock_Ent, Loc),
7487                         Attribute_Name => Name_Unchecked_Access))),
7488                 Then_Statements => Tstats));
7489
7490             --  The result is the new block
7491
7492             Set_Entry_Cancel_Parameter (Blk_Ent, Dblock_Ent);
7493
7494             Rewrite (N,
7495               Make_Block_Statement (Loc,
7496                 Declarations => New_List (
7497                   Make_Object_Declaration (Loc,
7498                     Defining_Identifier => Dblock_Ent,
7499                     Aliased_Present     => True,
7500                     Object_Definition   =>
7501                       New_Occurrence_Of (RTE (RE_Delay_Block), Loc))),
7502
7503                 Handled_Statement_Sequence =>
7504                   Make_Handled_Sequence_Of_Statements (Loc, Stmts)));
7505
7506             Analyze (N);
7507             return;
7508          end if;
7509
7510       else
7511          N_Orig := N;
7512       end if;
7513
7514       Extract_Entry (Ecall, Concval, Ename, Index);
7515       Build_Simple_Entry_Call (Ecall, Concval, Ename, Index);
7516
7517       Stmts := Statements (Handled_Statement_Sequence (Ecall));
7518       Decls := Declarations (Ecall);
7519
7520       if Is_Protected_Type (Etype (Concval)) then
7521
7522          --  Get the declarations of the block expanded from the entry call
7523
7524          Decl := First (Decls);
7525          while Present (Decl)
7526            and then (Nkind (Decl) /= N_Object_Declaration
7527                       or else not Is_RTE (Etype (Object_Definition (Decl)),
7528                                           RE_Communication_Block))
7529          loop
7530             Next (Decl);
7531          end loop;
7532
7533          pragma Assert (Present (Decl));
7534          Cancel_Param := Defining_Identifier (Decl);
7535
7536          --  Change the mode of the Protected_Entry_Call call
7537
7538          --  Protected_Entry_Call (
7539          --    Object => po._object'Access,
7540          --    E => <entry index>;
7541          --    Uninterpreted_Data => P'Address;
7542          --    Mode => Asynchronous_Call;
7543          --    Block => Bnn);
7544
7545          --  Skip assignments to temporaries created for in-out parameters
7546
7547          --  This makes unwarranted assumptions about the shape of the expanded
7548          --  tree for the call, and should be cleaned up ???
7549
7550          Stmt := First (Stmts);
7551          while Nkind (Stmt) /= N_Procedure_Call_Statement loop
7552             Next (Stmt);
7553          end loop;
7554
7555          Call := Stmt;
7556
7557          Param := First (Parameter_Associations (Call));
7558          while Present (Param)
7559            and then not Is_RTE (Etype (Param), RE_Call_Modes)
7560          loop
7561             Next (Param);
7562          end loop;
7563
7564          pragma Assert (Present (Param));
7565          Rewrite (Param, New_Occurrence_Of (RTE (RE_Asynchronous_Call), Loc));
7566          Analyze (Param);
7567
7568          --  Append an if statement to execute the abortable part
7569
7570          --  Generate:
7571          --    if Enqueued (Bnn) then
7572
7573          Append_To (Stmts,
7574            Make_Implicit_If_Statement (N,
7575              Condition =>
7576                Make_Function_Call (Loc,
7577                  Name => New_Occurrence_Of (RTE (RE_Enqueued), Loc),
7578                  Parameter_Associations => New_List (
7579                    New_Occurrence_Of (Cancel_Param, Loc))),
7580              Then_Statements => Astats));
7581
7582          Abortable_Block :=
7583            Make_Block_Statement (Loc,
7584              Identifier => New_Occurrence_Of (Blk_Ent, Loc),
7585              Handled_Statement_Sequence =>
7586                Make_Handled_Sequence_Of_Statements (Loc, Statements => Stmts),
7587              Has_Created_Identifier => True,
7588              Is_Asynchronous_Call_Block => True);
7589
7590          if Exception_Mechanism = Back_End_Exceptions then
7591
7592             --  Aborts are not deferred at beginning of exception handlers
7593             --  in ZCX.
7594
7595             Handler_Stmt := Make_Null_Statement (Loc);
7596
7597          else
7598             Handler_Stmt := Make_Procedure_Call_Statement (Loc,
7599               Name => New_Occurrence_Of (RTE (RE_Abort_Undefer), Loc),
7600               Parameter_Associations => No_List);
7601          end if;
7602
7603          Stmts := New_List (
7604            Make_Block_Statement (Loc,
7605              Handled_Statement_Sequence =>
7606                Make_Handled_Sequence_Of_Statements (Loc,
7607                  Statements => New_List (
7608                    Make_Implicit_Label_Declaration (Loc,
7609                      Defining_Identifier => Blk_Ent,
7610                      Label_Construct     => Abortable_Block),
7611                    Abortable_Block),
7612
7613                --  exception
7614
7615                  Exception_Handlers => New_List (
7616                    Make_Implicit_Exception_Handler (Loc,
7617
7618                --  when Abort_Signal =>
7619                --     Abort_Undefer.all;
7620
7621                      Exception_Choices =>
7622                        New_List (New_Occurrence_Of (Stand.Abort_Signal, Loc)),
7623                      Statements => New_List (Handler_Stmt))))),
7624
7625          --  if not Cancelled (Bnn) then
7626          --     triggered statements
7627          --  end if;
7628
7629            Make_Implicit_If_Statement (N,
7630              Condition => Make_Op_Not (Loc,
7631                Right_Opnd =>
7632                  Make_Function_Call (Loc,
7633                    Name => New_Occurrence_Of (RTE (RE_Cancelled), Loc),
7634                    Parameter_Associations => New_List (
7635                      New_Occurrence_Of (Cancel_Param, Loc)))),
7636              Then_Statements => Tstats));
7637
7638       --  Asynchronous task entry call
7639
7640       else
7641          if No (Decls) then
7642             Decls := New_List;
7643          end if;
7644
7645          B := Make_Defining_Identifier (Loc, Name_uB);
7646
7647          --  Insert declaration of B in declarations of existing block
7648
7649          Prepend_To (Decls,
7650            Make_Object_Declaration (Loc,
7651              Defining_Identifier => B,
7652              Object_Definition   =>
7653                New_Occurrence_Of (Standard_Boolean, Loc)));
7654
7655          Cancel_Param := Make_Defining_Identifier (Loc, Name_uC);
7656
7657          --  Insert declaration of C in declarations of existing block
7658
7659          Prepend_To (Decls,
7660            Make_Object_Declaration (Loc,
7661              Defining_Identifier => Cancel_Param,
7662              Object_Definition   =>
7663                New_Occurrence_Of (Standard_Boolean, Loc)));
7664
7665          --  Remove and save the call to Call_Simple
7666
7667          Stmt := First (Stmts);
7668
7669          --  Skip assignments to temporaries created for in-out parameters.
7670          --  This makes unwarranted assumptions about the shape of the expanded
7671          --  tree for the call, and should be cleaned up ???
7672
7673          while Nkind (Stmt) /= N_Procedure_Call_Statement loop
7674             Next (Stmt);
7675          end loop;
7676
7677          Call := Stmt;
7678
7679          --  Create the inner block to protect the abortable part
7680
7681          Hdle := New_List (Build_Abort_Block_Handler (Loc));
7682
7683          Prepend_To (Astats,
7684            Make_Procedure_Call_Statement (Loc,
7685              Name => New_Occurrence_Of (RTE (RE_Abort_Undefer), Loc)));
7686
7687          Abortable_Block :=
7688            Make_Block_Statement (Loc,
7689              Identifier                 => New_Occurrence_Of (Blk_Ent, Loc),
7690              Handled_Statement_Sequence =>
7691                Make_Handled_Sequence_Of_Statements (Loc, Statements => Astats),
7692              Has_Created_Identifier     => True,
7693              Is_Asynchronous_Call_Block => True);
7694
7695          Insert_After (Call,
7696            Make_Block_Statement (Loc,
7697              Handled_Statement_Sequence =>
7698                Make_Handled_Sequence_Of_Statements (Loc,
7699                  Statements => New_List (
7700                    Make_Implicit_Label_Declaration (Loc,
7701                      Defining_Identifier => Blk_Ent,
7702                      Label_Construct     => Abortable_Block),
7703                    Abortable_Block),
7704                  Exception_Handlers => Hdle)));
7705
7706          --  Create new call statement
7707
7708          Params := Parameter_Associations (Call);
7709
7710          Append_To (Params,
7711            New_Occurrence_Of (RTE (RE_Asynchronous_Call), Loc));
7712          Append_To (Params, New_Occurrence_Of (B, Loc));
7713
7714          Rewrite (Call,
7715            Make_Procedure_Call_Statement (Loc,
7716              Name => New_Occurrence_Of (RTE (RE_Task_Entry_Call), Loc),
7717              Parameter_Associations => Params));
7718
7719          --  Construct statement sequence for new block
7720
7721          Append_To (Stmts,
7722            Make_Implicit_If_Statement (N,
7723              Condition =>
7724                Make_Op_Not (Loc, New_Occurrence_Of (Cancel_Param, Loc)),
7725              Then_Statements => Tstats));
7726
7727          --  Protected the call against abort
7728
7729          Prepend_To (Stmts,
7730            Make_Procedure_Call_Statement (Loc,
7731              Name => New_Occurrence_Of (RTE (RE_Abort_Defer), Loc),
7732              Parameter_Associations => Empty_List));
7733       end if;
7734
7735       Set_Entry_Cancel_Parameter (Blk_Ent, Cancel_Param);
7736
7737       --  The result is the new block
7738
7739       Rewrite (N_Orig,
7740         Make_Block_Statement (Loc,
7741           Declarations => Decls,
7742           Handled_Statement_Sequence =>
7743             Make_Handled_Sequence_Of_Statements (Loc, Stmts)));
7744
7745       Analyze (N_Orig);
7746    end Expand_N_Asynchronous_Select;
7747
7748    -------------------------------------
7749    -- Expand_N_Conditional_Entry_Call --
7750    -------------------------------------
7751
7752    --  The conditional task entry call is converted to a call to
7753    --  Task_Entry_Call:
7754
7755    --    declare
7756    --       B : Boolean;
7757    --       P : parms := (parm, parm, parm);
7758
7759    --    begin
7760    --       Task_Entry_Call
7761    --         (<acceptor-task>,   --  Acceptor
7762    --          <entry-index>,     --  E
7763    --          P'Address,         --  Uninterpreted_Data
7764    --          Conditional_Call,  --  Mode
7765    --          B);                --  Rendezvous_Successful
7766    --       parm := P.param;
7767    --       parm := P.param;
7768    --       ...
7769    --       if B then
7770    --          normal-statements
7771    --       else
7772    --          else-statements
7773    --       end if;
7774    --    end;
7775
7776    --  For a description of the use of P and the assignments after the call,
7777    --  see Expand_N_Entry_Call_Statement. Note that the entry call of the
7778    --  conditional entry call has already been expanded (by the Expand_N_Entry
7779    --  _Call_Statement procedure) as follows:
7780
7781    --    declare
7782    --       P : parms := (parm, parm, parm);
7783    --    begin
7784    --       ... info for in-out parameters
7785    --       Call_Simple (acceptor-task, entry-index, P'Address);
7786    --       parm := P.param;
7787    --       parm := P.param;
7788    --       ...
7789    --    end;
7790
7791    --  so the task at hand is to convert the latter expansion into the former
7792
7793    --  The conditional protected entry call is converted to a call to
7794    --  Protected_Entry_Call:
7795
7796    --    declare
7797    --       P : parms := (parm, parm, parm);
7798    --       Bnn : Communications_Block;
7799
7800    --    begin
7801    --       Protected_Entry_Call
7802    --         (po._object'Access,  --  Object
7803    --          <entry index>,      --  E
7804    --          P'Address,          --  Uninterpreted_Data
7805    --          Conditional_Call,   --  Mode
7806    --          Bnn);               --  Block
7807    --       parm := P.param;
7808    --       parm := P.param;
7809    --       ...
7810    --       if Cancelled (Bnn) then
7811    --          else-statements
7812    --       else
7813    --          normal-statements
7814    --       end if;
7815    --    end;
7816
7817    --  Ada 2005 (AI-345): A dispatching conditional entry call is converted
7818    --  into:
7819
7820    --    declare
7821    --       B : Boolean := False;
7822    --       C : Ada.Tags.Prim_Op_Kind;
7823    --       K : Ada.Tags.Tagged_Kind :=
7824    --             Ada.Tags.Get_Tagged_Kind (Ada.Tags.Tag (<object>));
7825    --       P : Parameters := (Param1 .. ParamN);
7826    --       S : Integer;
7827
7828    --    begin
7829    --       if K = Ada.Tags.TK_Limited_Tagged
7830    --         or else K = Ada.Tags.TK_Tagged
7831    --       then
7832    --          <dispatching-call>;
7833    --          <triggering-statements>
7834
7835    --       else
7836    --          S :=
7837    --            Ada.Tags.Get_Offset_Index
7838    --              (Ada.Tags.Tag (<object>), DT_Position (<dispatching-call>));
7839
7840    --          _Disp_Conditional_Select (<object>, S, P'Address, C, B);
7841
7842    --          if C = POK_Protected_Entry
7843    --            or else C = POK_Task_Entry
7844    --          then
7845    --             Param1 := P.Param1;
7846    --             ...
7847    --             ParamN := P.ParamN;
7848    --          end if;
7849
7850    --          if B then
7851    --             if C = POK_Procedure
7852    --               or else C = POK_Protected_Procedure
7853    --               or else C = POK_Task_Procedure
7854    --             then
7855    --                <dispatching-call>;
7856    --             end if;
7857
7858    --             <triggering-statements>
7859    --          else
7860    --             <else-statements>
7861    --          end if;
7862    --       end if;
7863    --    end;
7864
7865    procedure Expand_N_Conditional_Entry_Call (N : Node_Id) is
7866       Loc : constant Source_Ptr := Sloc (N);
7867       Alt : constant Node_Id    := Entry_Call_Alternative (N);
7868       Blk : Node_Id             := Entry_Call_Statement (Alt);
7869
7870       Actuals        : List_Id;
7871       Blk_Typ        : Entity_Id;
7872       Call           : Node_Id;
7873       Call_Ent       : Entity_Id;
7874       Conc_Typ_Stmts : List_Id;
7875       Decl           : Node_Id;
7876       Decls          : List_Id;
7877       Formals        : List_Id;
7878       Lim_Typ_Stmts  : List_Id;
7879       N_Stats        : List_Id;
7880       Obj            : Entity_Id;
7881       Param          : Node_Id;
7882       Params         : List_Id;
7883       Stmt           : Node_Id;
7884       Stmts          : List_Id;
7885       Transient_Blk  : Node_Id;
7886       Unpack         : List_Id;
7887
7888       B : Entity_Id;  --  Call status flag
7889       C : Entity_Id;  --  Call kind
7890       K : Entity_Id;  --  Tagged kind
7891       P : Entity_Id;  --  Parameter block
7892       S : Entity_Id;  --  Primitive operation slot
7893
7894    begin
7895       Process_Statements_For_Controlled_Objects (N);
7896
7897       if Ada_Version >= Ada_2005
7898         and then Nkind (Blk) = N_Procedure_Call_Statement
7899       then
7900          Extract_Dispatching_Call (Blk, Call_Ent, Obj, Actuals, Formals);
7901
7902          Decls := New_List;
7903          Stmts := New_List;
7904
7905          --  Call status flag processing, generate:
7906          --    B : Boolean := False;
7907
7908          B := Build_B (Loc, Decls);
7909
7910          --  Call kind processing, generate:
7911          --    C : Ada.Tags.Prim_Op_Kind;
7912
7913          C := Build_C (Loc, Decls);
7914
7915          --  Tagged kind processing, generate:
7916          --    K : Ada.Tags.Tagged_Kind :=
7917          --          Ada.Tags.Get_Tagged_Kind (Ada.Tags.Tag (<object>));
7918
7919          K := Build_K (Loc, Decls, Obj);
7920
7921          --  Parameter block processing
7922
7923          Blk_Typ := Build_Parameter_Block (Loc, Actuals, Formals, Decls);
7924          P       := Parameter_Block_Pack
7925                       (Loc, Blk_Typ, Actuals, Formals, Decls, Stmts);
7926
7927          --  Dispatch table slot processing, generate:
7928          --    S : Integer;
7929
7930          S := Build_S (Loc, Decls);
7931
7932          --  Generate:
7933          --    S := Ada.Tags.Get_Offset_Index
7934          --           (Ada.Tags.Tag (<object>), DT_Position (Call_Ent));
7935
7936          Conc_Typ_Stmts :=
7937            New_List (Build_S_Assignment (Loc, S, Obj, Call_Ent));
7938
7939          --  Generate:
7940          --    _Disp_Conditional_Select (<object>, S, P'Address, C, B);
7941
7942          Append_To (Conc_Typ_Stmts,
7943            Make_Procedure_Call_Statement (Loc,
7944              Name =>
7945                New_Occurrence_Of (
7946                  Find_Prim_Op (Etype (Etype (Obj)),
7947                    Name_uDisp_Conditional_Select),
7948                  Loc),
7949              Parameter_Associations =>
7950                New_List (
7951                  New_Copy_Tree (Obj),            --  <object>
7952                  New_Occurrence_Of (S, Loc),      --  S
7953                  Make_Attribute_Reference (Loc,  --  P'Address
7954                    Prefix         => New_Occurrence_Of (P, Loc),
7955                    Attribute_Name => Name_Address),
7956                  New_Occurrence_Of (C, Loc),      --  C
7957                  New_Occurrence_Of (B, Loc))));   --  B
7958
7959          --  Generate:
7960          --    if C = POK_Protected_Entry
7961          --      or else C = POK_Task_Entry
7962          --    then
7963          --       Param1 := P.Param1;
7964          --       ...
7965          --       ParamN := P.ParamN;
7966          --    end if;
7967
7968          Unpack := Parameter_Block_Unpack (Loc, P, Actuals, Formals);
7969
7970          --  Generate the if statement only when the packed parameters need
7971          --  explicit assignments to their corresponding actuals.
7972
7973          if Present (Unpack) then
7974             Append_To (Conc_Typ_Stmts,
7975               Make_Implicit_If_Statement (N,
7976                 Condition =>
7977                   Make_Or_Else (Loc,
7978                     Left_Opnd =>
7979                       Make_Op_Eq (Loc,
7980                         Left_Opnd =>
7981                           New_Occurrence_Of (C, Loc),
7982                         Right_Opnd =>
7983                           New_Occurrence_Of (RTE (
7984                             RE_POK_Protected_Entry), Loc)),
7985
7986                     Right_Opnd =>
7987                       Make_Op_Eq (Loc,
7988                         Left_Opnd =>
7989                           New_Occurrence_Of (C, Loc),
7990                         Right_Opnd =>
7991                           New_Occurrence_Of (RTE (RE_POK_Task_Entry), Loc))),
7992
7993                 Then_Statements => Unpack));
7994          end if;
7995
7996          --  Generate:
7997          --    if B then
7998          --       if C = POK_Procedure
7999          --         or else C = POK_Protected_Procedure
8000          --         or else C = POK_Task_Procedure
8001          --       then
8002          --          <dispatching-call>
8003          --       end if;
8004          --       <normal-statements>
8005          --    else
8006          --       <else-statements>
8007          --    end if;
8008
8009          N_Stats := New_Copy_List_Tree (Statements (Alt));
8010
8011          Prepend_To (N_Stats,
8012            Make_Implicit_If_Statement (N,
8013              Condition =>
8014                Make_Or_Else (Loc,
8015                  Left_Opnd =>
8016                    Make_Op_Eq (Loc,
8017                      Left_Opnd =>
8018                        New_Occurrence_Of (C, Loc),
8019                      Right_Opnd =>
8020                        New_Occurrence_Of (RTE (RE_POK_Procedure), Loc)),
8021
8022                  Right_Opnd =>
8023                    Make_Or_Else (Loc,
8024                      Left_Opnd =>
8025                        Make_Op_Eq (Loc,
8026                          Left_Opnd =>
8027                            New_Occurrence_Of (C, Loc),
8028                          Right_Opnd =>
8029                            New_Occurrence_Of (RTE (
8030                              RE_POK_Protected_Procedure), Loc)),
8031
8032                      Right_Opnd =>
8033                        Make_Op_Eq (Loc,
8034                          Left_Opnd =>
8035                            New_Occurrence_Of (C, Loc),
8036                          Right_Opnd =>
8037                            New_Occurrence_Of (RTE (
8038                              RE_POK_Task_Procedure), Loc)))),
8039
8040              Then_Statements =>
8041                New_List (Blk)));
8042
8043          Append_To (Conc_Typ_Stmts,
8044            Make_Implicit_If_Statement (N,
8045              Condition       => New_Occurrence_Of (B, Loc),
8046              Then_Statements => N_Stats,
8047              Else_Statements => Else_Statements (N)));
8048
8049          --  Generate:
8050          --    <dispatching-call>;
8051          --    <triggering-statements>
8052
8053          Lim_Typ_Stmts := New_Copy_List_Tree (Statements (Alt));
8054          Prepend_To (Lim_Typ_Stmts, New_Copy_Tree (Blk));
8055
8056          --  Generate:
8057          --    if K = Ada.Tags.TK_Limited_Tagged
8058          --         or else K = Ada.Tags.TK_Tagged
8059          --       then
8060          --       Lim_Typ_Stmts
8061          --    else
8062          --       Conc_Typ_Stmts
8063          --    end if;
8064
8065          Append_To (Stmts,
8066            Make_Implicit_If_Statement (N,
8067              Condition       => Build_Dispatching_Tag_Check (K, N),
8068              Then_Statements => Lim_Typ_Stmts,
8069              Else_Statements => Conc_Typ_Stmts));
8070
8071          Rewrite (N,
8072            Make_Block_Statement (Loc,
8073              Declarations =>
8074                Decls,
8075              Handled_Statement_Sequence =>
8076                Make_Handled_Sequence_Of_Statements (Loc, Stmts)));
8077
8078       --  As described above, the entry alternative is transformed into a
8079       --  block that contains the gnulli call, and possibly assignment
8080       --  statements for in-out parameters. The gnulli call may itself be
8081       --  rewritten into a transient block if some unconstrained parameters
8082       --  require it. We need to retrieve the call to complete its parameter
8083       --  list.
8084
8085       else
8086          Transient_Blk :=
8087            First_Real_Statement (Handled_Statement_Sequence (Blk));
8088
8089          if Present (Transient_Blk)
8090            and then Nkind (Transient_Blk) = N_Block_Statement
8091          then
8092             Blk := Transient_Blk;
8093          end if;
8094
8095          Stmts := Statements (Handled_Statement_Sequence (Blk));
8096          Stmt  := First (Stmts);
8097          while Nkind (Stmt) /= N_Procedure_Call_Statement loop
8098             Next (Stmt);
8099          end loop;
8100
8101          Call   := Stmt;
8102          Params := Parameter_Associations (Call);
8103
8104          if Is_RTE (Entity (Name (Call)), RE_Protected_Entry_Call) then
8105
8106             --  Substitute Conditional_Entry_Call for Simple_Call parameter
8107
8108             Param := First (Params);
8109             while Present (Param)
8110               and then not Is_RTE (Etype (Param), RE_Call_Modes)
8111             loop
8112                Next (Param);
8113             end loop;
8114
8115             pragma Assert (Present (Param));
8116             Rewrite (Param,
8117               New_Occurrence_Of (RTE (RE_Conditional_Call), Loc));
8118
8119             Analyze (Param);
8120
8121             --  Find the Communication_Block parameter for the call to the
8122             --  Cancelled function.
8123
8124             Decl := First (Declarations (Blk));
8125             while Present (Decl)
8126               and then not Is_RTE (Etype (Object_Definition (Decl)),
8127                              RE_Communication_Block)
8128             loop
8129                Next (Decl);
8130             end loop;
8131
8132             --  Add an if statement to execute the else part if the call
8133             --  does not succeed (as indicated by the Cancelled predicate).
8134
8135             Append_To (Stmts,
8136               Make_Implicit_If_Statement (N,
8137                 Condition => Make_Function_Call (Loc,
8138                   Name => New_Occurrence_Of (RTE (RE_Cancelled), Loc),
8139                   Parameter_Associations => New_List (
8140                     New_Occurrence_Of (Defining_Identifier (Decl), Loc))),
8141                 Then_Statements => Else_Statements (N),
8142                 Else_Statements => Statements (Alt)));
8143
8144          else
8145             B := Make_Defining_Identifier (Loc, Name_uB);
8146
8147             --  Insert declaration of B in declarations of existing block
8148
8149             if No (Declarations (Blk)) then
8150                Set_Declarations (Blk, New_List);
8151             end if;
8152
8153             Prepend_To (Declarations (Blk),
8154               Make_Object_Declaration (Loc,
8155                 Defining_Identifier => B,
8156                 Object_Definition   =>
8157                   New_Occurrence_Of (Standard_Boolean, Loc)));
8158
8159             --  Create new call statement
8160
8161             Append_To (Params,
8162               New_Occurrence_Of (RTE (RE_Conditional_Call), Loc));
8163             Append_To (Params, New_Occurrence_Of (B, Loc));
8164
8165             Rewrite (Call,
8166               Make_Procedure_Call_Statement (Loc,
8167                 Name => New_Occurrence_Of (RTE (RE_Task_Entry_Call), Loc),
8168                 Parameter_Associations => Params));
8169
8170             --  Construct statement sequence for new block
8171
8172             Append_To (Stmts,
8173               Make_Implicit_If_Statement (N,
8174                 Condition       => New_Occurrence_Of (B, Loc),
8175                 Then_Statements => Statements (Alt),
8176                 Else_Statements => Else_Statements (N)));
8177          end if;
8178
8179          --  The result is the new block
8180
8181          Rewrite (N,
8182            Make_Block_Statement (Loc,
8183              Declarations => Declarations (Blk),
8184              Handled_Statement_Sequence =>
8185                Make_Handled_Sequence_Of_Statements (Loc, Stmts)));
8186       end if;
8187
8188       Analyze (N);
8189    end Expand_N_Conditional_Entry_Call;
8190
8191    ---------------------------------------
8192    -- Expand_N_Delay_Relative_Statement --
8193    ---------------------------------------
8194
8195    --  Delay statement is implemented as a procedure call to Delay_For
8196    --  defined in Ada.Calendar.Delays in order to reduce the overhead of
8197    --  simple delays imposed by the use of Protected Objects.
8198
8199    procedure Expand_N_Delay_Relative_Statement (N : Node_Id) is
8200       Loc : constant Source_Ptr := Sloc (N);
8201    begin
8202       Rewrite (N,
8203         Make_Procedure_Call_Statement (Loc,
8204           Name => New_Occurrence_Of (RTE (RO_CA_Delay_For), Loc),
8205           Parameter_Associations => New_List (Expression (N))));
8206       Analyze (N);
8207    end Expand_N_Delay_Relative_Statement;
8208
8209    ------------------------------------
8210    -- Expand_N_Delay_Until_Statement --
8211    ------------------------------------
8212
8213    --  Delay Until statement is implemented as a procedure call to
8214    --  Delay_Until defined in Ada.Calendar.Delays and Ada.Real_Time.Delays.
8215
8216    procedure Expand_N_Delay_Until_Statement (N : Node_Id) is
8217       Loc : constant Source_Ptr := Sloc (N);
8218       Typ : Entity_Id;
8219
8220    begin
8221       if Is_RTE (Base_Type (Etype (Expression (N))), RO_CA_Time) then
8222          Typ := RTE (RO_CA_Delay_Until);
8223       else
8224          Typ := RTE (RO_RT_Delay_Until);
8225       end if;
8226
8227       Rewrite (N,
8228         Make_Procedure_Call_Statement (Loc,
8229           Name => New_Occurrence_Of (Typ, Loc),
8230           Parameter_Associations => New_List (Expression (N))));
8231
8232       Analyze (N);
8233    end Expand_N_Delay_Until_Statement;
8234
8235    -------------------------
8236    -- Expand_N_Entry_Body --
8237    -------------------------
8238
8239    procedure Expand_N_Entry_Body (N : Node_Id) is
8240    begin
8241       --  Associate discriminals with the next protected operation body to be
8242       --  expanded.
8243
8244       if Present (Next_Protected_Operation (N)) then
8245          Set_Discriminals (Parent (Current_Scope));
8246       end if;
8247    end Expand_N_Entry_Body;
8248
8249    -----------------------------------
8250    -- Expand_N_Entry_Call_Statement --
8251    -----------------------------------
8252
8253    --  An entry call is expanded into GNARLI calls to implement a simple entry
8254    --  call (see Build_Simple_Entry_Call).
8255
8256    procedure Expand_N_Entry_Call_Statement (N : Node_Id) is
8257       Concval : Node_Id;
8258       Ename   : Node_Id;
8259       Index   : Node_Id;
8260
8261    begin
8262       if No_Run_Time_Mode then
8263          Error_Msg_CRT ("entry call", N);
8264          return;
8265       end if;
8266
8267       --  If this entry call is part of an asynchronous select, don't expand it
8268       --  here; it will be expanded with the select statement. Don't expand
8269       --  timed entry calls either, as they are translated into asynchronous
8270       --  entry calls.
8271
8272       --  ??? This whole approach is questionable; it may be better to go back
8273       --  to allowing the expansion to take place and then attempting to fix it
8274       --  up in Expand_N_Asynchronous_Select. The tricky part is figuring out
8275       --  whether the expanded call is on a task or protected entry.
8276
8277       if (Nkind (Parent (N)) /= N_Triggering_Alternative
8278            or else N /= Triggering_Statement (Parent (N)))
8279         and then (Nkind (Parent (N)) /= N_Entry_Call_Alternative
8280                    or else N /= Entry_Call_Statement (Parent (N))
8281                    or else Nkind (Parent (Parent (N))) /= N_Timed_Entry_Call)
8282       then
8283          Extract_Entry (N, Concval, Ename, Index);
8284          Build_Simple_Entry_Call (N, Concval, Ename, Index);
8285       end if;
8286    end Expand_N_Entry_Call_Statement;
8287
8288    --------------------------------
8289    -- Expand_N_Entry_Declaration --
8290    --------------------------------
8291
8292    --  If there are parameters, then first, each of the formals is marked by
8293    --  setting Is_Entry_Formal. Next a record type is built which is used to
8294    --  hold the parameter values. The name of this record type is entryP where
8295    --  entry is the name of the entry, with an additional corresponding access
8296    --  type called entryPA. The record type has matching components for each
8297    --  formal (the component names are the same as the formal names). For
8298    --  elementary types, the component type matches the formal type. For
8299    --  composite types, an access type is declared (with the name formalA)
8300    --  which designates the formal type, and the type of the component is this
8301    --  access type. Finally the Entry_Component of each formal is set to
8302    --  reference the corresponding record component.
8303
8304    procedure Expand_N_Entry_Declaration (N : Node_Id) is
8305       Loc        : constant Source_Ptr := Sloc (N);
8306       Entry_Ent  : constant Entity_Id  := Defining_Identifier (N);
8307       Components : List_Id;
8308       Formal     : Node_Id;
8309       Ftype      : Entity_Id;
8310       Last_Decl  : Node_Id;
8311       Component  : Entity_Id;
8312       Ctype      : Entity_Id;
8313       Decl       : Node_Id;
8314       Rec_Ent    : Entity_Id;
8315       Acc_Ent    : Entity_Id;
8316
8317    begin
8318       Formal := First_Formal (Entry_Ent);
8319       Last_Decl := N;
8320
8321       --  Most processing is done only if parameters are present
8322
8323       if Present (Formal) then
8324          Components := New_List;
8325
8326          --  Loop through formals
8327
8328          while Present (Formal) loop
8329             Set_Is_Entry_Formal (Formal);
8330             Component :=
8331               Make_Defining_Identifier (Sloc (Formal), Chars (Formal));
8332             Set_Entry_Component (Formal, Component);
8333             Set_Entry_Formal (Component, Formal);
8334             Ftype := Etype (Formal);
8335
8336             --  Declare new access type and then append
8337
8338             Ctype := Make_Temporary (Loc, 'A');
8339             Set_Is_Param_Block_Component_Type (Ctype);
8340
8341             Decl :=
8342               Make_Full_Type_Declaration (Loc,
8343                 Defining_Identifier => Ctype,
8344                 Type_Definition     =>
8345                   Make_Access_To_Object_Definition (Loc,
8346                     All_Present        => True,
8347                     Constant_Present   => Ekind (Formal) = E_In_Parameter,
8348                     Subtype_Indication => New_Occurrence_Of (Ftype, Loc)));
8349
8350             Insert_After (Last_Decl, Decl);
8351             Last_Decl := Decl;
8352
8353             Append_To (Components,
8354               Make_Component_Declaration (Loc,
8355                 Defining_Identifier => Component,
8356                 Component_Definition =>
8357                   Make_Component_Definition (Loc,
8358                     Aliased_Present    => False,
8359                     Subtype_Indication => New_Occurrence_Of (Ctype, Loc))));
8360
8361             Next_Formal_With_Extras (Formal);
8362          end loop;
8363
8364          --  Create the Entry_Parameter_Record declaration
8365
8366          Rec_Ent := Make_Temporary (Loc, 'P');
8367
8368          Decl :=
8369            Make_Full_Type_Declaration (Loc,
8370              Defining_Identifier => Rec_Ent,
8371              Type_Definition     =>
8372                Make_Record_Definition (Loc,
8373                  Component_List =>
8374                    Make_Component_List (Loc,
8375                      Component_Items => Components)));
8376
8377          Insert_After (Last_Decl, Decl);
8378          Last_Decl := Decl;
8379
8380          --  Construct and link in the corresponding access type
8381
8382          Acc_Ent := Make_Temporary (Loc, 'A');
8383
8384          Set_Entry_Parameters_Type (Entry_Ent, Acc_Ent);
8385
8386          Decl :=
8387            Make_Full_Type_Declaration (Loc,
8388              Defining_Identifier => Acc_Ent,
8389              Type_Definition     =>
8390                Make_Access_To_Object_Definition (Loc,
8391                  All_Present        => True,
8392                  Subtype_Indication => New_Occurrence_Of (Rec_Ent, Loc)));
8393
8394          Insert_After (Last_Decl, Decl);
8395       end if;
8396    end Expand_N_Entry_Declaration;
8397
8398    -----------------------------
8399    -- Expand_N_Protected_Body --
8400    -----------------------------
8401
8402    --  Protected bodies are expanded to the completion of the subprograms
8403    --  created for the corresponding protected type. These are a protected and
8404    --  unprotected version of each protected subprogram in the object, a
8405    --  function to calculate each entry barrier, and a procedure to execute the
8406    --  sequence of statements of each protected entry body. For example, for
8407    --  protected type ptype:
8408
8409    --  function entB
8410    --    (O : System.Address;
8411    --     E : Protected_Entry_Index)
8412    --     return Boolean
8413    --  is
8414    --     <discriminant renamings>
8415    --     <private object renamings>
8416    --  begin
8417    --     return <barrier expression>;
8418    --  end entB;
8419
8420    --  procedure pprocN (_object : in out poV;...) is
8421    --     <discriminant renamings>
8422    --     <private object renamings>
8423    --  begin
8424    --     <sequence of statements>
8425    --  end pprocN;
8426
8427    --  procedure pprocP (_object : in out poV;...) is
8428    --     procedure _clean is
8429    --       Pn : Boolean;
8430    --     begin
8431    --       ptypeS (_object, Pn);
8432    --       Unlock (_object._object'Access);
8433    --       Abort_Undefer.all;
8434    --     end _clean;
8435
8436    --  begin
8437    --     Abort_Defer.all;
8438    --     Lock (_object._object'Access);
8439    --     pprocN (_object;...);
8440    --  at end
8441    --     _clean;
8442    --  end pproc;
8443
8444    --  function pfuncN (_object : poV;...) return Return_Type is
8445    --     <discriminant renamings>
8446    --     <private object renamings>
8447    --  begin
8448    --     <sequence of statements>
8449    --  end pfuncN;
8450
8451    --  function pfuncP (_object : poV) return Return_Type is
8452    --     procedure _clean is
8453    --     begin
8454    --        Unlock (_object._object'Access);
8455    --        Abort_Undefer.all;
8456    --     end _clean;
8457
8458    --  begin
8459    --     Abort_Defer.all;
8460    --     Lock (_object._object'Access);
8461    --     return pfuncN (_object);
8462
8463    --  at end
8464    --     _clean;
8465    --  end pfunc;
8466
8467    --  procedure entE
8468    --    (O : System.Address;
8469    --     P : System.Address;
8470    --     E : Protected_Entry_Index)
8471    --  is
8472    --     <discriminant renamings>
8473    --     <private object renamings>
8474    --     type poVP is access poV;
8475    --     _Object : ptVP := ptVP!(O);
8476
8477    --  begin
8478    --     begin
8479    --        <statement sequence>
8480    --        Complete_Entry_Body (_Object._Object);
8481    --     exception
8482    --        when all others =>
8483    --           Exceptional_Complete_Entry_Body (
8484    --             _Object._Object, Get_GNAT_Exception);
8485    --     end;
8486    --  end entE;
8487
8488    --  The type poV is the record created for the protected type to hold
8489    --  the state of the protected object.
8490
8491    procedure Expand_N_Protected_Body (N : Node_Id) is
8492       Loc : constant Source_Ptr := Sloc (N);
8493       Pid : constant Entity_Id  := Corresponding_Spec (N);
8494
8495       Lock_Free_Active : constant Boolean := Uses_Lock_Free (Pid);
8496       --  This flag indicates whether the lock free implementation is active
8497
8498       Current_Node : Node_Id;
8499       Disp_Op_Body : Node_Id;
8500       New_Op_Body  : Node_Id;
8501       Op_Body      : Node_Id;
8502       Op_Id        : Entity_Id;
8503
8504       function Build_Dispatching_Subprogram_Body
8505         (N        : Node_Id;
8506          Pid      : Node_Id;
8507          Prot_Bod : Node_Id) return Node_Id;
8508       --  Build a dispatching version of the protected subprogram body. The
8509       --  newly generated subprogram contains a call to the original protected
8510       --  body. The following code is generated:
8511       --
8512       --  function <protected-function-name> (Param1 .. ParamN) return
8513       --    <return-type> is
8514       --  begin
8515       --     return <protected-function-name>P (Param1 .. ParamN);
8516       --  end <protected-function-name>;
8517       --
8518       --  or
8519       --
8520       --  procedure <protected-procedure-name> (Param1 .. ParamN) is
8521       --  begin
8522       --     <protected-procedure-name>P (Param1 .. ParamN);
8523       --  end <protected-procedure-name>
8524
8525       ---------------------------------------
8526       -- Build_Dispatching_Subprogram_Body --
8527       ---------------------------------------
8528
8529       function Build_Dispatching_Subprogram_Body
8530         (N        : Node_Id;
8531          Pid      : Node_Id;
8532          Prot_Bod : Node_Id) return Node_Id
8533       is
8534          Loc     : constant Source_Ptr := Sloc (N);
8535          Actuals : List_Id;
8536          Formal  : Node_Id;
8537          Spec    : Node_Id;
8538          Stmts   : List_Id;
8539
8540       begin
8541          --  Generate a specification without a letter suffix in order to
8542          --  override an interface function or procedure.
8543
8544          Spec := Build_Protected_Sub_Specification (N, Pid, Dispatching_Mode);
8545
8546          --  The formal parameters become the actuals of the protected function
8547          --  or procedure call.
8548
8549          Actuals := New_List;
8550          Formal  := First (Parameter_Specifications (Spec));
8551          while Present (Formal) loop
8552             Append_To (Actuals,
8553               Make_Identifier (Loc, Chars (Defining_Identifier (Formal))));
8554             Next (Formal);
8555          end loop;
8556
8557          if Nkind (Spec) = N_Procedure_Specification then
8558             Stmts :=
8559               New_List (
8560                 Make_Procedure_Call_Statement (Loc,
8561                   Name =>
8562                     New_Occurrence_Of (Corresponding_Spec (Prot_Bod), Loc),
8563                   Parameter_Associations => Actuals));
8564
8565          else
8566             pragma Assert (Nkind (Spec) = N_Function_Specification);
8567
8568             Stmts :=
8569               New_List (
8570                 Make_Simple_Return_Statement (Loc,
8571                   Expression =>
8572                     Make_Function_Call (Loc,
8573                       Name =>
8574                         New_Occurrence_Of (Corresponding_Spec (Prot_Bod), Loc),
8575                       Parameter_Associations => Actuals)));
8576          end if;
8577
8578          return
8579            Make_Subprogram_Body (Loc,
8580              Declarations               => Empty_List,
8581              Specification              => Spec,
8582              Handled_Statement_Sequence =>
8583                Make_Handled_Sequence_Of_Statements (Loc, Stmts));
8584       end Build_Dispatching_Subprogram_Body;
8585
8586    --  Start of processing for Expand_N_Protected_Body
8587
8588    begin
8589       if No_Run_Time_Mode then
8590          Error_Msg_CRT ("protected body", N);
8591          return;
8592       end if;
8593
8594       --  This is the proper body corresponding to a stub. The declarations
8595       --  must be inserted at the point of the stub, which in turn is in the
8596       --  declarative part of the parent unit.
8597
8598       if Nkind (Parent (N)) = N_Subunit then
8599          Current_Node := Corresponding_Stub (Parent (N));
8600       else
8601          Current_Node := N;
8602       end if;
8603
8604       Op_Body := First (Declarations (N));
8605
8606       --  The protected body is replaced with the bodies of its
8607       --  protected operations, and the declarations for internal objects
8608       --  that may have been created for entry family bounds.
8609
8610       Rewrite (N, Make_Null_Statement (Sloc (N)));
8611       Analyze (N);
8612
8613       while Present (Op_Body) loop
8614          case Nkind (Op_Body) is
8615             when N_Subprogram_Declaration =>
8616                null;
8617
8618             when N_Subprogram_Body =>
8619
8620                --  Do not create bodies for eliminated operations
8621
8622                if not Is_Eliminated (Defining_Entity (Op_Body))
8623                  and then not Is_Eliminated (Corresponding_Spec (Op_Body))
8624                then
8625                   if Lock_Free_Active then
8626                      New_Op_Body :=
8627                        Build_Lock_Free_Unprotected_Subprogram_Body
8628                          (Op_Body, Pid);
8629                   else
8630                      New_Op_Body :=
8631                        Build_Unprotected_Subprogram_Body (Op_Body, Pid);
8632                   end if;
8633
8634                   Insert_After (Current_Node, New_Op_Body);
8635                   Current_Node := New_Op_Body;
8636                   Analyze (New_Op_Body);
8637
8638                   --  Build the corresponding protected operation. It may
8639                   --  appear that this is needed only if this is a visible
8640                   --  operation of the type, or if it is an interrupt handler,
8641                   --  and this was the strategy used previously in GNAT.
8642
8643                   --  However, the operation may be exported through a 'Access
8644                   --  to an external caller. This is the common idiom in code
8645                   --  that uses the Ada 2005 Timing_Events package. As a result
8646                   --  we need to produce the protected body for both visible
8647                   --  and private operations, as well as operations that only
8648                   --  have a body in the source, and for which we create a
8649                   --  declaration in the protected body itself.
8650
8651                   if Present (Corresponding_Spec (Op_Body)) then
8652                      if Lock_Free_Active then
8653                         New_Op_Body :=
8654                           Build_Lock_Free_Protected_Subprogram_Body
8655                             (Op_Body, Pid, Specification (New_Op_Body));
8656                      else
8657                         New_Op_Body :=
8658                           Build_Protected_Subprogram_Body
8659                             (Op_Body, Pid, Specification (New_Op_Body));
8660                      end if;
8661
8662                      Insert_After (Current_Node, New_Op_Body);
8663                      Analyze (New_Op_Body);
8664
8665                      Current_Node := New_Op_Body;
8666
8667                      --  Generate an overriding primitive operation body for
8668                      --  this subprogram if the protected type implements an
8669                      --  interface.
8670
8671                      if Ada_Version >= Ada_2005
8672                        and then
8673                          Present (Interfaces (Corresponding_Record_Type (Pid)))
8674                      then
8675                         Disp_Op_Body :=
8676                           Build_Dispatching_Subprogram_Body
8677                             (Op_Body, Pid, New_Op_Body);
8678
8679                         Insert_After (Current_Node, Disp_Op_Body);
8680                         Analyze (Disp_Op_Body);
8681
8682                         Current_Node := Disp_Op_Body;
8683                      end if;
8684                   end if;
8685                end if;
8686
8687             when N_Entry_Body =>
8688                Op_Id := Defining_Identifier (Op_Body);
8689                New_Op_Body := Build_Protected_Entry (Op_Body, Op_Id, Pid);
8690
8691                Insert_After (Current_Node, New_Op_Body);
8692                Current_Node := New_Op_Body;
8693                Analyze (New_Op_Body);
8694
8695             when N_Implicit_Label_Declaration =>
8696                null;
8697
8698             when N_Itype_Reference =>
8699                Insert_After (Current_Node, New_Copy (Op_Body));
8700
8701             when N_Freeze_Entity =>
8702                New_Op_Body := New_Copy (Op_Body);
8703
8704                if Present (Entity (Op_Body))
8705                  and then Freeze_Node (Entity (Op_Body)) = Op_Body
8706                then
8707                   Set_Freeze_Node (Entity (Op_Body), New_Op_Body);
8708                end if;
8709
8710                Insert_After (Current_Node, New_Op_Body);
8711                Current_Node := New_Op_Body;
8712                Analyze (New_Op_Body);
8713
8714             when N_Pragma =>
8715                New_Op_Body := New_Copy (Op_Body);
8716                Insert_After (Current_Node, New_Op_Body);
8717                Current_Node := New_Op_Body;
8718                Analyze (New_Op_Body);
8719
8720             when N_Object_Declaration =>
8721                pragma Assert (not Comes_From_Source (Op_Body));
8722                New_Op_Body := New_Copy (Op_Body);
8723                Insert_After (Current_Node, New_Op_Body);
8724                Current_Node := New_Op_Body;
8725                Analyze (New_Op_Body);
8726
8727             when others =>
8728                raise Program_Error;
8729
8730          end case;
8731
8732          Next (Op_Body);
8733       end loop;
8734
8735       --  Finally, create the body of the function that maps an entry index
8736       --  into the corresponding body index, except when there is no entry, or
8737       --  in a Ravenscar-like profile.
8738
8739       if Corresponding_Runtime_Package (Pid) =
8740            System_Tasking_Protected_Objects_Entries
8741       then
8742          New_Op_Body := Build_Find_Body_Index (Pid);
8743          Insert_After (Current_Node, New_Op_Body);
8744          Current_Node := New_Op_Body;
8745          Analyze (New_Op_Body);
8746       end if;
8747
8748       --  Ada 2005 (AI-345): Construct the primitive wrapper bodies after the
8749       --  protected body. At this point all wrapper specs have been created,
8750       --  frozen and included in the dispatch table for the protected type.
8751
8752       if Ada_Version >= Ada_2005 then
8753          Build_Wrapper_Bodies (Loc, Pid, Current_Node);
8754       end if;
8755    end Expand_N_Protected_Body;
8756
8757    -----------------------------------------
8758    -- Expand_N_Protected_Type_Declaration --
8759    -----------------------------------------
8760
8761    --  First we create a corresponding record type declaration used to
8762    --  represent values of this protected type.
8763    --  The general form of this type declaration is
8764
8765    --    type poV (discriminants) is record
8766    --      _Object       : aliased <kind>Protection
8767    --         [(<entry count> [, <handler count>])];
8768    --      [entry_family  : array (bounds) of Void;]
8769    --      <private data fields>
8770    --    end record;
8771
8772    --  The discriminants are present only if the corresponding protected type
8773    --  has discriminants, and they exactly mirror the protected type
8774    --  discriminants. The private data fields similarly mirror the private
8775    --  declarations of the protected type.
8776
8777    --  The Object field is always present. It contains RTS specific data used
8778    --  to control the protected object. It is declared as Aliased so that it
8779    --  can be passed as a pointer to the RTS. This allows the protected record
8780    --  to be referenced within RTS data structures. An appropriate Protection
8781    --  type and discriminant are generated.
8782
8783    --  The Service field is present for protected objects with entries. It
8784    --  contains sufficient information to allow the entry service procedure for
8785    --  this object to be called when the object is not known till runtime.
8786
8787    --  One entry_family component is present for each entry family in the
8788    --  task definition (see Expand_N_Task_Type_Declaration).
8789
8790    --  When a protected object is declared, an instance of the protected type
8791    --  value record is created. The elaboration of this declaration creates the
8792    --  correct bounds for the entry families, and also evaluates the priority
8793    --  expression if needed. The initialization routine for the protected type
8794    --  itself then calls Initialize_Protection with appropriate parameters to
8795    --  initialize the value of the Task_Id field. Install_Handlers may be also
8796    --  called if a pragma Attach_Handler applies.
8797
8798    --  Note: this record is passed to the subprograms created by the expansion
8799    --  of protected subprograms and entries. It is an in parameter to protected
8800    --  functions and an in out parameter to procedures and entry bodies. The
8801    --  Entity_Id for this created record type is placed in the
8802    --  Corresponding_Record_Type field of the associated protected type entity.
8803
8804    --  Next we create a procedure specifications for protected subprograms and
8805    --  entry bodies. For each protected subprograms two subprograms are
8806    --  created, an unprotected and a protected version. The unprotected version
8807    --  is called from within other operations of the same protected object.
8808
8809    --  We also build the call to register the procedure if a pragma
8810    --  Interrupt_Handler applies.
8811
8812    --  A single subprogram is created to service all entry bodies; it has an
8813    --  additional boolean out parameter indicating that the previous entry call
8814    --  made by the current task was serviced immediately, i.e. not by proxy.
8815    --  The O parameter contains a pointer to a record object of the type
8816    --  described above. An untyped interface is used here to allow this
8817    --  procedure to be called in places where the type of the object to be
8818    --  serviced is not known. This must be done, for example, when a call that
8819    --  may have been requeued is cancelled; the corresponding object must be
8820    --  serviced, but which object that is not known till runtime.
8821
8822    --  procedure ptypeS
8823    --    (O : System.Address; P : out Boolean);
8824    --  procedure pprocN (_object : in out poV);
8825    --  procedure pproc (_object : in out poV);
8826    --  function pfuncN (_object : poV);
8827    --  function pfunc (_object : poV);
8828    --  ...
8829
8830    --  Note that this must come after the record type declaration, since
8831    --  the specs refer to this type.
8832
8833    procedure Expand_N_Protected_Type_Declaration (N : Node_Id) is
8834       Discr_Map : constant Elist_Id := New_Elmt_List;
8835       Loc       : constant Source_Ptr := Sloc (N);
8836       Prot_Typ  : constant Entity_Id  := Defining_Identifier (N);
8837
8838       Lock_Free_Active : constant Boolean := Uses_Lock_Free (Prot_Typ);
8839       --  This flag indicates whether the lock free implementation is active
8840
8841       Pdef : constant Node_Id := Protected_Definition (N);
8842       --  This contains two lists; one for visible and one for private decls
8843
8844       Body_Arr     : Node_Id;
8845       Body_Id      : Entity_Id;
8846       Cdecls       : List_Id;
8847       Comp         : Node_Id;
8848       Comp_Id      : Entity_Id;
8849       Current_Node : Node_Id := N;
8850       E_Count      : Int;
8851       Entries_Aggr : Node_Id;
8852       New_Priv     : Node_Id;
8853       Object_Comp  : Node_Id;
8854       Priv         : Node_Id;
8855       Rec_Decl     : Node_Id;
8856       Sub          : Node_Id;
8857
8858       procedure Check_Inlining (Subp : Entity_Id);
8859       --  If the original operation has a pragma Inline, propagate the flag
8860       --  to the internal body, for possible inlining later on. The source
8861       --  operation is invisible to the back-end and is never actually called.
8862
8863       function Discriminated_Size (Comp : Entity_Id) return Boolean;
8864       --  If a component size is not static then a warning will be emitted
8865       --  in Ravenscar or other restricted contexts. When a component is non-
8866       --  static because of a discriminant constraint we can specialize the
8867       --  warning by mentioning discriminants explicitly.
8868
8869       procedure Expand_Entry_Declaration (Comp : Entity_Id);
8870       --  Create the subprograms for the barrier and for the body, and append
8871       --  then to Entry_Bodies_Array.
8872
8873       function Static_Component_Size (Comp : Entity_Id) return Boolean;
8874       --  When compiling under the Ravenscar profile, private components must
8875       --  have a static size, or else a protected object  will require heap
8876       --  allocation, violating the corresponding restriction. It is preferable
8877       --  to make this check here, because it provides a better error message
8878       --  than the back-end, which refers to the object as a whole.
8879
8880       procedure Register_Handler;
8881       --  For a protected operation that is an interrupt handler, add the
8882       --  freeze action that will register it as such.
8883
8884       --------------------
8885       -- Check_Inlining --
8886       --------------------
8887
8888       procedure Check_Inlining (Subp : Entity_Id) is
8889       begin
8890          if Is_Inlined (Subp) then
8891             Set_Is_Inlined (Protected_Body_Subprogram (Subp));
8892             Set_Is_Inlined (Subp, False);
8893          end if;
8894       end Check_Inlining;
8895
8896       ------------------------
8897       -- Discriminated_Size --
8898       ------------------------
8899
8900       function Discriminated_Size (Comp : Entity_Id) return Boolean is
8901          Typ   : constant Entity_Id := Etype (Comp);
8902          Index : Node_Id;
8903
8904          function Non_Static_Bound (Bound : Node_Id) return Boolean;
8905          --  Check whether the bound of an index is non-static and does denote
8906          --  a discriminant, in which case any protected object of the type
8907          --  will have a non-static size.
8908
8909          ----------------------
8910          -- Non_Static_Bound --
8911          ----------------------
8912
8913          function Non_Static_Bound (Bound : Node_Id) return Boolean is
8914          begin
8915             if Is_OK_Static_Expression (Bound) then
8916                return False;
8917
8918             elsif Is_Entity_Name (Bound)
8919               and then Present (Discriminal_Link (Entity (Bound)))
8920             then
8921                return False;
8922
8923             else
8924                return True;
8925             end if;
8926          end Non_Static_Bound;
8927
8928       --  Start of processing for Discriminated_Size
8929
8930       begin
8931          if not Is_Array_Type (Typ) then
8932             return False;
8933          end if;
8934
8935          if Ekind (Typ) = E_Array_Subtype then
8936             Index := First_Index (Typ);
8937             while Present (Index) loop
8938                if Non_Static_Bound (Low_Bound (Index))
8939                  or else Non_Static_Bound (High_Bound (Index))
8940                then
8941                   return False;
8942                end if;
8943
8944                Next_Index (Index);
8945             end loop;
8946
8947             return True;
8948          end if;
8949
8950          return False;
8951       end Discriminated_Size;
8952
8953       ---------------------------
8954       -- Static_Component_Size --
8955       ---------------------------
8956
8957       function Static_Component_Size (Comp : Entity_Id) return Boolean is
8958          Typ : constant Entity_Id := Etype (Comp);
8959          C   : Entity_Id;
8960
8961       begin
8962          if Is_Scalar_Type (Typ) then
8963             return True;
8964
8965          elsif Is_Array_Type (Typ) then
8966             return Compile_Time_Known_Bounds (Typ);
8967
8968          elsif Is_Record_Type (Typ) then
8969             C := First_Component (Typ);
8970             while Present (C) loop
8971                if not Static_Component_Size (C) then
8972                   return False;
8973                end if;
8974
8975                Next_Component (C);
8976             end loop;
8977
8978             return True;
8979
8980          --  Any other type will be checked by the back-end
8981
8982          else
8983             return True;
8984          end if;
8985       end Static_Component_Size;
8986
8987       ------------------------------
8988       -- Expand_Entry_Declaration --
8989       ------------------------------
8990
8991       procedure Expand_Entry_Declaration (Comp : Entity_Id) is
8992          Bdef : Entity_Id;
8993          Edef : Entity_Id;
8994
8995       begin
8996          E_Count := E_Count + 1;
8997          Comp_Id := Defining_Identifier (Comp);
8998
8999          Edef :=
9000            Make_Defining_Identifier (Loc,
9001              Chars => Build_Selected_Name (Prot_Typ, Comp_Id, 'E'));
9002          Sub :=
9003            Make_Subprogram_Declaration (Loc,
9004              Specification =>
9005                Build_Protected_Entry_Specification (Loc, Edef, Comp_Id));
9006
9007          Insert_After (Current_Node, Sub);
9008          Analyze (Sub);
9009
9010          --  Build wrapper procedure for pre/postconditions
9011
9012          Build_PPC_Wrapper (Comp_Id, N);
9013
9014          Set_Protected_Body_Subprogram
9015            (Defining_Identifier (Comp),
9016             Defining_Unit_Name (Specification (Sub)));
9017
9018          Current_Node := Sub;
9019
9020          Bdef :=
9021            Make_Defining_Identifier (Loc,
9022              Chars => Build_Selected_Name (Prot_Typ, Comp_Id, 'B'));
9023          Sub :=
9024            Make_Subprogram_Declaration (Loc,
9025              Specification =>
9026                Build_Barrier_Function_Specification (Loc, Bdef));
9027          Set_Is_Entry_Barrier_Function (Sub);
9028
9029          Insert_After (Current_Node, Sub);
9030          Analyze (Sub);
9031          Set_Protected_Body_Subprogram (Bdef, Bdef);
9032          Set_Barrier_Function (Comp_Id, Bdef);
9033          Set_Scope (Bdef, Scope (Comp_Id));
9034          Current_Node := Sub;
9035
9036          --  Collect pointers to the protected subprogram and the barrier
9037          --  of the current entry, for insertion into Entry_Bodies_Array.
9038
9039          Append_To (Expressions (Entries_Aggr),
9040            Make_Aggregate (Loc,
9041              Expressions => New_List (
9042                Make_Attribute_Reference (Loc,
9043                  Prefix         => New_Occurrence_Of (Bdef, Loc),
9044                  Attribute_Name => Name_Unrestricted_Access),
9045                Make_Attribute_Reference (Loc,
9046                  Prefix         => New_Occurrence_Of (Edef, Loc),
9047                  Attribute_Name => Name_Unrestricted_Access))));
9048       end Expand_Entry_Declaration;
9049
9050       ----------------------
9051       -- Register_Handler --
9052       ----------------------
9053
9054       procedure Register_Handler is
9055
9056          --  All semantic checks already done in Sem_Prag
9057
9058          Prot_Proc    : constant Entity_Id :=
9059                           Defining_Unit_Name (Specification (Current_Node));
9060
9061          Proc_Address : constant Node_Id :=
9062                           Make_Attribute_Reference (Loc,
9063                             Prefix         =>
9064                               New_Occurrence_Of (Prot_Proc, Loc),
9065                             Attribute_Name => Name_Address);
9066
9067          RTS_Call     : constant Entity_Id :=
9068                           Make_Procedure_Call_Statement (Loc,
9069                             Name                   =>
9070                               New_Occurrence_Of
9071                                 (RTE (RE_Register_Interrupt_Handler), Loc),
9072                             Parameter_Associations => New_List (Proc_Address));
9073       begin
9074          Append_Freeze_Action (Prot_Proc, RTS_Call);
9075       end Register_Handler;
9076
9077    --  Start of processing for Expand_N_Protected_Type_Declaration
9078
9079    begin
9080       if Present (Corresponding_Record_Type (Prot_Typ)) then
9081          return;
9082       else
9083          Rec_Decl := Build_Corresponding_Record (N, Prot_Typ, Loc);
9084       end if;
9085
9086       Cdecls := Component_Items (Component_List (Type_Definition (Rec_Decl)));
9087
9088       Qualify_Entity_Names (N);
9089
9090       --  If the type has discriminants, their occurrences in the declaration
9091       --  have been replaced by the corresponding discriminals. For components
9092       --  that are constrained by discriminants, their homologues in the
9093       --  corresponding record type must refer to the discriminants of that
9094       --  record, so we must apply a new renaming to subtypes_indications:
9095
9096       --     protected discriminant => discriminal => record discriminant
9097
9098       --  This replacement is not applied to default expressions, for which
9099       --  the discriminal is correct.
9100
9101       if Has_Discriminants (Prot_Typ) then
9102          declare
9103             Disc : Entity_Id;
9104             Decl : Node_Id;
9105
9106          begin
9107             Disc := First_Discriminant (Prot_Typ);
9108             Decl := First (Discriminant_Specifications (Rec_Decl));
9109             while Present (Disc) loop
9110                Append_Elmt (Discriminal (Disc), Discr_Map);
9111                Append_Elmt (Defining_Identifier (Decl), Discr_Map);
9112                Next_Discriminant (Disc);
9113                Next (Decl);
9114             end loop;
9115          end;
9116       end if;
9117
9118       --  Fill in the component declarations
9119
9120       --  Add components for entry families. For each entry family, create an
9121       --  anonymous type declaration with the same size, and analyze the type.
9122
9123       Collect_Entry_Families (Loc, Cdecls, Current_Node, Prot_Typ);
9124
9125       pragma Assert (Present (Pdef));
9126
9127       --  Add private field components
9128
9129       if Present (Private_Declarations (Pdef)) then
9130          Priv := First (Private_Declarations (Pdef));
9131          while Present (Priv) loop
9132             if Nkind (Priv) = N_Component_Declaration then
9133                if not Static_Component_Size (Defining_Identifier (Priv)) then
9134
9135                   --  When compiling for a restricted profile, the private
9136                   --  components must have a static size. If not, this is an
9137                   --  error for a single protected declaration, and rates a
9138                   --  warning on a protected type declaration.
9139
9140                   if not Comes_From_Source (Prot_Typ) then
9141
9142                      --  It's ok to be checking this restriction at expansion
9143                      --  time, because this is only for the restricted profile,
9144                      --  which is not subject to strict RM conformance, so it
9145                      --  is OK to miss this check in -gnatc mode.
9146
9147                      Check_Restriction (No_Implicit_Heap_Allocations, Priv);
9148                      Check_Restriction
9149                        (No_Implicit_Protected_Object_Allocations, Priv);
9150
9151                   elsif Restriction_Active (No_Implicit_Heap_Allocations) then
9152                      if not Discriminated_Size (Defining_Identifier (Priv))
9153                      then
9154                         --  Any object of the type will be  non-static.
9155
9156                         Error_Msg_N ("component has non-static size??", Priv);
9157                         Error_Msg_NE
9158                           ("\creation of protected object of type& will "
9159                            & "violate restriction "
9160                            & "No_Implicit_Heap_Allocations??", Priv, Prot_Typ);
9161                      else
9162
9163                         --  Object will be non-static if discriminants are.
9164
9165                         Error_Msg_NE
9166                           ("creation of protected object of type& with "
9167                            &  "non-static discriminants  will violate"
9168                            & " restriction No_Implicit_Heap_Allocations??",
9169                            Priv, Prot_Typ);
9170                      end if;
9171
9172                   --  Likewise for No_Implicit_Protected_Object_Allocations
9173
9174                   elsif Restriction_Active
9175                     (No_Implicit_Protected_Object_Allocations)
9176                   then
9177                      if not Discriminated_Size (Defining_Identifier (Priv))
9178                      then
9179                         --  Any object of the type will be  non-static.
9180
9181                         Error_Msg_N ("component has non-static size??", Priv);
9182                         Error_Msg_NE
9183                           ("\creation of protected object of type& will "
9184                            & "violate restriction "
9185                            & "No_Implicit_Protected_Object_Allocations??",
9186                            Priv, Prot_Typ);
9187                      else
9188                         --  Object will be non-static if discriminants are.
9189
9190                         Error_Msg_NE
9191                           ("creation of protected object of type& with "
9192                            & "non-static discriminants  will violate "
9193                            & "restriction "
9194                            & "No_Implicit_Protected_Object_Allocations??",
9195                            Priv, Prot_Typ);
9196                      end if;
9197                   end if;
9198                end if;
9199
9200                --  The component definition consists of a subtype indication,
9201                --  or (in Ada 2005) an access definition. Make a copy of the
9202                --  proper definition.
9203
9204                declare
9205                   Old_Comp : constant Node_Id   := Component_Definition (Priv);
9206                   Oent     : constant Entity_Id := Defining_Identifier (Priv);
9207                   Nent     : constant Entity_Id :=
9208                                Make_Defining_Identifier (Sloc (Oent),
9209                                  Chars => Chars (Oent));
9210                   New_Comp : Node_Id;
9211
9212                begin
9213                   if Present (Subtype_Indication (Old_Comp)) then
9214                      New_Comp :=
9215                        Make_Component_Definition (Sloc (Oent),
9216                          Aliased_Present    => False,
9217                          Subtype_Indication =>
9218                            New_Copy_Tree
9219                              (Subtype_Indication (Old_Comp), Discr_Map));
9220                   else
9221                      New_Comp :=
9222                        Make_Component_Definition (Sloc (Oent),
9223                          Aliased_Present    => False,
9224                          Access_Definition  =>
9225                            New_Copy_Tree
9226                              (Access_Definition (Old_Comp), Discr_Map));
9227                   end if;
9228
9229                   New_Priv :=
9230                     Make_Component_Declaration (Loc,
9231                       Defining_Identifier  => Nent,
9232                       Component_Definition => New_Comp,
9233                       Expression           => Expression (Priv));
9234
9235                   Set_Has_Per_Object_Constraint (Nent,
9236                     Has_Per_Object_Constraint (Oent));
9237
9238                   Append_To (Cdecls, New_Priv);
9239                end;
9240
9241             elsif Nkind (Priv) = N_Subprogram_Declaration then
9242
9243                --  Make the unprotected version of the subprogram available
9244                --  for expansion of intra object calls. There is need for
9245                --  a protected version only if the subprogram is an interrupt
9246                --  handler, otherwise  this operation can only be called from
9247                --  within the body.
9248
9249                Sub :=
9250                  Make_Subprogram_Declaration (Loc,
9251                    Specification =>
9252                      Build_Protected_Sub_Specification
9253                        (Priv, Prot_Typ, Unprotected_Mode));
9254
9255                Insert_After (Current_Node, Sub);
9256                Analyze (Sub);
9257
9258                Set_Protected_Body_Subprogram
9259                  (Defining_Unit_Name (Specification (Priv)),
9260                   Defining_Unit_Name (Specification (Sub)));
9261                Check_Inlining (Defining_Unit_Name (Specification (Priv)));
9262                Current_Node := Sub;
9263
9264                Sub :=
9265                  Make_Subprogram_Declaration (Loc,
9266                    Specification =>
9267                      Build_Protected_Sub_Specification
9268                        (Priv, Prot_Typ, Protected_Mode));
9269
9270                Insert_After (Current_Node, Sub);
9271                Analyze (Sub);
9272                Current_Node := Sub;
9273
9274                if Is_Interrupt_Handler
9275                  (Defining_Unit_Name (Specification (Priv)))
9276                then
9277                   if not Restricted_Profile then
9278                      Register_Handler;
9279                   end if;
9280                end if;
9281             end if;
9282
9283             Next (Priv);
9284          end loop;
9285       end if;
9286
9287       --  Except for the lock-free implementation, append the _Object field
9288       --  with the right type to the component list. We need to compute the
9289       --  number of entries, and in some cases the number of Attach_Handler
9290       --  pragmas.
9291
9292       if not Lock_Free_Active then
9293          declare
9294             Entry_Count_Expr   : constant Node_Id :=
9295                                    Build_Entry_Count_Expression
9296                                      (Prot_Typ, Cdecls, Loc);
9297             Num_Attach_Handler : Int := 0;
9298             Protection_Subtype : Node_Id;
9299             Ritem              : Node_Id;
9300
9301          begin
9302             if Has_Attach_Handler (Prot_Typ) then
9303                Ritem := First_Rep_Item (Prot_Typ);
9304                while Present (Ritem) loop
9305                   if Nkind (Ritem) = N_Pragma
9306                     and then Pragma_Name (Ritem) = Name_Attach_Handler
9307                   then
9308                      Num_Attach_Handler := Num_Attach_Handler + 1;
9309                   end if;
9310
9311                   Next_Rep_Item (Ritem);
9312                end loop;
9313             end if;
9314
9315             --  Determine the proper protection type. There are two special
9316             --  cases: 1) when the protected type has dynamic interrupt
9317             --  handlers, and 2) when it has static handlers and we use a
9318             --  restricted profile.
9319
9320             if Has_Attach_Handler (Prot_Typ)
9321               and then not Restricted_Profile
9322             then
9323                Protection_Subtype :=
9324                  Make_Subtype_Indication (Loc,
9325                   Subtype_Mark =>
9326                     New_Occurrence_Of
9327                       (RTE (RE_Static_Interrupt_Protection), Loc),
9328                   Constraint   =>
9329                     Make_Index_Or_Discriminant_Constraint (Loc,
9330                       Constraints => New_List (
9331                         Entry_Count_Expr,
9332                         Make_Integer_Literal (Loc, Num_Attach_Handler))));
9333
9334             elsif Has_Interrupt_Handler (Prot_Typ)
9335               and then not Restriction_Active (No_Dynamic_Attachment)
9336             then
9337                Protection_Subtype :=
9338                  Make_Subtype_Indication (Loc,
9339                    Subtype_Mark =>
9340                      New_Occurrence_Of
9341                        (RTE (RE_Dynamic_Interrupt_Protection), Loc),
9342                    Constraint   =>
9343                      Make_Index_Or_Discriminant_Constraint (Loc,
9344                        Constraints => New_List (Entry_Count_Expr)));
9345
9346             else
9347                case Corresponding_Runtime_Package (Prot_Typ) is
9348                   when System_Tasking_Protected_Objects_Entries =>
9349                      Protection_Subtype :=
9350                         Make_Subtype_Indication (Loc,
9351                           Subtype_Mark =>
9352                             New_Occurrence_Of
9353                               (RTE (RE_Protection_Entries), Loc),
9354                           Constraint   =>
9355                             Make_Index_Or_Discriminant_Constraint (Loc,
9356                               Constraints => New_List (Entry_Count_Expr)));
9357
9358                   when System_Tasking_Protected_Objects_Single_Entry =>
9359                      Protection_Subtype :=
9360                        New_Occurrence_Of (RTE (RE_Protection_Entry), Loc);
9361
9362                   when System_Tasking_Protected_Objects =>
9363                      Protection_Subtype :=
9364                        New_Occurrence_Of (RTE (RE_Protection), Loc);
9365
9366                   when others =>
9367                      raise Program_Error;
9368                end case;
9369             end if;
9370
9371             Object_Comp :=
9372               Make_Component_Declaration (Loc,
9373                 Defining_Identifier  =>
9374                   Make_Defining_Identifier (Loc, Name_uObject),
9375                 Component_Definition =>
9376                   Make_Component_Definition (Loc,
9377                     Aliased_Present    => True,
9378                     Subtype_Indication => Protection_Subtype));
9379          end;
9380
9381          --  Put the _Object component after the private component so that it
9382          --  be finalized early as required by 9.4 (20)
9383
9384          Append_To (Cdecls, Object_Comp);
9385       end if;
9386
9387       Insert_After (Current_Node, Rec_Decl);
9388       Current_Node := Rec_Decl;
9389
9390       --  Analyze the record declaration immediately after construction,
9391       --  because the initialization procedure is needed for single object
9392       --  declarations before the next entity is analyzed (the freeze call
9393       --  that generates this initialization procedure is found below).
9394
9395       Analyze (Rec_Decl, Suppress => All_Checks);
9396
9397       --  Ada 2005 (AI-345): Construct the primitive entry wrappers before
9398       --  the corresponding record is frozen. If any wrappers are generated,
9399       --  Current_Node is updated accordingly.
9400
9401       if Ada_Version >= Ada_2005 then
9402          Build_Wrapper_Specs (Loc, Prot_Typ, Current_Node);
9403       end if;
9404
9405       --  Collect pointers to entry bodies and their barriers, to be placed
9406       --  in the Entry_Bodies_Array for the type. For each entry/family we
9407       --  add an expression to the aggregate which is the initial value of
9408       --  this array. The array is declared after all protected subprograms.
9409
9410       if Has_Entries (Prot_Typ) then
9411          Entries_Aggr := Make_Aggregate (Loc, Expressions => New_List);
9412       else
9413          Entries_Aggr := Empty;
9414       end if;
9415
9416       --  Build two new procedure specifications for each protected subprogram;
9417       --  one to call from outside the object and one to call from inside.
9418       --  Build a barrier function and an entry body action procedure
9419       --  specification for each protected entry. Initialize the entry body
9420       --  array. If subprogram is flagged as eliminated, do not generate any
9421       --  internal operations.
9422
9423       E_Count := 0;
9424       Comp := First (Visible_Declarations (Pdef));
9425       while Present (Comp) loop
9426          if Nkind (Comp) = N_Subprogram_Declaration then
9427             Sub :=
9428               Make_Subprogram_Declaration (Loc,
9429                 Specification =>
9430                   Build_Protected_Sub_Specification
9431                     (Comp, Prot_Typ, Unprotected_Mode));
9432
9433             Insert_After (Current_Node, Sub);
9434             Analyze (Sub);
9435
9436             Set_Protected_Body_Subprogram
9437               (Defining_Unit_Name (Specification (Comp)),
9438                Defining_Unit_Name (Specification (Sub)));
9439             Check_Inlining (Defining_Unit_Name (Specification (Comp)));
9440
9441             --  Make the protected version of the subprogram available for
9442             --  expansion of external calls.
9443
9444             Current_Node := Sub;
9445
9446             Sub :=
9447               Make_Subprogram_Declaration (Loc,
9448                 Specification =>
9449                   Build_Protected_Sub_Specification
9450                     (Comp, Prot_Typ, Protected_Mode));
9451
9452             Insert_After (Current_Node, Sub);
9453             Analyze (Sub);
9454
9455             Current_Node := Sub;
9456
9457             --  Generate an overriding primitive operation specification for
9458             --  this subprogram if the protected type implements an interface.
9459
9460             if Ada_Version >= Ada_2005
9461               and then
9462                 Present (Interfaces (Corresponding_Record_Type (Prot_Typ)))
9463             then
9464                Sub :=
9465                  Make_Subprogram_Declaration (Loc,
9466                    Specification =>
9467                      Build_Protected_Sub_Specification
9468                        (Comp, Prot_Typ, Dispatching_Mode));
9469
9470                Insert_After (Current_Node, Sub);
9471                Analyze (Sub);
9472
9473                Current_Node := Sub;
9474             end if;
9475
9476             --  If a pragma Interrupt_Handler applies, build and add a call to
9477             --  Register_Interrupt_Handler to the freezing actions of the
9478             --  protected version (Current_Node) of the subprogram:
9479
9480             --    system.interrupts.register_interrupt_handler
9481             --       (prot_procP'address);
9482
9483             if not Restricted_Profile
9484               and then Is_Interrupt_Handler
9485                          (Defining_Unit_Name (Specification (Comp)))
9486             then
9487                Register_Handler;
9488             end if;
9489
9490          elsif Nkind (Comp) = N_Entry_Declaration then
9491             Expand_Entry_Declaration (Comp);
9492          end if;
9493
9494          Next (Comp);
9495       end loop;
9496
9497       --  If there are some private entry declarations, expand it as if they
9498       --  were visible entries.
9499
9500       if Present (Private_Declarations (Pdef)) then
9501          Comp := First (Private_Declarations (Pdef));
9502          while Present (Comp) loop
9503             if Nkind (Comp) = N_Entry_Declaration then
9504                Expand_Entry_Declaration (Comp);
9505             end if;
9506
9507             Next (Comp);
9508          end loop;
9509       end if;
9510
9511       --  Emit declaration for Entry_Bodies_Array, now that the addresses of
9512       --  all protected subprograms have been collected.
9513
9514       if Has_Entries (Prot_Typ) then
9515          Body_Id :=
9516            Make_Defining_Identifier (Sloc (Prot_Typ),
9517              Chars => New_External_Name (Chars (Prot_Typ), 'A'));
9518
9519          case Corresponding_Runtime_Package (Prot_Typ) is
9520             when System_Tasking_Protected_Objects_Entries =>
9521                Body_Arr :=
9522                  Make_Object_Declaration (Loc,
9523                    Defining_Identifier => Body_Id,
9524                    Aliased_Present => True,
9525                    Object_Definition =>
9526                      Make_Subtype_Indication (Loc,
9527                        Subtype_Mark =>
9528                          New_Occurrence_Of
9529                            (RTE (RE_Protected_Entry_Body_Array), Loc),
9530                        Constraint =>
9531                          Make_Index_Or_Discriminant_Constraint (Loc,
9532                            Constraints => New_List (
9533                               Make_Range (Loc,
9534                                 Make_Integer_Literal (Loc, 1),
9535                                 Make_Integer_Literal (Loc, E_Count))))),
9536                    Expression => Entries_Aggr);
9537
9538             when System_Tasking_Protected_Objects_Single_Entry =>
9539                Body_Arr :=
9540                  Make_Object_Declaration (Loc,
9541                    Defining_Identifier => Body_Id,
9542                    Aliased_Present     => True,
9543                    Object_Definition   =>
9544                      New_Occurrence_Of (RTE (RE_Entry_Body), Loc),
9545                    Expression => Remove_Head (Expressions (Entries_Aggr)));
9546
9547             when others =>
9548                raise Program_Error;
9549          end case;
9550
9551          --  A pointer to this array will be placed in the corresponding record
9552          --  by its initialization procedure so this needs to be analyzed here.
9553
9554          Insert_After (Current_Node, Body_Arr);
9555          Current_Node := Body_Arr;
9556          Analyze (Body_Arr);
9557
9558          Set_Entry_Bodies_Array (Prot_Typ, Body_Id);
9559
9560          --  Finally, build the function that maps an entry index into the
9561          --  corresponding body. A pointer to this function is placed in each
9562          --  object of the type. Except for a ravenscar-like profile (no abort,
9563          --  no entry queue, 1 entry)
9564
9565          if Corresponding_Runtime_Package (Prot_Typ) =
9566               System_Tasking_Protected_Objects_Entries
9567          then
9568             Sub :=
9569               Make_Subprogram_Declaration (Loc,
9570                 Specification => Build_Find_Body_Index_Spec (Prot_Typ));
9571             Insert_After (Current_Node, Sub);
9572             Analyze (Sub);
9573          end if;
9574       end if;
9575    end Expand_N_Protected_Type_Declaration;
9576
9577    --------------------------------
9578    -- Expand_N_Requeue_Statement --
9579    --------------------------------
9580
9581    --  A non-dispatching requeue statement is expanded into one of four GNARLI
9582    --  operations, depending on the source and destination (task or protected
9583    --  object). A dispatching requeue statement is expanded into a call to the
9584    --  predefined primitive _Disp_Requeue. In addition, code is generated to
9585    --  jump around the remainder of processing for the original entry and, if
9586    --  the destination is (different) protected object, to attempt to service
9587    --  it. The following illustrates the various cases:
9588
9589    --  procedure entE
9590    --    (O : System.Address;
9591    --     P : System.Address;
9592    --     E : Protected_Entry_Index)
9593    --  is
9594    --     <discriminant renamings>
9595    --     <private object renamings>
9596    --     type poVP is access poV;
9597    --     _object : ptVP := ptVP!(O);
9598
9599    --  begin
9600    --     begin
9601    --        <start of statement sequence for entry>
9602
9603    --        -- Requeue from one protected entry body to another protected
9604    --        -- entry.
9605
9606    --        Requeue_Protected_Entry (
9607    --          _object._object'Access,
9608    --          new._object'Access,
9609    --          E,
9610    --          Abort_Present);
9611    --        return;
9612
9613    --        <some more of the statement sequence for entry>
9614
9615    --        --  Requeue from an entry body to a task entry
9616
9617    --        Requeue_Protected_To_Task_Entry (
9618    --          New._task_id,
9619    --          E,
9620    --          Abort_Present);
9621    --        return;
9622
9623    --        <rest of statement sequence for entry>
9624    --        Complete_Entry_Body (_object._object);
9625
9626    --     exception
9627    --        when all others =>
9628    --           Exceptional_Complete_Entry_Body (
9629    --             _object._object, Get_GNAT_Exception);
9630    --     end;
9631    --  end entE;
9632
9633    --  Requeue of a task entry call to a task entry
9634
9635    --  Accept_Call (E, Ann);
9636    --     <start of statement sequence for accept statement>
9637    --     Requeue_Task_Entry (New._task_id, E, Abort_Present);
9638    --     goto Lnn;
9639    --     <rest of statement sequence for accept statement>
9640    --     <<Lnn>>
9641    --     Complete_Rendezvous;
9642
9643    --  exception
9644    --     when all others =>
9645    --        Exceptional_Complete_Rendezvous (Get_GNAT_Exception);
9646
9647    --  Requeue of a task entry call to a protected entry
9648
9649    --  Accept_Call (E, Ann);
9650    --     <start of statement sequence for accept statement>
9651    --     Requeue_Task_To_Protected_Entry (
9652    --       new._object'Access,
9653    --       E,
9654    --       Abort_Present);
9655    --     newS (new, Pnn);
9656    --     goto Lnn;
9657    --     <rest of statement sequence for accept statement>
9658    --     <<Lnn>>
9659    --     Complete_Rendezvous;
9660
9661    --  exception
9662    --     when all others =>
9663    --        Exceptional_Complete_Rendezvous (Get_GNAT_Exception);
9664
9665    --  Ada 2012 (AI05-0030): Dispatching requeue to an interface primitive
9666    --  marked by pragma Implemented (XXX, By_Entry).
9667
9668    --  The requeue is inside a protected entry:
9669
9670    --  procedure entE
9671    --    (O : System.Address;
9672    --     P : System.Address;
9673    --     E : Protected_Entry_Index)
9674    --  is
9675    --     <discriminant renamings>
9676    --     <private object renamings>
9677    --     type poVP is access poV;
9678    --     _object : ptVP := ptVP!(O);
9679
9680    --  begin
9681    --     begin
9682    --        <start of statement sequence for entry>
9683
9684    --        _Disp_Requeue
9685    --          (<interface class-wide object>,
9686    --           True,
9687    --           _object'Address,
9688    --           Ada.Tags.Get_Offset_Index
9689    --             (Tag (_object),
9690    --              <interface dispatch table index of target entry>),
9691    --           Abort_Present);
9692    --        return;
9693
9694    --        <rest of statement sequence for entry>
9695    --        Complete_Entry_Body (_object._object);
9696
9697    --     exception
9698    --        when all others =>
9699    --           Exceptional_Complete_Entry_Body (
9700    --             _object._object, Get_GNAT_Exception);
9701    --     end;
9702    --  end entE;
9703
9704    --  The requeue is inside a task entry:
9705
9706    --    Accept_Call (E, Ann);
9707    --     <start of statement sequence for accept statement>
9708    --     _Disp_Requeue
9709    --       (<interface class-wide object>,
9710    --        False,
9711    --        null,
9712    --        Ada.Tags.Get_Offset_Index
9713    --          (Tag (_object),
9714    --           <interface dispatch table index of target entrt>),
9715    --        Abort_Present);
9716    --     newS (new, Pnn);
9717    --     goto Lnn;
9718    --     <rest of statement sequence for accept statement>
9719    --     <<Lnn>>
9720    --     Complete_Rendezvous;
9721
9722    --  exception
9723    --     when all others =>
9724    --        Exceptional_Complete_Rendezvous (Get_GNAT_Exception);
9725
9726    --  Ada 2012 (AI05-0030): Dispatching requeue to an interface primitive
9727    --  marked by pragma Implemented (XXX, By_Protected_Procedure). The requeue
9728    --  statement is replaced by a dispatching call with actual parameters taken
9729    --  from the inner-most accept statement or entry body.
9730
9731    --    Target.Primitive (Param1, ..., ParamN);
9732
9733    --  Ada 2012 (AI05-0030): Dispatching requeue to an interface primitive
9734    --  marked by pragma Implemented (XXX, By_Any | Optional) or not marked
9735    --  at all.
9736
9737    --    declare
9738    --       S : constant Offset_Index :=
9739    --             Get_Offset_Index (Tag (Concval), DT_Position (Ename));
9740    --       C : constant Prim_Op_Kind := Get_Prim_Op_Kind (Tag (Concval), S);
9741
9742    --    begin
9743    --       if C = POK_Protected_Entry
9744    --         or else C = POK_Task_Entry
9745    --       then
9746    --          <statements for dispatching requeue>
9747
9748    --       elsif C = POK_Protected_Procedure then
9749    --          <dispatching call equivalent>
9750
9751    --       else
9752    --          raise Program_Error;
9753    --       end if;
9754    --    end;
9755
9756    procedure Expand_N_Requeue_Statement (N : Node_Id) is
9757       Loc      : constant Source_Ptr := Sloc (N);
9758       Conc_Typ : Entity_Id;
9759       Concval  : Node_Id;
9760       Ename    : Node_Id;
9761       Index    : Node_Id;
9762       Old_Typ  : Entity_Id;
9763
9764       function Build_Dispatching_Call_Equivalent return Node_Id;
9765       --  Ada 2012 (AI05-0030): N denotes a dispatching requeue statement of
9766       --  the form Concval.Ename. It is statically known that Ename is allowed
9767       --  to be implemented by a protected procedure. Create a dispatching call
9768       --  equivalent of Concval.Ename taking the actual parameters from the
9769       --  inner-most accept statement or entry body.
9770
9771       function Build_Dispatching_Requeue return Node_Id;
9772       --  Ada 2012 (AI05-0030): N denotes a dispatching requeue statement of
9773       --  the form Concval.Ename. It is statically known that Ename is allowed
9774       --  to be implemented by a protected or a task entry. Create a call to
9775       --  primitive _Disp_Requeue which handles the low-level actions.
9776
9777       function Build_Dispatching_Requeue_To_Any return Node_Id;
9778       --  Ada 2012 (AI05-0030): N denotes a dispatching requeue statement of
9779       --  the form Concval.Ename. Ename is either marked by pragma Implemented
9780       --  (XXX, By_Any | Optional) or not marked at all. Create a block which
9781       --  determines at runtime whether Ename denotes an entry or a procedure
9782       --  and perform the appropriate kind of dispatching select.
9783
9784       function Build_Normal_Requeue return Node_Id;
9785       --  N denotes a non-dispatching requeue statement to either a task or a
9786       --  protected entry. Build the appropriate runtime call to perform the
9787       --  action.
9788
9789       function Build_Skip_Statement (Search : Node_Id) return Node_Id;
9790       --  For a protected entry, create a return statement to skip the rest of
9791       --  the entry body. Otherwise, create a goto statement to skip the rest
9792       --  of a task accept statement. The lookup for the enclosing entry body
9793       --  or accept statement starts from Search.
9794
9795       ---------------------------------------
9796       -- Build_Dispatching_Call_Equivalent --
9797       ---------------------------------------
9798
9799       function Build_Dispatching_Call_Equivalent return Node_Id is
9800          Call_Ent : constant Entity_Id := Entity (Ename);
9801          Obj      : constant Node_Id   := Original_Node (Concval);
9802          Acc_Ent  : Node_Id;
9803          Actuals  : List_Id;
9804          Formal   : Node_Id;
9805          Formals  : List_Id;
9806
9807       begin
9808          --  Climb the parent chain looking for the inner-most entry body or
9809          --  accept statement.
9810
9811          Acc_Ent := N;
9812          while Present (Acc_Ent)
9813            and then not Nkind_In (Acc_Ent, N_Accept_Statement,
9814                                            N_Entry_Body)
9815          loop
9816             Acc_Ent := Parent (Acc_Ent);
9817          end loop;
9818
9819          --  A requeue statement should be housed inside an entry body or an
9820          --  accept statement at some level. If this is not the case, then the
9821          --  tree is malformed.
9822
9823          pragma Assert (Present (Acc_Ent));
9824
9825          --  Recover the list of formal parameters
9826
9827          if Nkind (Acc_Ent) = N_Entry_Body then
9828             Acc_Ent := Entry_Body_Formal_Part (Acc_Ent);
9829          end if;
9830
9831          Formals := Parameter_Specifications (Acc_Ent);
9832
9833          --  Create the actual parameters for the dispatching call. These are
9834          --  simply copies of the entry body or accept statement formals in the
9835          --  same order as they appear.
9836
9837          Actuals := No_List;
9838
9839          if Present (Formals) then
9840             Actuals := New_List;
9841             Formal  := First (Formals);
9842             while Present (Formal) loop
9843                Append_To (Actuals,
9844                  Make_Identifier (Loc, Chars (Defining_Identifier (Formal))));
9845                Next (Formal);
9846             end loop;
9847          end if;
9848
9849          --  Generate:
9850          --    Obj.Call_Ent (Actuals);
9851
9852          return
9853            Make_Procedure_Call_Statement (Loc,
9854              Name =>
9855                Make_Selected_Component (Loc,
9856                  Prefix        => Make_Identifier (Loc, Chars (Obj)),
9857                  Selector_Name => Make_Identifier (Loc, Chars (Call_Ent))),
9858
9859              Parameter_Associations => Actuals);
9860       end Build_Dispatching_Call_Equivalent;
9861
9862       -------------------------------
9863       -- Build_Dispatching_Requeue --
9864       -------------------------------
9865
9866       function Build_Dispatching_Requeue return Node_Id is
9867          Params : constant List_Id := New_List;
9868
9869       begin
9870          --  Process the "with abort" parameter
9871
9872          Prepend_To (Params,
9873            New_Occurrence_Of (Boolean_Literals (Abort_Present (N)), Loc));
9874
9875          --  Process the entry wrapper's position in the primary dispatch
9876          --  table parameter. Generate:
9877
9878          --    Ada.Tags.Get_Entry_Index
9879          --      (T        => To_Tag_Ptr (Obj'Address).all,
9880          --       Position =>
9881          --         Ada.Tags.Get_Offset_Index
9882          --           (Ada.Tags.Tag (Concval),
9883          --            <interface dispatch table position of Ename>));
9884
9885          --  Note that Obj'Address is recursively expanded into a call to
9886          --  Base_Address (Obj).
9887
9888          if Tagged_Type_Expansion then
9889             Prepend_To (Params,
9890               Make_Function_Call (Loc,
9891                 Name => New_Occurrence_Of (RTE (RE_Get_Entry_Index), Loc),
9892                 Parameter_Associations => New_List (
9893
9894                   Make_Explicit_Dereference (Loc,
9895                     Unchecked_Convert_To (RTE (RE_Tag_Ptr),
9896                       Make_Attribute_Reference (Loc,
9897                         Prefix => New_Copy_Tree (Concval),
9898                         Attribute_Name => Name_Address))),
9899
9900                   Make_Function_Call (Loc,
9901                     Name => New_Occurrence_Of (RTE (RE_Get_Offset_Index), Loc),
9902                     Parameter_Associations => New_List (
9903                       Unchecked_Convert_To (RTE (RE_Tag), Concval),
9904                       Make_Integer_Literal (Loc,
9905                         DT_Position (Entity (Ename))))))));
9906
9907          --  VM targets
9908
9909          else
9910             Prepend_To (Params,
9911               Make_Function_Call (Loc,
9912                 Name => New_Occurrence_Of (RTE (RE_Get_Entry_Index), Loc),
9913                 Parameter_Associations => New_List (
9914
9915                   Make_Attribute_Reference (Loc,
9916                     Prefix         => Concval,
9917                     Attribute_Name => Name_Tag),
9918
9919                   Make_Function_Call (Loc,
9920                     Name => New_Occurrence_Of (RTE (RE_Get_Offset_Index), Loc),
9921
9922                     Parameter_Associations => New_List (
9923
9924                       --  Obj_Tag
9925
9926                       Make_Attribute_Reference (Loc,
9927                         Prefix => Concval,
9928                         Attribute_Name => Name_Tag),
9929
9930                       --  Tag_Typ
9931
9932                       Make_Attribute_Reference (Loc,
9933                         Prefix => New_Occurrence_Of (Etype (Concval), Loc),
9934                         Attribute_Name => Name_Tag),
9935
9936                       --  Position
9937
9938                       Make_Integer_Literal (Loc,
9939                         DT_Position (Entity (Ename))))))));
9940          end if;
9941
9942          --  Specific actuals for protected to XXX requeue
9943
9944          if Is_Protected_Type (Old_Typ) then
9945             Prepend_To (Params,
9946               Make_Attribute_Reference (Loc,        --  _object'Address
9947                 Prefix =>
9948                   Concurrent_Ref (New_Occurrence_Of (Old_Typ, Loc)),
9949                 Attribute_Name => Name_Address));
9950
9951             Prepend_To (Params,                     --  True
9952               New_Occurrence_Of (Standard_True, Loc));
9953
9954          --  Specific actuals for task to XXX requeue
9955
9956          else
9957             pragma Assert (Is_Task_Type (Old_Typ));
9958
9959             Prepend_To (Params,                     --  null
9960               New_Occurrence_Of (RTE (RE_Null_Address), Loc));
9961
9962             Prepend_To (Params,                     --  False
9963               New_Occurrence_Of (Standard_False, Loc));
9964          end if;
9965
9966          --  Add the object parameter
9967
9968          Prepend_To (Params, New_Copy_Tree (Concval));
9969
9970          --  Generate:
9971          --    _Disp_Requeue (<Params>);
9972
9973          --  Find entity for Disp_Requeue operation, which belongs to
9974          --  the type and may not be directly visible.
9975
9976          declare
9977             Elmt : Elmt_Id;
9978             Op   : Entity_Id;
9979
9980          begin
9981             Elmt := First_Elmt (Primitive_Operations (Etype (Conc_Typ)));
9982             while Present (Elmt) loop
9983                Op := Node (Elmt);
9984                exit when Chars (Op) = Name_uDisp_Requeue;
9985                Next_Elmt (Elmt);
9986             end loop;
9987
9988             return
9989               Make_Procedure_Call_Statement (Loc,
9990                 Name                   => New_Occurrence_Of (Op, Loc),
9991                 Parameter_Associations => Params);
9992          end;
9993       end Build_Dispatching_Requeue;
9994
9995       --------------------------------------
9996       -- Build_Dispatching_Requeue_To_Any --
9997       --------------------------------------
9998
9999       function Build_Dispatching_Requeue_To_Any return Node_Id is
10000          Call_Ent : constant Entity_Id := Entity (Ename);
10001          Obj      : constant Node_Id   := Original_Node (Concval);
10002          Skip     : constant Node_Id   := Build_Skip_Statement (N);
10003          C        : Entity_Id;
10004          Decls    : List_Id;
10005          S        : Entity_Id;
10006          Stmts    : List_Id;
10007
10008       begin
10009          Decls := New_List;
10010          Stmts := New_List;
10011
10012          --  Dispatch table slot processing, generate:
10013          --    S : Integer;
10014
10015          S := Build_S (Loc, Decls);
10016
10017          --  Call kind processing, generate:
10018          --    C : Ada.Tags.Prim_Op_Kind;
10019
10020          C := Build_C (Loc, Decls);
10021
10022          --  Generate:
10023          --    S := Ada.Tags.Get_Offset_Index
10024          --           (Ada.Tags.Tag (Obj), DT_Position (Call_Ent));
10025
10026          Append_To (Stmts, Build_S_Assignment (Loc, S, Obj, Call_Ent));
10027
10028          --  Generate:
10029          --    _Disp_Get_Prim_Op_Kind (Obj, S, C);
10030
10031          Append_To (Stmts,
10032            Make_Procedure_Call_Statement (Loc,
10033              Name =>
10034                New_Occurrence_Of (
10035                  Find_Prim_Op (Etype (Etype (Obj)),
10036                    Name_uDisp_Get_Prim_Op_Kind),
10037                  Loc),
10038              Parameter_Associations => New_List (
10039                New_Copy_Tree (Obj),
10040                New_Occurrence_Of (S, Loc),
10041                New_Occurrence_Of (C, Loc))));
10042
10043          Append_To (Stmts,
10044
10045             --  if C = POK_Protected_Entry
10046             --    or else C = POK_Task_Entry
10047             --  then
10048
10049            Make_Implicit_If_Statement (N,
10050              Condition =>
10051                Make_Op_Or (Loc,
10052                  Left_Opnd =>
10053                    Make_Op_Eq (Loc,
10054                      Left_Opnd =>
10055                        New_Occurrence_Of (C, Loc),
10056                      Right_Opnd =>
10057                        New_Occurrence_Of (RTE (RE_POK_Protected_Entry), Loc)),
10058
10059                  Right_Opnd =>
10060                    Make_Op_Eq (Loc,
10061                      Left_Opnd =>
10062                        New_Occurrence_Of (C, Loc),
10063                      Right_Opnd =>
10064                        New_Occurrence_Of (RTE (RE_POK_Task_Entry), Loc))),
10065
10066                --  Dispatching requeue equivalent
10067
10068              Then_Statements => New_List (
10069                Build_Dispatching_Requeue,
10070                Skip),
10071
10072                --  elsif C = POK_Protected_Procedure then
10073
10074              Elsif_Parts => New_List (
10075                Make_Elsif_Part (Loc,
10076                  Condition =>
10077                    Make_Op_Eq (Loc,
10078                      Left_Opnd =>
10079                        New_Occurrence_Of (C, Loc),
10080                      Right_Opnd =>
10081                        New_Occurrence_Of (
10082                          RTE (RE_POK_Protected_Procedure), Loc)),
10083
10084                   --  Dispatching call equivalent
10085
10086                  Then_Statements => New_List (
10087                    Build_Dispatching_Call_Equivalent))),
10088
10089             --  else
10090             --     raise Program_Error;
10091             --  end if;
10092
10093              Else_Statements => New_List (
10094                Make_Raise_Program_Error (Loc,
10095                  Reason => PE_Explicit_Raise))));
10096
10097          --  Wrap everything into a block
10098
10099          return
10100            Make_Block_Statement (Loc,
10101              Declarations => Decls,
10102              Handled_Statement_Sequence =>
10103                Make_Handled_Sequence_Of_Statements (Loc,
10104                  Statements => Stmts));
10105       end Build_Dispatching_Requeue_To_Any;
10106
10107       --------------------------
10108       -- Build_Normal_Requeue --
10109       --------------------------
10110
10111       function Build_Normal_Requeue return Node_Id is
10112          Params  : constant List_Id := New_List;
10113          Param   : Node_Id;
10114          RT_Call : Node_Id;
10115
10116       begin
10117          --  Process the "with abort" parameter
10118
10119          Prepend_To (Params,
10120            New_Occurrence_Of (Boolean_Literals (Abort_Present (N)), Loc));
10121
10122          --  Add the index expression to the parameters. It is common among all
10123          --  four cases.
10124
10125          Prepend_To (Params,
10126            Entry_Index_Expression (Loc, Entity (Ename), Index, Conc_Typ));
10127
10128          if Is_Protected_Type (Old_Typ) then
10129             declare
10130                Self_Param : Node_Id;
10131
10132             begin
10133                Self_Param :=
10134                  Make_Attribute_Reference (Loc,
10135                    Prefix =>
10136                      Concurrent_Ref (New_Occurrence_Of (Old_Typ, Loc)),
10137                    Attribute_Name =>
10138                      Name_Unchecked_Access);
10139
10140                --  Protected to protected requeue
10141
10142                if Is_Protected_Type (Conc_Typ) then
10143                   RT_Call :=
10144                     New_Occurrence_Of (
10145                       RTE (RE_Requeue_Protected_Entry), Loc);
10146
10147                   Param :=
10148                     Make_Attribute_Reference (Loc,
10149                       Prefix =>
10150                         Concurrent_Ref (Concval),
10151                       Attribute_Name =>
10152                         Name_Unchecked_Access);
10153
10154                --  Protected to task requeue
10155
10156                else pragma Assert (Is_Task_Type (Conc_Typ));
10157                   RT_Call :=
10158                     New_Occurrence_Of (
10159                       RTE (RE_Requeue_Protected_To_Task_Entry), Loc);
10160
10161                   Param := Concurrent_Ref (Concval);
10162                end if;
10163
10164                Prepend_To (Params, Param);
10165                Prepend_To (Params, Self_Param);
10166             end;
10167
10168          else pragma Assert (Is_Task_Type (Old_Typ));
10169
10170             --  Task to protected requeue
10171
10172             if Is_Protected_Type (Conc_Typ) then
10173                RT_Call :=
10174                  New_Occurrence_Of (
10175                    RTE (RE_Requeue_Task_To_Protected_Entry), Loc);
10176
10177                Param :=
10178                  Make_Attribute_Reference (Loc,
10179                    Prefix =>
10180                      Concurrent_Ref (Concval),
10181                    Attribute_Name =>
10182                      Name_Unchecked_Access);
10183
10184             --  Task to task requeue
10185
10186             else pragma Assert (Is_Task_Type (Conc_Typ));
10187                RT_Call :=
10188                  New_Occurrence_Of (RTE (RE_Requeue_Task_Entry), Loc);
10189
10190                Param := Concurrent_Ref (Concval);
10191             end if;
10192
10193             Prepend_To (Params, Param);
10194          end if;
10195
10196          return
10197             Make_Procedure_Call_Statement (Loc,
10198               Name => RT_Call,
10199               Parameter_Associations => Params);
10200       end Build_Normal_Requeue;
10201
10202       --------------------------
10203       -- Build_Skip_Statement --
10204       --------------------------
10205
10206       function Build_Skip_Statement (Search : Node_Id) return Node_Id is
10207          Skip_Stmt : Node_Id;
10208
10209       begin
10210          --  Build a return statement to skip the rest of the entire body
10211
10212          if Is_Protected_Type (Old_Typ) then
10213             Skip_Stmt := Make_Simple_Return_Statement (Loc);
10214
10215          --  If the requeue is within a task, find the end label of the
10216          --  enclosing accept statement and create a goto statement to it.
10217
10218          else
10219             declare
10220                Acc   : Node_Id;
10221                Label : Node_Id;
10222
10223             begin
10224                --  Climb the parent chain looking for the enclosing accept
10225                --  statement.
10226
10227                Acc := Parent (Search);
10228                while Present (Acc)
10229                  and then Nkind (Acc) /= N_Accept_Statement
10230                loop
10231                   Acc := Parent (Acc);
10232                end loop;
10233
10234                --  The last statement is the second label used for completing
10235                --  the rendezvous the usual way. The label we are looking for
10236                --  is right before it.
10237
10238                Label :=
10239                  Prev (Last (Statements (Handled_Statement_Sequence (Acc))));
10240
10241                pragma Assert (Nkind (Label) = N_Label);
10242
10243                --  Generate a goto statement to skip the rest of the accept
10244
10245                Skip_Stmt :=
10246                  Make_Goto_Statement (Loc,
10247                    Name =>
10248                      New_Occurrence_Of (Entity (Identifier (Label)), Loc));
10249             end;
10250          end if;
10251
10252          Set_Analyzed (Skip_Stmt);
10253
10254          return Skip_Stmt;
10255       end Build_Skip_Statement;
10256
10257    --  Start of processing for Expand_N_Requeue_Statement
10258
10259    begin
10260       --  Extract the components of the entry call
10261
10262       Extract_Entry (N, Concval, Ename, Index);
10263       Conc_Typ := Etype (Concval);
10264
10265       --  If the prefix is an access to class-wide type, dereference to get
10266       --  object and entry type.
10267
10268       if Is_Access_Type (Conc_Typ) then
10269          Conc_Typ := Designated_Type (Conc_Typ);
10270          Rewrite (Concval,
10271            Make_Explicit_Dereference (Loc, Relocate_Node (Concval)));
10272          Analyze_And_Resolve (Concval, Conc_Typ);
10273       end if;
10274
10275       --  Examine the scope stack in order to find nearest enclosing protected
10276       --  or task type. This will constitute our invocation source.
10277
10278       Old_Typ := Current_Scope;
10279       while Present (Old_Typ)
10280         and then not Is_Protected_Type (Old_Typ)
10281         and then not Is_Task_Type (Old_Typ)
10282       loop
10283          Old_Typ := Scope (Old_Typ);
10284       end loop;
10285
10286       --  Ada 2012 (AI05-0030): We have a dispatching requeue of the form
10287       --  Concval.Ename where the type of Concval is class-wide concurrent
10288       --  interface.
10289
10290       if Ada_Version >= Ada_2012
10291         and then Present (Concval)
10292         and then Is_Class_Wide_Type (Conc_Typ)
10293         and then Is_Concurrent_Interface (Conc_Typ)
10294       then
10295          declare
10296             Has_Impl  : Boolean := False;
10297             Impl_Kind : Name_Id := No_Name;
10298
10299          begin
10300             --  Check whether the Ename is flagged by pragma Implemented
10301
10302             if Has_Rep_Pragma (Entity (Ename), Name_Implemented) then
10303                Has_Impl  := True;
10304                Impl_Kind := Implementation_Kind (Entity (Ename));
10305             end if;
10306
10307             --  The procedure_or_entry_NAME is guaranteed to be overridden by
10308             --  an entry. Create a call to predefined primitive _Disp_Requeue.
10309
10310             if Has_Impl and then Impl_Kind = Name_By_Entry then
10311                Rewrite (N, Build_Dispatching_Requeue);
10312                Analyze (N);
10313                Insert_After (N, Build_Skip_Statement (N));
10314
10315             --  The procedure_or_entry_NAME is guaranteed to be overridden by
10316             --  a protected procedure. In this case the requeue is transformed
10317             --  into a dispatching call.
10318
10319             elsif Has_Impl
10320               and then Impl_Kind = Name_By_Protected_Procedure
10321             then
10322                Rewrite (N, Build_Dispatching_Call_Equivalent);
10323                Analyze (N);
10324
10325             --  The procedure_or_entry_NAME's implementation kind is either
10326             --  By_Any, Optional, or pragma Implemented was not applied at all.
10327             --  In this case a runtime test determines whether Ename denotes an
10328             --  entry or a protected procedure and performs the appropriate
10329             --  call.
10330
10331             else
10332                Rewrite (N, Build_Dispatching_Requeue_To_Any);
10333                Analyze (N);
10334             end if;
10335          end;
10336
10337       --  Processing for regular (non-dispatching) requeues
10338
10339       else
10340          Rewrite (N, Build_Normal_Requeue);
10341          Analyze (N);
10342          Insert_After (N, Build_Skip_Statement (N));
10343       end if;
10344    end Expand_N_Requeue_Statement;
10345
10346    -------------------------------
10347    -- Expand_N_Selective_Accept --
10348    -------------------------------
10349
10350    procedure Expand_N_Selective_Accept (N : Node_Id) is
10351       Loc            : constant Source_Ptr := Sloc (N);
10352       Alts           : constant List_Id    := Select_Alternatives (N);
10353
10354       --  Note: in the below declarations a lot of new lists are allocated
10355       --  unconditionally which may well not end up being used. That's not
10356       --  a good idea since it wastes space gratuitously ???
10357
10358       Accept_Case    : List_Id;
10359       Accept_List    : constant List_Id := New_List;
10360
10361       Alt            : Node_Id;
10362       Alt_List       : constant List_Id := New_List;
10363       Alt_Stats      : List_Id;
10364       Ann            : Entity_Id := Empty;
10365
10366       Check_Guard    : Boolean := True;
10367
10368       Decls          : constant List_Id := New_List;
10369       Stats          : constant List_Id := New_List;
10370       Body_List      : constant List_Id := New_List;
10371       Trailing_List  : constant List_Id := New_List;
10372
10373       Choices        : List_Id;
10374       Else_Present   : Boolean := False;
10375       Terminate_Alt  : Node_Id := Empty;
10376       Select_Mode    : Node_Id;
10377
10378       Delay_Case     : List_Id;
10379       Delay_Count    : Integer := 0;
10380       Delay_Val      : Entity_Id;
10381       Delay_Index    : Entity_Id;
10382       Delay_Min      : Entity_Id;
10383       Delay_Num      : Int := 1;
10384       Delay_Alt_List : List_Id := New_List;
10385       Delay_List     : constant List_Id := New_List;
10386       D              : Entity_Id;
10387       M              : Entity_Id;
10388
10389       First_Delay    : Boolean := True;
10390       Guard_Open     : Entity_Id;
10391
10392       End_Lab        : Node_Id;
10393       Index          : Int := 1;
10394       Lab            : Node_Id;
10395       Num_Alts       : Int;
10396       Num_Accept     : Nat := 0;
10397       Proc           : Node_Id;
10398       Time_Type      : Entity_Id;
10399       Select_Call    : Node_Id;
10400
10401       Qnam : constant Entity_Id :=
10402                Make_Defining_Identifier (Loc, New_External_Name ('S', 0));
10403
10404       Xnam : constant Entity_Id :=
10405                Make_Defining_Identifier (Loc, New_External_Name ('J', 1));
10406
10407       -----------------------
10408       -- Local subprograms --
10409       -----------------------
10410
10411       function Accept_Or_Raise return List_Id;
10412       --  For the rare case where delay alternatives all have guards, and
10413       --  all of them are closed, it is still possible that there were open
10414       --  accept alternatives with no callers. We must reexamine the
10415       --  Accept_List, and execute a selective wait with no else if some
10416       --  accept is open. If none, we raise program_error.
10417
10418       procedure Add_Accept (Alt : Node_Id);
10419       --  Process a single accept statement in a select alternative. Build
10420       --  procedure for body of accept, and add entry to dispatch table with
10421       --  expression for guard, in preparation for call to run time select.
10422
10423       function Make_And_Declare_Label (Num : Int) return Node_Id;
10424       --  Manufacture a label using Num as a serial number and declare it.
10425       --  The declaration is appended to Decls. The label marks the trailing
10426       --  statements of an accept or delay alternative.
10427
10428       function Make_Select_Call (Select_Mode : Entity_Id) return Node_Id;
10429       --  Build call to Selective_Wait runtime routine
10430
10431       procedure Process_Delay_Alternative (Alt : Node_Id; Index : Int);
10432       --  Add code to compare value of delay with previous values, and
10433       --  generate case entry for trailing statements.
10434
10435       procedure Process_Accept_Alternative
10436         (Alt   : Node_Id;
10437          Index : Int;
10438          Proc  : Node_Id);
10439       --  Add code to call corresponding procedure, and branch to
10440       --  trailing statements, if any.
10441
10442       ---------------------
10443       -- Accept_Or_Raise --
10444       ---------------------
10445
10446       function Accept_Or_Raise return List_Id is
10447          Cond  : Node_Id;
10448          Stats : List_Id;
10449          J     : constant Entity_Id := Make_Temporary (Loc, 'J');
10450
10451       begin
10452          --  We generate the following:
10453
10454          --    for J in q'range loop
10455          --       if q(J).S /=null_task_entry then
10456          --          selective_wait (simple_mode,...);
10457          --          done := True;
10458          --          exit;
10459          --       end if;
10460          --    end loop;
10461          --
10462          --    if no rendez_vous then
10463          --       raise program_error;
10464          --    end if;
10465
10466          --    Note that the code needs to know that the selector name
10467          --    in an Accept_Alternative is named S.
10468
10469          Cond := Make_Op_Ne (Loc,
10470            Left_Opnd =>
10471              Make_Selected_Component (Loc,
10472                Prefix        =>
10473                  Make_Indexed_Component (Loc,
10474                    Prefix => New_Occurrence_Of (Qnam, Loc),
10475                      Expressions => New_List (New_Occurrence_Of (J, Loc))),
10476                Selector_Name => Make_Identifier (Loc, Name_S)),
10477            Right_Opnd =>
10478              New_Occurrence_Of (RTE (RE_Null_Task_Entry), Loc));
10479
10480          Stats := New_List (
10481            Make_Implicit_Loop_Statement (N,
10482              Iteration_Scheme =>
10483                Make_Iteration_Scheme (Loc,
10484                  Loop_Parameter_Specification =>
10485                    Make_Loop_Parameter_Specification (Loc,
10486                      Defining_Identifier         => J,
10487                      Discrete_Subtype_Definition =>
10488                        Make_Attribute_Reference (Loc,
10489                          Prefix         => New_Occurrence_Of (Qnam, Loc),
10490                          Attribute_Name => Name_Range,
10491                          Expressions    => New_List (
10492                            Make_Integer_Literal (Loc, 1))))),
10493
10494              Statements       => New_List (
10495                Make_Implicit_If_Statement (N,
10496                  Condition       =>  Cond,
10497                  Then_Statements => New_List (
10498                    Make_Select_Call (
10499                      New_Occurrence_Of (RTE (RE_Simple_Mode), Loc)),
10500                    Make_Exit_Statement (Loc))))));
10501
10502          Append_To (Stats,
10503            Make_Raise_Program_Error (Loc,
10504              Condition => Make_Op_Eq (Loc,
10505                Left_Opnd  => New_Occurrence_Of (Xnam, Loc),
10506                Right_Opnd =>
10507                  New_Occurrence_Of (RTE (RE_No_Rendezvous), Loc)),
10508              Reason => PE_All_Guards_Closed));
10509
10510          return Stats;
10511       end Accept_Or_Raise;
10512
10513       ----------------
10514       -- Add_Accept --
10515       ----------------
10516
10517       procedure Add_Accept (Alt : Node_Id) is
10518          Acc_Stm   : constant Node_Id    := Accept_Statement (Alt);
10519          Ename     : constant Node_Id    := Entry_Direct_Name (Acc_Stm);
10520          Eloc      : constant Source_Ptr := Sloc (Ename);
10521          Eent      : constant Entity_Id  := Entity (Ename);
10522          Index     : constant Node_Id    := Entry_Index (Acc_Stm);
10523          Null_Body : Node_Id;
10524          Proc_Body : Node_Id;
10525          PB_Ent    : Entity_Id;
10526          Expr      : Node_Id;
10527          Call      : Node_Id;
10528
10529       begin
10530          if No (Ann) then
10531             Ann := Node (Last_Elmt (Accept_Address (Eent)));
10532          end if;
10533
10534          if Present (Condition (Alt)) then
10535             Expr :=
10536               Make_If_Expression (Eloc, New_List (
10537                 Condition (Alt),
10538                 Entry_Index_Expression (Eloc, Eent, Index, Scope (Eent)),
10539                 New_Occurrence_Of (RTE (RE_Null_Task_Entry), Eloc)));
10540          else
10541             Expr :=
10542               Entry_Index_Expression
10543                 (Eloc, Eent, Index, Scope (Eent));
10544          end if;
10545
10546          if Present (Handled_Statement_Sequence (Accept_Statement (Alt))) then
10547             Null_Body := New_Occurrence_Of (Standard_False, Eloc);
10548
10549             --  Always add call to Abort_Undefer when generating code, since
10550             --  this is what the runtime expects (abort deferred in
10551             --  Selective_Wait). In CodePeer mode this only confuses the
10552             --  analysis with unknown calls, so don't do it.
10553
10554             if not CodePeer_Mode then
10555                Call :=
10556                  Make_Procedure_Call_Statement (Eloc,
10557                    Name => New_Occurrence_Of (RTE (RE_Abort_Undefer), Eloc));
10558                Insert_Before
10559                  (First (Statements (Handled_Statement_Sequence
10560                                        (Accept_Statement (Alt)))),
10561                   Call);
10562                Analyze (Call);
10563             end if;
10564
10565             PB_Ent :=
10566               Make_Defining_Identifier (Eloc,
10567                 New_External_Name (Chars (Ename), 'A', Num_Accept));
10568
10569             if Comes_From_Source (Alt) then
10570                Set_Debug_Info_Needed (PB_Ent);
10571             end if;
10572
10573             Proc_Body :=
10574               Make_Subprogram_Body (Eloc,
10575                 Specification              =>
10576                   Make_Procedure_Specification (Eloc,
10577                     Defining_Unit_Name => PB_Ent),
10578                 Declarations               => Declarations (Acc_Stm),
10579                 Handled_Statement_Sequence =>
10580                   Build_Accept_Body (Accept_Statement (Alt)));
10581
10582             --  During the analysis of the body of the accept statement, any
10583             --  zero cost exception handler records were collected in the
10584             --  Accept_Handler_Records field of the N_Accept_Alternative node.
10585             --  This is where we move them to where they belong, namely the
10586             --  newly created procedure.
10587
10588             Set_Handler_Records (PB_Ent, Accept_Handler_Records (Alt));
10589             Append (Proc_Body, Body_List);
10590
10591          else
10592             Null_Body := New_Occurrence_Of (Standard_True,  Eloc);
10593
10594             --  if accept statement has declarations, insert above, given that
10595             --  we are not creating a body for the accept.
10596
10597             if Present (Declarations (Acc_Stm)) then
10598                Insert_Actions (N, Declarations (Acc_Stm));
10599             end if;
10600          end if;
10601
10602          Append_To (Accept_List,
10603            Make_Aggregate (Eloc, Expressions => New_List (Null_Body, Expr)));
10604
10605          Num_Accept := Num_Accept + 1;
10606       end Add_Accept;
10607
10608       ----------------------------
10609       -- Make_And_Declare_Label --
10610       ----------------------------
10611
10612       function Make_And_Declare_Label (Num : Int) return Node_Id is
10613          Lab_Id : Node_Id;
10614
10615       begin
10616          Lab_Id := Make_Identifier (Loc, New_External_Name ('L', Num));
10617          Lab :=
10618            Make_Label (Loc, Lab_Id);
10619
10620          Append_To (Decls,
10621            Make_Implicit_Label_Declaration (Loc,
10622              Defining_Identifier  =>
10623                Make_Defining_Identifier (Loc, Chars (Lab_Id)),
10624              Label_Construct      => Lab));
10625
10626          return Lab;
10627       end Make_And_Declare_Label;
10628
10629       ----------------------
10630       -- Make_Select_Call --
10631       ----------------------
10632
10633       function Make_Select_Call (Select_Mode : Entity_Id) return Node_Id is
10634          Params : constant List_Id := New_List;
10635
10636       begin
10637          Append_To (Params,
10638            Make_Attribute_Reference (Loc,
10639              Prefix         => New_Occurrence_Of (Qnam, Loc),
10640              Attribute_Name => Name_Unchecked_Access));
10641          Append_To (Params, Select_Mode);
10642          Append_To (Params, New_Occurrence_Of (Ann, Loc));
10643          Append_To (Params, New_Occurrence_Of (Xnam, Loc));
10644
10645          return
10646            Make_Procedure_Call_Statement (Loc,
10647              Name => New_Occurrence_Of (RTE (RE_Selective_Wait), Loc),
10648              Parameter_Associations => Params);
10649       end Make_Select_Call;
10650
10651       --------------------------------
10652       -- Process_Accept_Alternative --
10653       --------------------------------
10654
10655       procedure Process_Accept_Alternative
10656         (Alt   : Node_Id;
10657          Index : Int;
10658          Proc  : Node_Id)
10659       is
10660          Astmt     : constant Node_Id := Accept_Statement (Alt);
10661          Alt_Stats : List_Id;
10662
10663       begin
10664          Adjust_Condition (Condition (Alt));
10665
10666          --  Accept with body
10667
10668          if Present (Handled_Statement_Sequence (Astmt)) then
10669             Alt_Stats :=
10670               New_List (
10671                 Make_Procedure_Call_Statement (Sloc (Proc),
10672                   Name =>
10673                     New_Occurrence_Of
10674                       (Defining_Unit_Name (Specification (Proc)),
10675                        Sloc (Proc))));
10676
10677          --  Accept with no body (followed by trailing statements)
10678
10679          else
10680             Alt_Stats := Empty_List;
10681          end if;
10682
10683          Ensure_Statement_Present (Sloc (Astmt), Alt);
10684
10685          --  After the call, if any, branch to trailing statements, if any.
10686          --  We create a label for each, as well as the corresponding label
10687          --  declaration.
10688
10689          if not Is_Empty_List (Statements (Alt)) then
10690             Lab := Make_And_Declare_Label (Index);
10691             Append (Lab, Trailing_List);
10692             Append_List (Statements (Alt), Trailing_List);
10693             Append_To (Trailing_List,
10694               Make_Goto_Statement (Loc,
10695                 Name => New_Copy (Identifier (End_Lab))));
10696
10697          else
10698             Lab := End_Lab;
10699          end if;
10700
10701          Append_To (Alt_Stats,
10702            Make_Goto_Statement (Loc, Name => New_Copy (Identifier (Lab))));
10703
10704          Append_To (Alt_List,
10705            Make_Case_Statement_Alternative (Loc,
10706              Discrete_Choices => New_List (Make_Integer_Literal (Loc, Index)),
10707              Statements       => Alt_Stats));
10708       end Process_Accept_Alternative;
10709
10710       -------------------------------
10711       -- Process_Delay_Alternative --
10712       -------------------------------
10713
10714       procedure Process_Delay_Alternative (Alt : Node_Id; Index : Int) is
10715          Dloc      : constant Source_Ptr := Sloc (Delay_Statement (Alt));
10716          Cond      : Node_Id;
10717          Delay_Alt : List_Id;
10718
10719       begin
10720          --  Deal with C/Fortran boolean as delay condition
10721
10722          Adjust_Condition (Condition (Alt));
10723
10724          --  Determine the smallest specified delay
10725
10726          --  for each delay alternative generate:
10727
10728          --    if guard-expression then
10729          --       Delay_Val  := delay-expression;
10730          --       Guard_Open := True;
10731          --       if Delay_Val < Delay_Min then
10732          --          Delay_Min   := Delay_Val;
10733          --          Delay_Index := Index;
10734          --       end if;
10735          --    end if;
10736
10737          --  The enclosing if-statement is omitted if there is no guard
10738
10739          if Delay_Count = 1 or else First_Delay then
10740             First_Delay := False;
10741
10742             Delay_Alt := New_List (
10743               Make_Assignment_Statement (Loc,
10744                 Name       => New_Occurrence_Of (Delay_Min, Loc),
10745                 Expression => Expression (Delay_Statement (Alt))));
10746
10747             if Delay_Count > 1 then
10748                Append_To (Delay_Alt,
10749                  Make_Assignment_Statement (Loc,
10750                    Name       => New_Occurrence_Of (Delay_Index, Loc),
10751                    Expression => Make_Integer_Literal (Loc, Index)));
10752             end if;
10753
10754          else
10755             Delay_Alt := New_List (
10756               Make_Assignment_Statement (Loc,
10757                 Name       => New_Occurrence_Of (Delay_Val, Loc),
10758                 Expression => Expression (Delay_Statement (Alt))));
10759
10760             if Time_Type = Standard_Duration then
10761                Cond :=
10762                   Make_Op_Lt (Loc,
10763                     Left_Opnd  => New_Occurrence_Of (Delay_Val, Loc),
10764                     Right_Opnd => New_Occurrence_Of (Delay_Min, Loc));
10765
10766             else
10767                --  The scope of the time type must define a comparison
10768                --  operator. The scope itself may not be visible, so we
10769                --  construct a node with entity information to insure that
10770                --  semantic analysis can find the proper operator.
10771
10772                Cond :=
10773                  Make_Function_Call (Loc,
10774                    Name => Make_Selected_Component (Loc,
10775                      Prefix        =>
10776                        New_Occurrence_Of (Scope (Time_Type), Loc),
10777                      Selector_Name =>
10778                        Make_Operator_Symbol (Loc,
10779                          Chars  => Name_Op_Lt,
10780                          Strval => No_String)),
10781                     Parameter_Associations =>
10782                       New_List (
10783                         New_Occurrence_Of (Delay_Val, Loc),
10784                         New_Occurrence_Of (Delay_Min, Loc)));
10785
10786                Set_Entity (Prefix (Name (Cond)), Scope (Time_Type));
10787             end if;
10788
10789             Append_To (Delay_Alt,
10790               Make_Implicit_If_Statement (N,
10791                 Condition => Cond,
10792                 Then_Statements => New_List (
10793                   Make_Assignment_Statement (Loc,
10794                     Name       => New_Occurrence_Of (Delay_Min, Loc),
10795                     Expression => New_Occurrence_Of (Delay_Val, Loc)),
10796
10797                   Make_Assignment_Statement (Loc,
10798                     Name       => New_Occurrence_Of (Delay_Index, Loc),
10799                     Expression => Make_Integer_Literal (Loc, Index)))));
10800          end if;
10801
10802          if Check_Guard then
10803             Append_To (Delay_Alt,
10804               Make_Assignment_Statement (Loc,
10805                 Name       => New_Occurrence_Of (Guard_Open, Loc),
10806                 Expression => New_Occurrence_Of (Standard_True, Loc)));
10807          end if;
10808
10809          if Present (Condition (Alt)) then
10810             Delay_Alt := New_List (
10811               Make_Implicit_If_Statement (N,
10812                 Condition       => Condition (Alt),
10813                 Then_Statements => Delay_Alt));
10814          end if;
10815
10816          Append_List (Delay_Alt, Delay_List);
10817
10818          Ensure_Statement_Present (Dloc, Alt);
10819
10820          --  If the delay alternative has a statement part, add choice to the
10821          --  case statements for delays.
10822
10823          if not Is_Empty_List (Statements (Alt)) then
10824
10825             if Delay_Count = 1 then
10826                Append_List (Statements (Alt), Delay_Alt_List);
10827
10828             else
10829                Append_To (Delay_Alt_List,
10830                  Make_Case_Statement_Alternative (Loc,
10831                    Discrete_Choices => New_List (
10832                                          Make_Integer_Literal (Loc, Index)),
10833                    Statements       => Statements (Alt)));
10834             end if;
10835
10836          elsif Delay_Count = 1 then
10837
10838             --  If the single delay has no trailing statements, add a branch
10839             --  to the exit label to the selective wait.
10840
10841             Delay_Alt_List := New_List (
10842               Make_Goto_Statement (Loc,
10843                 Name => New_Copy (Identifier (End_Lab))));
10844
10845          end if;
10846       end Process_Delay_Alternative;
10847
10848    --  Start of processing for Expand_N_Selective_Accept
10849
10850    begin
10851       Process_Statements_For_Controlled_Objects (N);
10852
10853       --  First insert some declarations before the select. The first is:
10854
10855       --    Ann : Address
10856
10857       --  This variable holds the parameters passed to the accept body. This
10858       --  declaration has already been inserted by the time we get here by
10859       --  a call to Expand_Accept_Declarations made from the semantics when
10860       --  processing the first accept statement contained in the select. We
10861       --  can find this entity as Accept_Address (E), where E is any of the
10862       --  entries references by contained accept statements.
10863
10864       --  The first step is to scan the list of Selective_Accept_Statements
10865       --  to find this entity, and also count the number of accepts, and
10866       --  determine if terminated, delay or else is present:
10867
10868       Num_Alts := 0;
10869
10870       Alt := First (Alts);
10871       while Present (Alt) loop
10872          Process_Statements_For_Controlled_Objects (Alt);
10873
10874          if Nkind (Alt) = N_Accept_Alternative then
10875             Add_Accept (Alt);
10876
10877          elsif Nkind (Alt) = N_Delay_Alternative then
10878             Delay_Count := Delay_Count + 1;
10879
10880             --  If the delays are relative delays, the delay expressions have
10881             --  type Standard_Duration. Otherwise they must have some time type
10882             --  recognized by GNAT.
10883
10884             if Nkind (Delay_Statement (Alt)) = N_Delay_Relative_Statement then
10885                Time_Type := Standard_Duration;
10886             else
10887                Time_Type := Etype (Expression (Delay_Statement (Alt)));
10888
10889                if Is_RTE (Base_Type (Etype (Time_Type)), RO_CA_Time)
10890                  or else Is_RTE (Base_Type (Etype (Time_Type)), RO_RT_Time)
10891                then
10892                   null;
10893                else
10894                   Error_Msg_NE (
10895                     "& is not a time type (RM 9.6(6))",
10896                        Expression (Delay_Statement (Alt)), Time_Type);
10897                   Time_Type := Standard_Duration;
10898                   Set_Etype (Expression (Delay_Statement (Alt)), Any_Type);
10899                end if;
10900             end if;
10901
10902             if No (Condition (Alt)) then
10903
10904                --  This guard will always be open
10905
10906                Check_Guard := False;
10907             end if;
10908
10909          elsif Nkind (Alt) = N_Terminate_Alternative then
10910             Adjust_Condition (Condition (Alt));
10911             Terminate_Alt := Alt;
10912          end if;
10913
10914          Num_Alts := Num_Alts + 1;
10915          Next (Alt);
10916       end loop;
10917
10918       Else_Present := Present (Else_Statements (N));
10919
10920       --  At the same time (see procedure Add_Accept) we build the accept list:
10921
10922       --    Qnn : Accept_List (1 .. num-select) := (
10923       --          (null-body, entry-index),
10924       --          (null-body, entry-index),
10925       --          ..
10926       --          (null_body, entry-index));
10927
10928       --  In the above declaration, null-body is True if the corresponding
10929       --  accept has no body, and false otherwise. The entry is either the
10930       --  entry index expression if there is no guard, or if a guard is
10931       --  present, then an if expression of the form:
10932
10933       --    (if guard then entry-index else Null_Task_Entry)
10934
10935       --  If a guard is statically known to be false, the entry can simply
10936       --  be omitted from the accept list.
10937
10938       Append_To (Decls,
10939         Make_Object_Declaration (Loc,
10940           Defining_Identifier => Qnam,
10941           Object_Definition   => New_Occurrence_Of (RTE (RE_Accept_List), Loc),
10942           Aliased_Present     => True,
10943           Expression          =>
10944              Make_Qualified_Expression (Loc,
10945                Subtype_Mark =>
10946                  New_Occurrence_Of (RTE (RE_Accept_List), Loc),
10947                Expression   =>
10948                  Make_Aggregate (Loc, Expressions => Accept_List))));
10949
10950       --  Then we declare the variable that holds the index for the accept
10951       --  that will be selected for service:
10952
10953       --    Xnn : Select_Index;
10954
10955       Append_To (Decls,
10956         Make_Object_Declaration (Loc,
10957           Defining_Identifier => Xnam,
10958           Object_Definition =>
10959             New_Occurrence_Of (RTE (RE_Select_Index), Loc),
10960           Expression =>
10961             New_Occurrence_Of (RTE (RE_No_Rendezvous), Loc)));
10962
10963       --  After this follow procedure declarations for each accept body
10964
10965       --    procedure Pnn is
10966       --    begin
10967       --       ...
10968       --    end;
10969
10970       --  where the ... are statements from the corresponding procedure body.
10971       --  No parameters are involved, since the parameters are passed via Ann
10972       --  and the parameter references have already been expanded to be direct
10973       --  references to Ann (see Exp_Ch2.Expand_Entry_Parameter). Furthermore,
10974       --  any embedded tasking statements (which would normally be illegal in
10975       --  procedures), have been converted to calls to the tasking runtime so
10976       --  there is no problem in putting them into procedures.
10977
10978       --  The original accept statement has been expanded into a block in
10979       --  the same fashion as for simple accepts (see Build_Accept_Body).
10980
10981       --  Note: we don't really need to build these procedures for the case
10982       --  where no delay statement is present, but it is just as easy to
10983       --  build them unconditionally, and not significantly inefficient,
10984       --  since if they are short they will be inlined anyway.
10985
10986       --  The procedure declarations have been assembled in Body_List
10987
10988       --  If delays are present, we must compute the required delay.
10989       --  We first generate the declarations:
10990
10991       --    Delay_Index : Boolean := 0;
10992       --    Delay_Min   : Some_Time_Type.Time;
10993       --    Delay_Val   : Some_Time_Type.Time;
10994
10995       --  Delay_Index will be set to the index of the minimum delay, i.e. the
10996       --  active delay that is actually chosen as the basis for the possible
10997       --  delay if an immediate rendez-vous is not possible.
10998
10999       --  In the most common case there is a single delay statement, and this
11000       --  is handled specially.
11001
11002       if Delay_Count > 0 then
11003
11004          --  Generate the required declarations
11005
11006          Delay_Val :=
11007            Make_Defining_Identifier (Loc, New_External_Name ('D', 1));
11008          Delay_Index :=
11009            Make_Defining_Identifier (Loc, New_External_Name ('D', 2));
11010          Delay_Min :=
11011            Make_Defining_Identifier (Loc, New_External_Name ('D', 3));
11012
11013          Append_To (Decls,
11014            Make_Object_Declaration (Loc,
11015              Defining_Identifier => Delay_Val,
11016              Object_Definition   => New_Occurrence_Of (Time_Type, Loc)));
11017
11018          Append_To (Decls,
11019            Make_Object_Declaration (Loc,
11020              Defining_Identifier => Delay_Index,
11021              Object_Definition   => New_Occurrence_Of (Standard_Integer, Loc),
11022              Expression          => Make_Integer_Literal (Loc, 0)));
11023
11024          Append_To (Decls,
11025            Make_Object_Declaration (Loc,
11026              Defining_Identifier => Delay_Min,
11027              Object_Definition   => New_Occurrence_Of (Time_Type, Loc),
11028              Expression          =>
11029                Unchecked_Convert_To (Time_Type,
11030                  Make_Attribute_Reference (Loc,
11031                    Prefix =>
11032                      New_Occurrence_Of (Underlying_Type (Time_Type), Loc),
11033                    Attribute_Name => Name_Last))));
11034
11035          --  Create Duration and Delay_Mode objects used for passing a delay
11036          --  value to RTS
11037
11038          D := Make_Temporary (Loc, 'D');
11039          M := Make_Temporary (Loc, 'M');
11040
11041          declare
11042             Discr : Entity_Id;
11043
11044          begin
11045             --  Note that these values are defined in s-osprim.ads and must
11046             --  be kept in sync:
11047             --
11048             --     Relative          : constant := 0;
11049             --     Absolute_Calendar : constant := 1;
11050             --     Absolute_RT       : constant := 2;
11051
11052             if Time_Type = Standard_Duration then
11053                Discr := Make_Integer_Literal (Loc, 0);
11054
11055             elsif Is_RTE (Base_Type (Etype (Time_Type)), RO_CA_Time) then
11056                Discr := Make_Integer_Literal (Loc, 1);
11057
11058             else
11059                pragma Assert
11060                  (Is_RTE (Base_Type (Etype (Time_Type)), RO_RT_Time));
11061                Discr := Make_Integer_Literal (Loc, 2);
11062             end if;
11063
11064             Append_To (Decls,
11065               Make_Object_Declaration (Loc,
11066                 Defining_Identifier => D,
11067                 Object_Definition   =>
11068                   New_Occurrence_Of (Standard_Duration, Loc)));
11069
11070             Append_To (Decls,
11071               Make_Object_Declaration (Loc,
11072                 Defining_Identifier => M,
11073                 Object_Definition   =>
11074                   New_Occurrence_Of (Standard_Integer, Loc),
11075                 Expression          => Discr));
11076          end;
11077
11078          if Check_Guard then
11079             Guard_Open :=
11080               Make_Defining_Identifier (Loc, New_External_Name ('G', 1));
11081
11082             Append_To (Decls,
11083               Make_Object_Declaration (Loc,
11084                  Defining_Identifier => Guard_Open,
11085                  Object_Definition   =>
11086                    New_Occurrence_Of (Standard_Boolean, Loc),
11087                  Expression          =>
11088                    New_Occurrence_Of (Standard_False, Loc)));
11089          end if;
11090
11091       --  Delay_Count is zero, don't need M and D set (suppress warning)
11092
11093       else
11094          M := Empty;
11095          D := Empty;
11096       end if;
11097
11098       if Present (Terminate_Alt) then
11099
11100          --  If the terminate alternative guard is False, use
11101          --  Simple_Mode; otherwise use Terminate_Mode.
11102
11103          if Present (Condition (Terminate_Alt)) then
11104             Select_Mode := Make_If_Expression (Loc,
11105               New_List (Condition (Terminate_Alt),
11106                         New_Occurrence_Of (RTE (RE_Terminate_Mode), Loc),
11107                         New_Occurrence_Of (RTE (RE_Simple_Mode), Loc)));
11108          else
11109             Select_Mode := New_Occurrence_Of (RTE (RE_Terminate_Mode), Loc);
11110          end if;
11111
11112       elsif Else_Present or Delay_Count > 0 then
11113          Select_Mode := New_Occurrence_Of (RTE (RE_Else_Mode), Loc);
11114
11115       else
11116          Select_Mode := New_Occurrence_Of (RTE (RE_Simple_Mode), Loc);
11117       end if;
11118
11119       Select_Call := Make_Select_Call (Select_Mode);
11120       Append (Select_Call, Stats);
11121
11122       --  Now generate code to act on the result. There is an entry
11123       --  in this case for each accept statement with a non-null body,
11124       --  followed by a branch to the statements that follow the Accept.
11125       --  In the absence of delay alternatives, we generate:
11126
11127       --    case X is
11128       --      when No_Rendezvous =>  --  omitted if simple mode
11129       --         goto Lab0;
11130
11131       --      when 1 =>
11132       --         P1n;
11133       --         goto Lab1;
11134
11135       --      when 2 =>
11136       --         P2n;
11137       --         goto Lab2;
11138
11139       --      when others =>
11140       --         goto Exit;
11141       --    end case;
11142       --
11143       --    Lab0: Else_Statements;
11144       --    goto exit;
11145
11146       --    Lab1:  Trailing_Statements1;
11147       --    goto Exit;
11148       --
11149       --    Lab2:  Trailing_Statements2;
11150       --    goto Exit;
11151       --    ...
11152       --    Exit:
11153
11154       --  Generate label for common exit
11155
11156       End_Lab := Make_And_Declare_Label (Num_Alts + 1);
11157
11158       --  First entry is the default case, when no rendezvous is possible
11159
11160       Choices := New_List (New_Occurrence_Of (RTE (RE_No_Rendezvous), Loc));
11161
11162       if Else_Present then
11163
11164          --  If no rendezvous is possible, the else part is executed
11165
11166          Lab := Make_And_Declare_Label (0);
11167          Alt_Stats := New_List (
11168            Make_Goto_Statement (Loc,
11169              Name => New_Copy (Identifier (Lab))));
11170
11171          Append (Lab, Trailing_List);
11172          Append_List (Else_Statements (N), Trailing_List);
11173          Append_To (Trailing_List,
11174            Make_Goto_Statement (Loc,
11175              Name => New_Copy (Identifier (End_Lab))));
11176       else
11177          Alt_Stats := New_List (
11178            Make_Goto_Statement (Loc,
11179              Name => New_Copy (Identifier (End_Lab))));
11180       end if;
11181
11182       Append_To (Alt_List,
11183         Make_Case_Statement_Alternative (Loc,
11184           Discrete_Choices => Choices,
11185           Statements       => Alt_Stats));
11186
11187       --  We make use of the fact that Accept_Index is an integer type, and
11188       --  generate successive literals for entries for each accept. Only those
11189       --  for which there is a body or trailing statements get a case entry.
11190
11191       Alt := First (Select_Alternatives (N));
11192       Proc := First (Body_List);
11193       while Present (Alt) loop
11194
11195          if Nkind (Alt) = N_Accept_Alternative then
11196             Process_Accept_Alternative (Alt, Index, Proc);
11197             Index := Index + 1;
11198
11199             if Present
11200               (Handled_Statement_Sequence (Accept_Statement (Alt)))
11201             then
11202                Next (Proc);
11203             end if;
11204
11205          elsif Nkind (Alt) = N_Delay_Alternative then
11206             Process_Delay_Alternative (Alt, Delay_Num);
11207             Delay_Num := Delay_Num + 1;
11208          end if;
11209
11210          Next (Alt);
11211       end loop;
11212
11213       --  An others choice is always added to the main case, as well
11214       --  as the delay case (to satisfy the compiler).
11215
11216       Append_To (Alt_List,
11217         Make_Case_Statement_Alternative (Loc,
11218           Discrete_Choices =>
11219             New_List (Make_Others_Choice (Loc)),
11220           Statements       =>
11221             New_List (Make_Goto_Statement (Loc,
11222               Name => New_Copy (Identifier (End_Lab))))));
11223
11224       Accept_Case := New_List (
11225         Make_Case_Statement (Loc,
11226           Expression   => New_Occurrence_Of (Xnam, Loc),
11227           Alternatives => Alt_List));
11228
11229       Append_List (Trailing_List, Accept_Case);
11230       Append_List (Body_List, Decls);
11231
11232       --  Construct case statement for trailing statements of delay
11233       --  alternatives, if there are several of them.
11234
11235       if Delay_Count > 1 then
11236          Append_To (Delay_Alt_List,
11237            Make_Case_Statement_Alternative (Loc,
11238              Discrete_Choices =>
11239                New_List (Make_Others_Choice (Loc)),
11240              Statements       =>
11241                New_List (Make_Null_Statement (Loc))));
11242
11243          Delay_Case := New_List (
11244            Make_Case_Statement (Loc,
11245              Expression   => New_Occurrence_Of (Delay_Index, Loc),
11246              Alternatives => Delay_Alt_List));
11247       else
11248          Delay_Case := Delay_Alt_List;
11249       end if;
11250
11251       --  If there are no delay alternatives, we append the case statement
11252       --  to the statement list.
11253
11254       if Delay_Count = 0 then
11255          Append_List (Accept_Case, Stats);
11256
11257       --  Delay alternatives present
11258
11259       else
11260          --  If delay alternatives are present we generate:
11261
11262          --    find minimum delay.
11263          --    DX := minimum delay;
11264          --    M := <delay mode>;
11265          --    Timed_Selective_Wait (Q'Unchecked_Access, Delay_Mode, P,
11266          --      DX, MX, X);
11267          --
11268          --    if X = No_Rendezvous then
11269          --      case statement for delay statements.
11270          --    else
11271          --      case statement for accept alternatives.
11272          --    end if;
11273
11274          declare
11275             Cases : Node_Id;
11276             Stmt  : Node_Id;
11277             Parms : List_Id;
11278             Parm  : Node_Id;
11279             Conv  : Node_Id;
11280
11281          begin
11282             --  The type of the delay expression is known to be legal
11283
11284             if Time_Type = Standard_Duration then
11285                Conv := New_Occurrence_Of (Delay_Min, Loc);
11286
11287             elsif Is_RTE (Base_Type (Etype (Time_Type)), RO_CA_Time) then
11288                Conv := Make_Function_Call (Loc,
11289                  New_Occurrence_Of (RTE (RO_CA_To_Duration), Loc),
11290                  New_List (New_Occurrence_Of (Delay_Min, Loc)));
11291
11292             else
11293                pragma Assert
11294                  (Is_RTE (Base_Type (Etype (Time_Type)), RO_RT_Time));
11295
11296                Conv := Make_Function_Call (Loc,
11297                  New_Occurrence_Of (RTE (RO_RT_To_Duration), Loc),
11298                  New_List (New_Occurrence_Of (Delay_Min, Loc)));
11299             end if;
11300
11301             Stmt := Make_Assignment_Statement (Loc,
11302               Name       => New_Occurrence_Of (D, Loc),
11303               Expression => Conv);
11304
11305             --  Change the value for Accept_Modes. (Else_Mode -> Delay_Mode)
11306
11307             Parms := Parameter_Associations (Select_Call);
11308
11309             Parm := First (Parms);
11310             while Present (Parm) and then Parm /= Select_Mode loop
11311                Next (Parm);
11312             end loop;
11313
11314             pragma Assert (Present (Parm));
11315             Rewrite (Parm, New_Occurrence_Of (RTE (RE_Delay_Mode), Loc));
11316             Analyze (Parm);
11317
11318             --  Prepare two new parameters of Duration and Delay_Mode type
11319             --  which represent the value and the mode of the minimum delay.
11320
11321             Next (Parm);
11322             Insert_After (Parm, New_Occurrence_Of (M, Loc));
11323             Insert_After (Parm, New_Occurrence_Of (D, Loc));
11324
11325             --  Create a call to RTS
11326
11327             Rewrite (Select_Call,
11328               Make_Procedure_Call_Statement (Loc,
11329                 Name => New_Occurrence_Of (RTE (RE_Timed_Selective_Wait), Loc),
11330                 Parameter_Associations => Parms));
11331
11332             --  This new call should follow the calculation of the minimum
11333             --  delay.
11334
11335             Insert_List_Before (Select_Call, Delay_List);
11336
11337             if Check_Guard then
11338                Stmt :=
11339                  Make_Implicit_If_Statement (N,
11340                    Condition       => New_Occurrence_Of (Guard_Open, Loc),
11341                    Then_Statements => New_List (
11342                      New_Copy_Tree (Stmt),
11343                      New_Copy_Tree (Select_Call)),
11344                    Else_Statements => Accept_Or_Raise);
11345                Rewrite (Select_Call, Stmt);
11346             else
11347                Insert_Before (Select_Call, Stmt);
11348             end if;
11349
11350             Cases :=
11351               Make_Implicit_If_Statement (N,
11352                 Condition => Make_Op_Eq (Loc,
11353                   Left_Opnd  => New_Occurrence_Of (Xnam, Loc),
11354                   Right_Opnd =>
11355                     New_Occurrence_Of (RTE (RE_No_Rendezvous), Loc)),
11356
11357                 Then_Statements => Delay_Case,
11358                 Else_Statements => Accept_Case);
11359
11360             Append (Cases, Stats);
11361          end;
11362       end if;
11363
11364       Append (End_Lab, Stats);
11365
11366       --  Replace accept statement with appropriate block
11367
11368       Rewrite (N,
11369         Make_Block_Statement (Loc,
11370           Declarations               => Decls,
11371           Handled_Statement_Sequence =>
11372             Make_Handled_Sequence_Of_Statements (Loc, Statements => Stats)));
11373       Analyze (N);
11374
11375       --  Note: have to worry more about abort deferral in above code ???
11376
11377       --  Final step is to unstack the Accept_Address entries for all accept
11378       --  statements appearing in accept alternatives in the select statement
11379
11380       Alt := First (Alts);
11381       while Present (Alt) loop
11382          if Nkind (Alt) = N_Accept_Alternative then
11383             Remove_Last_Elmt (Accept_Address
11384               (Entity (Entry_Direct_Name (Accept_Statement (Alt)))));
11385          end if;
11386
11387          Next (Alt);
11388       end loop;
11389    end Expand_N_Selective_Accept;
11390
11391    --------------------------------------
11392    -- Expand_N_Single_Task_Declaration --
11393    --------------------------------------
11394
11395    --  Single task declarations should never be present after semantic
11396    --  analysis, since we expect them to be replaced by a declaration of an
11397    --  anonymous task type, followed by a declaration of the task object. We
11398    --  include this routine to make sure that is happening.
11399
11400    procedure Expand_N_Single_Task_Declaration (N : Node_Id) is
11401    begin
11402       raise Program_Error;
11403    end Expand_N_Single_Task_Declaration;
11404
11405    ------------------------
11406    -- Expand_N_Task_Body --
11407    ------------------------
11408
11409    --  Given a task body
11410
11411    --    task body tname is
11412    --       <declarations>
11413    --    begin
11414    --       <statements>
11415    --    end x;
11416
11417    --  This expansion routine converts it into a procedure and sets the
11418    --  elaboration flag for the procedure to true, to represent the fact
11419    --  that the task body is now elaborated:
11420
11421    --    procedure tnameB (_Task : access tnameV) is
11422    --       discriminal : dtype renames _Task.discriminant;
11423
11424    --       procedure _clean is
11425    --       begin
11426    --          Abort_Defer.all;
11427    --          Complete_Task;
11428    --          Abort_Undefer.all;
11429    --          return;
11430    --       end _clean;
11431
11432    --    begin
11433    --       Abort_Undefer.all;
11434    --       <declarations>
11435    --       System.Task_Stages.Complete_Activation;
11436    --       <statements>
11437    --    at end
11438    --       _clean;
11439    --    end tnameB;
11440
11441    --    tnameE := True;
11442
11443    --  In addition, if the task body is an activator, then a call to activate
11444    --  tasks is added at the start of the statements, before the call to
11445    --  Complete_Activation, and if in addition the task is a master then it
11446    --  must be established as a master. These calls are inserted and analyzed
11447    --  in Expand_Cleanup_Actions, when the Handled_Sequence_Of_Statements is
11448    --  expanded.
11449
11450    --  There is one discriminal declaration line generated for each
11451    --  discriminant that is present to provide an easy reference point for
11452    --  discriminant references inside the body (see Exp_Ch2.Expand_Name).
11453
11454    --  Note on relationship to GNARLI definition. In the GNARLI definition,
11455    --  task body procedures have a profile (Arg : System.Address). That is
11456    --  needed because GNARLI has to use the same access-to-subprogram type
11457    --  for all task types. We depend here on knowing that in GNAT, passing
11458    --  an address argument by value is identical to passing a record value
11459    --  by access (in either case a single pointer is passed), so even though
11460    --  this procedure has the wrong profile. In fact it's all OK, since the
11461    --  callings sequence is identical.
11462
11463    procedure Expand_N_Task_Body (N : Node_Id) is
11464       Loc   : constant Source_Ptr := Sloc (N);
11465       Ttyp  : constant Entity_Id  := Corresponding_Spec (N);
11466       Call  : Node_Id;
11467       New_N : Node_Id;
11468
11469       Insert_Nod : Node_Id;
11470       --  Used to determine the proper location of wrapper body insertions
11471
11472    begin
11473       --  if no task body procedure, means we had an error in configurable
11474       --  run-time mode, and there is no point in proceeding further.
11475
11476       if No (Task_Body_Procedure (Ttyp)) then
11477          return;
11478       end if;
11479
11480       --  Add renaming declarations for discriminals and a declaration for the
11481       --  entry family index (if applicable).
11482
11483       Install_Private_Data_Declarations
11484         (Loc, Task_Body_Procedure (Ttyp), Ttyp, N, Declarations (N));
11485
11486       --  Add a call to Abort_Undefer at the very beginning of the task
11487       --  body since this body is called with abort still deferred.
11488
11489       if Abort_Allowed then
11490          Call := Build_Runtime_Call (Loc, RE_Abort_Undefer);
11491          Insert_Before
11492            (First (Statements (Handled_Statement_Sequence (N))), Call);
11493          Analyze (Call);
11494       end if;
11495
11496       --  The statement part has already been protected with an at_end and
11497       --  cleanup actions. The call to Complete_Activation must be placed
11498       --  at the head of the sequence of statements of that block. The
11499       --  declarations have been merged in this sequence of statements but
11500       --  the first real statement is accessible from the First_Real_Statement
11501       --  field (which was set for exactly this purpose).
11502
11503       if Restricted_Profile then
11504          Call := Build_Runtime_Call (Loc, RE_Complete_Restricted_Activation);
11505       else
11506          Call := Build_Runtime_Call (Loc, RE_Complete_Activation);
11507       end if;
11508
11509       Insert_Before
11510         (First_Real_Statement (Handled_Statement_Sequence (N)), Call);
11511       Analyze (Call);
11512
11513       New_N :=
11514         Make_Subprogram_Body (Loc,
11515           Specification              => Build_Task_Proc_Specification (Ttyp),
11516           Declarations               => Declarations (N),
11517           Handled_Statement_Sequence => Handled_Statement_Sequence (N));
11518       Set_Is_Task_Body_Procedure (New_N);
11519
11520       --  If the task contains generic instantiations, cleanup actions are
11521       --  delayed until after instantiation. Transfer the activation chain to
11522       --  the subprogram, to insure that the activation call is properly
11523       --  generated. It the task body contains inner tasks, indicate that the
11524       --  subprogram is a task master.
11525
11526       if Delay_Cleanups (Ttyp) then
11527          Set_Activation_Chain_Entity (New_N, Activation_Chain_Entity (N));
11528          Set_Is_Task_Master  (New_N, Is_Task_Master (N));
11529       end if;
11530
11531       Rewrite (N, New_N);
11532       Analyze (N);
11533
11534       --  Set elaboration flag immediately after task body. If the body is a
11535       --  subunit, the flag is set in the declarative part containing the stub.
11536
11537       if Nkind (Parent (N)) /= N_Subunit then
11538          Insert_After (N,
11539            Make_Assignment_Statement (Loc,
11540              Name =>
11541                Make_Identifier (Loc, New_External_Name (Chars (Ttyp), 'E')),
11542              Expression => New_Occurrence_Of (Standard_True, Loc)));
11543       end if;
11544
11545       --  Ada 2005 (AI-345): Construct the primitive entry wrapper bodies after
11546       --  the task body. At this point all wrapper specs have been created,
11547       --  frozen and included in the dispatch table for the task type.
11548
11549       if Ada_Version >= Ada_2005 then
11550          if Nkind (Parent (N)) = N_Subunit then
11551             Insert_Nod := Corresponding_Stub (Parent (N));
11552          else
11553             Insert_Nod := N;
11554          end if;
11555
11556          Build_Wrapper_Bodies (Loc, Ttyp, Insert_Nod);
11557       end if;
11558    end Expand_N_Task_Body;
11559
11560    ------------------------------------
11561    -- Expand_N_Task_Type_Declaration --
11562    ------------------------------------
11563
11564    --  We have several things to do. First we must create a Boolean flag used
11565    --  to mark if the body is elaborated yet. This variable gets set to True
11566    --  when the body of the task is elaborated (we can't rely on the normal
11567    --  ABE mechanism for the task body, since we need to pass an access to
11568    --  this elaboration boolean to the runtime routines).
11569
11570    --    taskE : aliased Boolean := False;
11571
11572    --  Next a variable is declared to hold the task stack size (either the
11573    --  default : Unspecified_Size, or a value that is set by a pragma
11574    --  Storage_Size). If the value of the pragma Storage_Size is static, then
11575    --  the variable is initialized with this value:
11576
11577    --    taskZ : Size_Type := Unspecified_Size;
11578    --  or
11579    --    taskZ : Size_Type := Size_Type (size_expression);
11580
11581    --  Note: No variable is needed to hold the task relative deadline since
11582    --  its value would never be static because the parameter is of a private
11583    --  type (Ada.Real_Time.Time_Span).
11584
11585    --  Next we create a corresponding record type declaration used to represent
11586    --  values of this task. The general form of this type declaration is
11587
11588    --    type taskV (discriminants) is record
11589    --      _Task_Id           : Task_Id;
11590    --      entry_family       : array (bounds) of Void;
11591    --      _Priority          : Integer            := priority_expression;
11592    --      _Size              : Size_Type          := size_expression;
11593    --      _Task_Info         : Task_Info_Type     := task_info_expression;
11594    --      _CPU               : Integer            := cpu_range_expression;
11595    --      _Relative_Deadline : Time_Span          := time_span_expression;
11596    --      _Domain            : Dispatching_Domain := dd_expression;
11597    --    end record;
11598
11599    --  The discriminants are present only if the corresponding task type has
11600    --  discriminants, and they exactly mirror the task type discriminants.
11601
11602    --  The Id field is always present. It contains the Task_Id value, as set by
11603    --  the call to Create_Task. Note that although the task is limited, the
11604    --  task value record type is not limited, so there is no problem in passing
11605    --  this field as an out parameter to Create_Task.
11606
11607    --  One entry_family component is present for each entry family in the task
11608    --  definition. The bounds correspond to the bounds of the entry family
11609    --  (which may depend on discriminants). The element type is void, since we
11610    --  only need the bounds information for determining the entry index. Note
11611    --  that the use of an anonymous array would normally be illegal in this
11612    --  context, but this is a parser check, and the semantics is quite prepared
11613    --  to handle such a case.
11614
11615    --  The _Size field is present only if a Storage_Size pragma appears in the
11616    --  task definition. The expression captures the argument that was present
11617    --  in the pragma, and is used to override the task stack size otherwise
11618    --  associated with the task type.
11619
11620    --  The _Priority field is present only if the task entity has a Priority or
11621    --  Interrupt_Priority rep item (pragma, aspect specification or attribute
11622    --  definition clause). It will be filled at the freeze point, when the
11623    --  record init proc is built, to capture the expression of the rep item
11624    --  (see Build_Record_Init_Proc in Exp_Ch3). Note that it cannot be filled
11625    --  here since aspect evaluations are delayed till the freeze point.
11626
11627    --  The _Task_Info field is present only if a Task_Info pragma appears in
11628    --  the task definition. The expression captures the argument that was
11629    --  present in the pragma, and is used to provide the Task_Image parameter
11630    --  to the call to Create_Task.
11631
11632    --  The _CPU field is present only if the task entity has a CPU rep item
11633    --  (pragma, aspect specification or attribute definition clause). It will
11634    --  be filled at the freeze point, when the record init proc is built, to
11635    --  capture the expression of the rep item (see Build_Record_Init_Proc in
11636    --  Exp_Ch3). Note that it cannot be filled here since aspect evaluations
11637    --  are delayed till the freeze point.
11638
11639    --  The _Relative_Deadline field is present only if a Relative_Deadline
11640    --  pragma appears in the task definition. The expression captures the
11641    --  argument that was present in the pragma, and is used to provide the
11642    --  Relative_Deadline parameter to the call to Create_Task.
11643
11644    --  The _Domain field is present only if the task entity has a
11645    --  Dispatching_Domain rep item (pragma, aspect specification or attribute
11646    --  definition clause). It will be filled at the freeze point, when the
11647    --  record init proc is built, to capture the expression of the rep item
11648    --  (see Build_Record_Init_Proc in Exp_Ch3). Note that it cannot be filled
11649    --  here since aspect evaluations are delayed till the freeze point.
11650
11651    --  When a task is declared, an instance of the task value record is
11652    --  created. The elaboration of this declaration creates the correct bounds
11653    --  for the entry families, and also evaluates the size, priority, and
11654    --  task_Info expressions if needed. The initialization routine for the task
11655    --  type itself then calls Create_Task with appropriate parameters to
11656    --  initialize the value of the Task_Id field.
11657
11658    --  Note: the address of this record is passed as the "Discriminants"
11659    --  parameter for Create_Task. Since Create_Task merely passes this onto the
11660    --  body procedure, it does not matter that it does not quite match the
11661    --  GNARLI model of what is being passed (the record contains more than just
11662    --  the discriminants, but the discriminants can be found from the record
11663    --  value).
11664
11665    --  The Entity_Id for this created record type is placed in the
11666    --  Corresponding_Record_Type field of the associated task type entity.
11667
11668    --  Next we create a procedure specification for the task body procedure:
11669
11670    --    procedure taskB (_Task : access taskV);
11671
11672    --  Note that this must come after the record type declaration, since
11673    --  the spec refers to this type. It turns out that the initialization
11674    --  procedure for the value type references the task body spec, but that's
11675    --  fine, since it won't be generated till the freeze point for the type,
11676    --  which is certainly after the task body spec declaration.
11677
11678    --  Finally, we set the task index value field of the entry attribute in
11679    --  the case of a simple entry.
11680
11681    procedure Expand_N_Task_Type_Declaration (N : Node_Id) is
11682       Loc     : constant Source_Ptr := Sloc (N);
11683       TaskId  : constant Entity_Id  := Defining_Identifier (N);
11684       Tasktyp : constant Entity_Id  := Etype (Defining_Identifier (N));
11685       Tasknm  : constant Name_Id    := Chars (Tasktyp);
11686       Taskdef : constant Node_Id    := Task_Definition (N);
11687
11688       Body_Decl  : Node_Id;
11689       Cdecls     : List_Id;
11690       Decl_Stack : Node_Id;
11691       Elab_Decl  : Node_Id;
11692       Ent_Stack  : Entity_Id;
11693       Proc_Spec  : Node_Id;
11694       Rec_Decl   : Node_Id;
11695       Rec_Ent    : Entity_Id;
11696       Size_Decl  : Entity_Id;
11697       Task_Size  : Node_Id;
11698
11699       function Get_Relative_Deadline_Pragma (T : Node_Id) return Node_Id;
11700       --  Searches the task definition T for the first occurrence of the pragma
11701       --  Relative Deadline. The caller has ensured that the pragma is present
11702       --  in the task definition. Note that this routine cannot be implemented
11703       --  with the Rep Item chain mechanism since Relative_Deadline pragmas are
11704       --  not chained because their expansion into a procedure call statement
11705       --  would cause a break in the chain.
11706
11707       ----------------------------------
11708       -- Get_Relative_Deadline_Pragma --
11709       ----------------------------------
11710
11711       function Get_Relative_Deadline_Pragma (T : Node_Id) return Node_Id is
11712          N : Node_Id;
11713
11714       begin
11715          N := First (Visible_Declarations (T));
11716          while Present (N) loop
11717             if Nkind (N) = N_Pragma
11718               and then Pragma_Name (N) = Name_Relative_Deadline
11719             then
11720                return N;
11721             end if;
11722
11723             Next (N);
11724          end loop;
11725
11726          N := First (Private_Declarations (T));
11727          while Present (N) loop
11728             if Nkind (N) = N_Pragma
11729               and then Pragma_Name (N) = Name_Relative_Deadline
11730             then
11731                return N;
11732             end if;
11733
11734             Next (N);
11735          end loop;
11736
11737          raise Program_Error;
11738       end Get_Relative_Deadline_Pragma;
11739
11740    --  Start of processing for Expand_N_Task_Type_Declaration
11741
11742    begin
11743       --  If already expanded, nothing to do
11744
11745       if Present (Corresponding_Record_Type (Tasktyp)) then
11746          return;
11747       end if;
11748
11749       --  Here we will do the expansion
11750
11751       Rec_Decl := Build_Corresponding_Record (N, Tasktyp, Loc);
11752
11753       Rec_Ent  := Defining_Identifier (Rec_Decl);
11754       Cdecls   := Component_Items (Component_List
11755                                      (Type_Definition (Rec_Decl)));
11756
11757       Qualify_Entity_Names (N);
11758
11759       --  First create the elaboration variable
11760
11761       Elab_Decl :=
11762         Make_Object_Declaration (Loc,
11763           Defining_Identifier =>
11764             Make_Defining_Identifier (Sloc (Tasktyp),
11765               Chars => New_External_Name (Tasknm, 'E')),
11766           Aliased_Present      => True,
11767           Object_Definition    => New_Occurrence_Of (Standard_Boolean, Loc),
11768           Expression           => New_Occurrence_Of (Standard_False, Loc));
11769
11770       Insert_After (N, Elab_Decl);
11771
11772       --  Next create the declaration of the size variable (tasknmZ)
11773
11774       Set_Storage_Size_Variable (Tasktyp,
11775         Make_Defining_Identifier (Sloc (Tasktyp),
11776           Chars => New_External_Name (Tasknm, 'Z')));
11777
11778       if Present (Taskdef)
11779         and then Has_Storage_Size_Pragma (Taskdef)
11780         and then
11781           Is_OK_Static_Expression
11782             (Expression
11783                (First (Pragma_Argument_Associations
11784                          (Get_Rep_Pragma (TaskId, Name_Storage_Size)))))
11785       then
11786          Size_Decl :=
11787            Make_Object_Declaration (Loc,
11788              Defining_Identifier => Storage_Size_Variable (Tasktyp),
11789              Object_Definition   =>
11790                New_Occurrence_Of (RTE (RE_Size_Type), Loc),
11791              Expression          =>
11792                Convert_To (RTE (RE_Size_Type),
11793                  Relocate_Node
11794                    (Expression (First (Pragma_Argument_Associations
11795                                          (Get_Rep_Pragma
11796                                             (TaskId, Name_Storage_Size)))))));
11797
11798       else
11799          Size_Decl :=
11800            Make_Object_Declaration (Loc,
11801              Defining_Identifier => Storage_Size_Variable (Tasktyp),
11802              Object_Definition   =>
11803                New_Occurrence_Of (RTE (RE_Size_Type), Loc),
11804              Expression          =>
11805                New_Occurrence_Of (RTE (RE_Unspecified_Size), Loc));
11806       end if;
11807
11808       Insert_After (Elab_Decl, Size_Decl);
11809
11810       --  Next build the rest of the corresponding record declaration. This is
11811       --  done last, since the corresponding record initialization procedure
11812       --  will reference the previously created entities.
11813
11814       --  Fill in the component declarations -- first the _Task_Id field
11815
11816       Append_To (Cdecls,
11817         Make_Component_Declaration (Loc,
11818           Defining_Identifier  =>
11819             Make_Defining_Identifier (Loc, Name_uTask_Id),
11820           Component_Definition =>
11821             Make_Component_Definition (Loc,
11822               Aliased_Present    => False,
11823               Subtype_Indication => New_Occurrence_Of (RTE (RO_ST_Task_Id),
11824                                     Loc))));
11825
11826       --  Declare static ATCB (that is, created by the expander) if we are
11827       --  using the Restricted run time.
11828
11829       if Restricted_Profile then
11830          Append_To (Cdecls,
11831            Make_Component_Declaration (Loc,
11832              Defining_Identifier  =>
11833                Make_Defining_Identifier (Loc, Name_uATCB),
11834
11835              Component_Definition =>
11836                Make_Component_Definition (Loc,
11837                  Aliased_Present     => True,
11838                  Subtype_Indication  => Make_Subtype_Indication (Loc,
11839                    Subtype_Mark =>
11840                      New_Occurrence_Of (RTE (RE_Ada_Task_Control_Block), Loc),
11841
11842                    Constraint   =>
11843                      Make_Index_Or_Discriminant_Constraint (Loc,
11844                        Constraints =>
11845                          New_List (Make_Integer_Literal (Loc, 0)))))));
11846
11847       end if;
11848
11849       --  Declare static stack (that is, created by the expander) if we are
11850       --  using the Restricted run time on a bare board configuration.
11851
11852       if Restricted_Profile and then Preallocated_Stacks_On_Target then
11853
11854          --  First we need to extract the appropriate stack size
11855
11856          Ent_Stack := Make_Defining_Identifier (Loc, Name_uStack);
11857
11858          if Present (Taskdef) and then Has_Storage_Size_Pragma (Taskdef) then
11859             declare
11860                Expr_N : constant Node_Id :=
11861                           Expression (First (
11862                             Pragma_Argument_Associations (
11863                               Get_Rep_Pragma (TaskId, Name_Storage_Size))));
11864                Etyp   : constant Entity_Id := Etype (Expr_N);
11865                P      : constant Node_Id   := Parent (Expr_N);
11866
11867             begin
11868                --  The stack is defined inside the corresponding record.
11869                --  Therefore if the size of the stack is set by means of
11870                --  a discriminant, we must reference the discriminant of the
11871                --  corresponding record type.
11872
11873                if Nkind (Expr_N) in N_Has_Entity
11874                  and then Present (Discriminal_Link (Entity (Expr_N)))
11875                then
11876                   Task_Size :=
11877                     New_Occurrence_Of
11878                       (CR_Discriminant (Discriminal_Link (Entity (Expr_N))),
11879                        Loc);
11880                   Set_Parent   (Task_Size, P);
11881                   Set_Etype    (Task_Size, Etyp);
11882                   Set_Analyzed (Task_Size);
11883
11884                else
11885                   Task_Size := Relocate_Node (Expr_N);
11886                end if;
11887             end;
11888
11889          else
11890             Task_Size :=
11891               New_Occurrence_Of (RTE (RE_Default_Stack_Size), Loc);
11892          end if;
11893
11894          Decl_Stack := Make_Component_Declaration (Loc,
11895            Defining_Identifier  => Ent_Stack,
11896
11897            Component_Definition =>
11898              Make_Component_Definition (Loc,
11899                Aliased_Present     => True,
11900                Subtype_Indication  => Make_Subtype_Indication (Loc,
11901                  Subtype_Mark =>
11902                    New_Occurrence_Of (RTE (RE_Storage_Array), Loc),
11903
11904                  Constraint   =>
11905                    Make_Index_Or_Discriminant_Constraint (Loc,
11906                      Constraints  => New_List (Make_Range (Loc,
11907                        Low_Bound  => Make_Integer_Literal (Loc, 1),
11908                        High_Bound => Convert_To (RTE (RE_Storage_Offset),
11909                          Task_Size)))))));
11910
11911          Append_To (Cdecls, Decl_Stack);
11912
11913          --  The appropriate alignment for the stack is ensured by the run-time
11914          --  code in charge of task creation.
11915
11916       end if;
11917
11918       --  Add components for entry families
11919
11920       Collect_Entry_Families (Loc, Cdecls, Size_Decl, Tasktyp);
11921
11922       --  Add the _Priority component if a Interrupt_Priority or Priority rep
11923       --  item is present.
11924
11925       if Has_Rep_Item (TaskId, Name_Priority, Check_Parents => False) then
11926          Append_To (Cdecls,
11927            Make_Component_Declaration (Loc,
11928              Defining_Identifier  =>
11929                Make_Defining_Identifier (Loc, Name_uPriority),
11930              Component_Definition =>
11931                Make_Component_Definition (Loc,
11932                  Aliased_Present    => False,
11933                  Subtype_Indication =>
11934                    New_Occurrence_Of (Standard_Integer, Loc))));
11935       end if;
11936
11937       --  Add the _Size component if a Storage_Size pragma is present
11938
11939       if Present (Taskdef) and then Has_Storage_Size_Pragma (Taskdef) then
11940          Append_To (Cdecls,
11941            Make_Component_Declaration (Loc,
11942              Defining_Identifier =>
11943                Make_Defining_Identifier (Loc, Name_uSize),
11944
11945              Component_Definition =>
11946                Make_Component_Definition (Loc,
11947                  Aliased_Present    => False,
11948                  Subtype_Indication =>
11949                    New_Occurrence_Of (RTE (RE_Size_Type), Loc)),
11950
11951              Expression =>
11952                Convert_To (RTE (RE_Size_Type),
11953                  Relocate_Node (
11954                    Expression (First (
11955                      Pragma_Argument_Associations (
11956                        Get_Rep_Pragma (TaskId, Name_Storage_Size))))))));
11957       end if;
11958
11959       --  Add the _Task_Info component if a Task_Info pragma is present
11960
11961       if Has_Rep_Pragma (TaskId, Name_Task_Info, Check_Parents => False) then
11962          Append_To (Cdecls,
11963            Make_Component_Declaration (Loc,
11964              Defining_Identifier =>
11965                Make_Defining_Identifier (Loc, Name_uTask_Info),
11966
11967              Component_Definition =>
11968                Make_Component_Definition (Loc,
11969                  Aliased_Present    => False,
11970                  Subtype_Indication =>
11971                    New_Occurrence_Of (RTE (RE_Task_Info_Type), Loc)),
11972
11973              Expression => New_Copy (
11974                Expression (First (
11975                  Pragma_Argument_Associations (
11976                    Get_Rep_Pragma
11977                      (TaskId, Name_Task_Info, Check_Parents => False)))))));
11978       end if;
11979
11980       --  Add the _CPU component if a CPU rep item is present
11981
11982       if Has_Rep_Item (TaskId, Name_CPU, Check_Parents => False) then
11983          Append_To (Cdecls,
11984            Make_Component_Declaration (Loc,
11985              Defining_Identifier =>
11986                Make_Defining_Identifier (Loc, Name_uCPU),
11987
11988              Component_Definition =>
11989                Make_Component_Definition (Loc,
11990                  Aliased_Present    => False,
11991                  Subtype_Indication =>
11992                    New_Occurrence_Of (RTE (RE_CPU_Range), Loc))));
11993       end if;
11994
11995       --  Add the _Relative_Deadline component if a Relative_Deadline pragma is
11996       --  present. If we are using a restricted run time this component will
11997       --  not be added (deadlines are not allowed by the Ravenscar profile).
11998
11999       if not Restricted_Profile
12000         and then Present (Taskdef)
12001         and then Has_Relative_Deadline_Pragma (Taskdef)
12002       then
12003          Append_To (Cdecls,
12004            Make_Component_Declaration (Loc,
12005              Defining_Identifier =>
12006                Make_Defining_Identifier (Loc, Name_uRelative_Deadline),
12007
12008              Component_Definition =>
12009                Make_Component_Definition (Loc,
12010                  Aliased_Present    => False,
12011                  Subtype_Indication =>
12012                    New_Occurrence_Of (RTE (RE_Time_Span), Loc)),
12013
12014              Expression =>
12015                Convert_To (RTE (RE_Time_Span),
12016                  Relocate_Node (
12017                    Expression (First (
12018                      Pragma_Argument_Associations (
12019                        Get_Relative_Deadline_Pragma (Taskdef))))))));
12020       end if;
12021
12022       --  Add the _Dispatching_Domain component if a Dispatching_Domain rep
12023       --  item is present. If we are using a restricted run time this component
12024       --  will not be added (dispatching domains are not allowed by the
12025       --  Ravenscar profile).
12026
12027       if not Restricted_Profile
12028         and then
12029           Has_Rep_Item
12030             (TaskId, Name_Dispatching_Domain, Check_Parents => False)
12031       then
12032          Append_To (Cdecls,
12033            Make_Component_Declaration (Loc,
12034              Defining_Identifier  =>
12035                Make_Defining_Identifier (Loc, Name_uDispatching_Domain),
12036
12037              Component_Definition =>
12038                Make_Component_Definition (Loc,
12039                  Aliased_Present    => False,
12040                  Subtype_Indication =>
12041                    New_Occurrence_Of
12042                      (RTE (RE_Dispatching_Domain_Access), Loc))));
12043       end if;
12044
12045       Insert_After (Size_Decl, Rec_Decl);
12046
12047       --  Analyze the record declaration immediately after construction,
12048       --  because the initialization procedure is needed for single task
12049       --  declarations before the next entity is analyzed.
12050
12051       Analyze (Rec_Decl);
12052
12053       --  Create the declaration of the task body procedure
12054
12055       Proc_Spec := Build_Task_Proc_Specification (Tasktyp);
12056       Body_Decl :=
12057         Make_Subprogram_Declaration (Loc,
12058           Specification => Proc_Spec);
12059       Set_Is_Task_Body_Procedure (Body_Decl);
12060
12061       Insert_After (Rec_Decl, Body_Decl);
12062
12063       --  The subprogram does not comes from source, so we have to indicate the
12064       --  need for debugging information explicitly.
12065
12066       if Comes_From_Source (Original_Node (N)) then
12067          Set_Debug_Info_Needed (Defining_Entity (Proc_Spec));
12068       end if;
12069
12070       --  Ada 2005 (AI-345): Construct the primitive entry wrapper specs before
12071       --  the corresponding record has been frozen.
12072
12073       if Ada_Version >= Ada_2005 then
12074          Build_Wrapper_Specs (Loc, Tasktyp, Rec_Decl);
12075       end if;
12076
12077       --  Ada 2005 (AI-345): We must defer freezing to allow further
12078       --  declaration of primitive subprograms covering task interfaces
12079
12080       if Ada_Version <= Ada_95 then
12081
12082          --  Now we can freeze the corresponding record. This needs manually
12083          --  freezing, since it is really part of the task type, and the task
12084          --  type is frozen at this stage. We of course need the initialization
12085          --  procedure for this corresponding record type and we won't get it
12086          --  in time if we don't freeze now.
12087
12088          declare
12089             L : constant List_Id := Freeze_Entity (Rec_Ent, N);
12090          begin
12091             if Is_Non_Empty_List (L) then
12092                Insert_List_After (Body_Decl, L);
12093             end if;
12094          end;
12095       end if;
12096
12097       --  Complete the expansion of access types to the current task type, if
12098       --  any were declared.
12099
12100       Expand_Previous_Access_Type (Tasktyp);
12101
12102       --  Create wrappers for entries that have pre/postconditions
12103
12104       declare
12105          Ent : Entity_Id;
12106
12107       begin
12108          Ent := First_Entity (Tasktyp);
12109          while Present (Ent) loop
12110             if Ekind_In (Ent, E_Entry, E_Entry_Family)
12111               and then Present (Contract (Ent))
12112               and then Present (Pre_Post_Conditions (Contract (Ent)))
12113             then
12114                Build_PPC_Wrapper (Ent, N);
12115             end if;
12116
12117             Next_Entity (Ent);
12118          end loop;
12119       end;
12120    end Expand_N_Task_Type_Declaration;
12121
12122    -------------------------------
12123    -- Expand_N_Timed_Entry_Call --
12124    -------------------------------
12125
12126    --  A timed entry call in normal case is not implemented using ATC mechanism
12127    --  anymore for efficiency reason.
12128
12129    --     select
12130    --        T.E;
12131    --        S1;
12132    --     or
12133    --        delay D;
12134    --        S2;
12135    --     end select;
12136
12137    --  is expanded as follows:
12138
12139    --  1) When T.E is a task entry_call;
12140
12141    --    declare
12142    --       B  : Boolean;
12143    --       X  : Task_Entry_Index := <entry index>;
12144    --       DX : Duration := To_Duration (D);
12145    --       M  : Delay_Mode := <discriminant>;
12146    --       P  : parms := (parm, parm, parm);
12147
12148    --    begin
12149    --       Timed_Protected_Entry_Call
12150    --         (<acceptor-task>, X, P'Address, DX, M, B);
12151    --       if B then
12152    --          S1;
12153    --       else
12154    --          S2;
12155    --       end if;
12156    --    end;
12157
12158    --  2) When T.E is a protected entry_call;
12159
12160    --    declare
12161    --       B  : Boolean;
12162    --       X  : Protected_Entry_Index := <entry index>;
12163    --       DX : Duration := To_Duration (D);
12164    --       M  : Delay_Mode := <discriminant>;
12165    --       P  : parms := (parm, parm, parm);
12166
12167    --    begin
12168    --       Timed_Protected_Entry_Call
12169    --         (<object>'unchecked_access, X, P'Address, DX, M, B);
12170    --       if B then
12171    --          S1;
12172    --       else
12173    --          S2;
12174    --       end if;
12175    --    end;
12176
12177    --  3) Ada 2005 (AI-345): When T.E is a dispatching procedure call, there
12178    --     is no delay and the triggering statements are executed. We first
12179    --     determine the kind of the triggering call and then execute a
12180    --     synchronized operation or a direct call.
12181
12182    --    declare
12183    --       B  : Boolean := False;
12184    --       C  : Ada.Tags.Prim_Op_Kind;
12185    --       DX : Duration := To_Duration (D)
12186    --       K  : Ada.Tags.Tagged_Kind :=
12187    --              Ada.Tags.Get_Tagged_Kind (Ada.Tags.Tag (<object>));
12188    --       M  : Integer :=...;
12189    --       P  : Parameters := (Param1 .. ParamN);
12190    --       S  : Integer;
12191
12192    --    begin
12193    --       if K = Ada.Tags.TK_Limited_Tagged
12194    --         or else K = Ada.Tags.TK_Tagged
12195    --       then
12196    --          <dispatching-call>;
12197    --          B := True;
12198
12199    --       else
12200    --          S :=
12201    --            Ada.Tags.Get_Offset_Index
12202    --              (Ada.Tags.Tag (<object>), DT_Position (<dispatching-call>));
12203
12204    --          _Disp_Timed_Select (<object>, S, P'Address, DX, M, C, B);
12205
12206    --          if C = POK_Protected_Entry
12207    --            or else C = POK_Task_Entry
12208    --          then
12209    --             Param1 := P.Param1;
12210    --             ...
12211    --             ParamN := P.ParamN;
12212    --          end if;
12213
12214    --          if B then
12215    --             if C = POK_Procedure
12216    --               or else C = POK_Protected_Procedure
12217    --               or else C = POK_Task_Procedure
12218    --             then
12219    --                <dispatching-call>;
12220    --             end if;
12221    --         end if;
12222    --       end if;
12223
12224    --      if B then
12225    --          <triggering-statements>
12226    --      else
12227    --          <timed-statements>
12228    --      end if;
12229    --    end;
12230
12231    --  The triggering statement and the sequence of timed statements have not
12232    --  been analyzed yet (see Analyzed_Timed_Entry_Call), but they may contain
12233    --  global references if within an instantiation.
12234
12235    procedure Expand_N_Timed_Entry_Call (N : Node_Id) is
12236       Loc : constant Source_Ptr := Sloc (N);
12237
12238       Actuals        : List_Id;
12239       Blk_Typ        : Entity_Id;
12240       Call           : Node_Id;
12241       Call_Ent       : Entity_Id;
12242       Conc_Typ_Stmts : List_Id;
12243       Concval        : Node_Id;
12244       D_Alt          : constant Node_Id := Delay_Alternative (N);
12245       D_Conv         : Node_Id;
12246       D_Disc         : Node_Id;
12247       D_Stat         : Node_Id          := Delay_Statement (D_Alt);
12248       D_Stats        : List_Id;
12249       D_Type         : Entity_Id;
12250       Decls          : List_Id;
12251       Dummy          : Node_Id;
12252       E_Alt          : constant Node_Id := Entry_Call_Alternative (N);
12253       E_Call         : Node_Id          := Entry_Call_Statement (E_Alt);
12254       E_Stats        : List_Id;
12255       Ename          : Node_Id;
12256       Formals        : List_Id;
12257       Index          : Node_Id;
12258       Is_Disp_Select : Boolean;
12259       Lim_Typ_Stmts  : List_Id;
12260       N_Stats        : List_Id;
12261       Obj            : Entity_Id;
12262       Param          : Node_Id;
12263       Params         : List_Id;
12264       Stmt           : Node_Id;
12265       Stmts          : List_Id;
12266       Unpack         : List_Id;
12267
12268       B : Entity_Id;  --  Call status flag
12269       C : Entity_Id;  --  Call kind
12270       D : Entity_Id;  --  Delay
12271       K : Entity_Id;  --  Tagged kind
12272       M : Entity_Id;  --  Delay mode
12273       P : Entity_Id;  --  Parameter block
12274       S : Entity_Id;  --  Primitive operation slot
12275
12276    --  Start of processing for Expand_N_Timed_Entry_Call
12277
12278    begin
12279       --  Under the Ravenscar profile, timed entry calls are excluded. An error
12280       --  was already reported on spec, so do not attempt to expand the call.
12281
12282       if Restriction_Active (No_Select_Statements) then
12283          return;
12284       end if;
12285
12286       Process_Statements_For_Controlled_Objects (E_Alt);
12287       Process_Statements_For_Controlled_Objects (D_Alt);
12288
12289       Ensure_Statement_Present (Sloc (D_Stat), D_Alt);
12290
12291       --  Retrieve E_Stats and D_Stats now because the finalization machinery
12292       --  may wrap them in blocks.
12293
12294       E_Stats := Statements (E_Alt);
12295       D_Stats := Statements (D_Alt);
12296
12297       --  The arguments in the call may require dynamic allocation, and the
12298       --  call statement may have been transformed into a block. The block
12299       --  may contain additional declarations for internal entities, and the
12300       --  original call is found by sequential search.
12301
12302       if Nkind (E_Call) = N_Block_Statement then
12303          E_Call := First (Statements (Handled_Statement_Sequence (E_Call)));
12304          while not Nkind_In (E_Call, N_Procedure_Call_Statement,
12305                                      N_Entry_Call_Statement)
12306          loop
12307             Next (E_Call);
12308          end loop;
12309       end if;
12310
12311       Is_Disp_Select :=
12312         Ada_Version >= Ada_2005
12313           and then Nkind (E_Call) = N_Procedure_Call_Statement;
12314
12315       if Is_Disp_Select then
12316          Extract_Dispatching_Call (E_Call, Call_Ent, Obj, Actuals, Formals);
12317          Decls := New_List;
12318
12319          Stmts := New_List;
12320
12321          --  Generate:
12322          --    B : Boolean := False;
12323
12324          B := Build_B (Loc, Decls);
12325
12326          --  Generate:
12327          --    C : Ada.Tags.Prim_Op_Kind;
12328
12329          C := Build_C (Loc, Decls);
12330
12331          --  Because the analysis of all statements was disabled, manually
12332          --  analyze the delay statement.
12333
12334          Analyze (D_Stat);
12335          D_Stat := Original_Node (D_Stat);
12336
12337       else
12338          --  Build an entry call using Simple_Entry_Call
12339
12340          Extract_Entry (E_Call, Concval, Ename, Index);
12341          Build_Simple_Entry_Call (E_Call, Concval, Ename, Index);
12342
12343          Decls := Declarations (E_Call);
12344          Stmts := Statements (Handled_Statement_Sequence (E_Call));
12345
12346          if No (Decls) then
12347             Decls := New_List;
12348          end if;
12349
12350          --  Generate:
12351          --    B : Boolean;
12352
12353          B := Make_Defining_Identifier (Loc, Name_uB);
12354
12355          Prepend_To (Decls,
12356            Make_Object_Declaration (Loc,
12357              Defining_Identifier => B,
12358              Object_Definition   =>
12359                New_Occurrence_Of (Standard_Boolean, Loc)));
12360       end if;
12361
12362       --  Duration and mode processing
12363
12364       D_Type := Base_Type (Etype (Expression (D_Stat)));
12365
12366       --  Use the type of the delay expression (Calendar or Real_Time) to
12367       --  generate the appropriate conversion.
12368
12369       if Nkind (D_Stat) = N_Delay_Relative_Statement then
12370          D_Disc := Make_Integer_Literal (Loc, 0);
12371          D_Conv := Relocate_Node (Expression (D_Stat));
12372
12373       elsif Is_RTE (D_Type, RO_CA_Time) then
12374          D_Disc := Make_Integer_Literal (Loc, 1);
12375          D_Conv :=
12376            Make_Function_Call (Loc,
12377              Name => New_Occurrence_Of (RTE (RO_CA_To_Duration), Loc),
12378              Parameter_Associations =>
12379                New_List (New_Copy (Expression (D_Stat))));
12380
12381       else pragma Assert (Is_RTE (D_Type, RO_RT_Time));
12382          D_Disc := Make_Integer_Literal (Loc, 2);
12383          D_Conv :=
12384            Make_Function_Call (Loc,
12385              Name => New_Occurrence_Of (RTE (RO_RT_To_Duration), Loc),
12386              Parameter_Associations =>
12387                New_List (New_Copy (Expression (D_Stat))));
12388       end if;
12389
12390       D := Make_Temporary (Loc, 'D');
12391
12392       --  Generate:
12393       --    D : Duration;
12394
12395       Append_To (Decls,
12396         Make_Object_Declaration (Loc,
12397           Defining_Identifier => D,
12398           Object_Definition   => New_Occurrence_Of (Standard_Duration, Loc)));
12399
12400       M := Make_Temporary (Loc, 'M');
12401
12402       --  Generate:
12403       --    M : Integer := (0 | 1 | 2);
12404
12405       Append_To (Decls,
12406         Make_Object_Declaration (Loc,
12407           Defining_Identifier => M,
12408           Object_Definition   => New_Occurrence_Of (Standard_Integer, Loc),
12409           Expression          => D_Disc));
12410
12411       --  Do the assignment at this stage only because the evaluation of the
12412       --  expression must not occur before (see ACVC C97302A).
12413
12414       Append_To (Stmts,
12415         Make_Assignment_Statement (Loc,
12416           Name       => New_Occurrence_Of (D, Loc),
12417           Expression => D_Conv));
12418
12419       --  Parameter block processing
12420
12421       --  Manually create the parameter block for dispatching calls. In the
12422       --  case of entries, the block has already been created during the call
12423       --  to Build_Simple_Entry_Call.
12424
12425       if Is_Disp_Select then
12426
12427          --  Tagged kind processing, generate:
12428          --    K : Ada.Tags.Tagged_Kind :=
12429          --          Ada.Tags.Get_Tagged_Kind (Ada.Tags.Tag <object>));
12430
12431          K := Build_K (Loc, Decls, Obj);
12432
12433          Blk_Typ := Build_Parameter_Block (Loc, Actuals, Formals, Decls);
12434          P :=
12435            Parameter_Block_Pack (Loc, Blk_Typ, Actuals, Formals, Decls, Stmts);
12436
12437          --  Dispatch table slot processing, generate:
12438          --    S : Integer;
12439
12440          S := Build_S (Loc, Decls);
12441
12442          --  Generate:
12443          --    S := Ada.Tags.Get_Offset_Index
12444          --           (Ada.Tags.Tag (<object>), DT_Position (Call_Ent));
12445
12446          Conc_Typ_Stmts :=
12447            New_List (Build_S_Assignment (Loc, S, Obj, Call_Ent));
12448
12449          --  Generate:
12450          --    _Disp_Timed_Select (<object>, S, P'Address, D, M, C, B);
12451
12452          --  where Obj is the controlling formal parameter, S is the dispatch
12453          --  table slot number of the dispatching operation, P is the wrapped
12454          --  parameter block, D is the duration, M is the duration mode, C is
12455          --  the call kind and B is the call status.
12456
12457          Params := New_List;
12458
12459          Append_To (Params, New_Copy_Tree (Obj));
12460          Append_To (Params, New_Occurrence_Of (S, Loc));
12461          Append_To (Params,
12462            Make_Attribute_Reference (Loc,
12463              Prefix         => New_Occurrence_Of (P, Loc),
12464              Attribute_Name => Name_Address));
12465          Append_To (Params, New_Occurrence_Of (D, Loc));
12466          Append_To (Params, New_Occurrence_Of (M, Loc));
12467          Append_To (Params, New_Occurrence_Of (C, Loc));
12468          Append_To (Params, New_Occurrence_Of (B, Loc));
12469
12470          Append_To (Conc_Typ_Stmts,
12471            Make_Procedure_Call_Statement (Loc,
12472              Name =>
12473                New_Occurrence_Of
12474                  (Find_Prim_Op
12475                    (Etype (Etype (Obj)), Name_uDisp_Timed_Select), Loc),
12476              Parameter_Associations => Params));
12477
12478          --  Generate:
12479          --    if C = POK_Protected_Entry
12480          --      or else C = POK_Task_Entry
12481          --    then
12482          --       Param1 := P.Param1;
12483          --       ...
12484          --       ParamN := P.ParamN;
12485          --    end if;
12486
12487          Unpack := Parameter_Block_Unpack (Loc, P, Actuals, Formals);
12488
12489          --  Generate the if statement only when the packed parameters need
12490          --  explicit assignments to their corresponding actuals.
12491
12492          if Present (Unpack) then
12493             Append_To (Conc_Typ_Stmts,
12494               Make_Implicit_If_Statement (N,
12495
12496                 Condition       =>
12497                   Make_Or_Else (Loc,
12498                     Left_Opnd  =>
12499                       Make_Op_Eq (Loc,
12500                         Left_Opnd => New_Occurrence_Of (C, Loc),
12501                         Right_Opnd =>
12502                           New_Occurrence_Of
12503                             (RTE (RE_POK_Protected_Entry), Loc)),
12504
12505                     Right_Opnd =>
12506                       Make_Op_Eq (Loc,
12507                         Left_Opnd  => New_Occurrence_Of (C, Loc),
12508                         Right_Opnd =>
12509                           New_Occurrence_Of (RTE (RE_POK_Task_Entry), Loc))),
12510
12511                 Then_Statements => Unpack));
12512          end if;
12513
12514          --  Generate:
12515
12516          --    if B then
12517          --       if C = POK_Procedure
12518          --         or else C = POK_Protected_Procedure
12519          --         or else C = POK_Task_Procedure
12520          --       then
12521          --          <dispatching-call>
12522          --       end if;
12523          --    end if;
12524
12525          N_Stats := New_List (
12526            Make_Implicit_If_Statement (N,
12527              Condition =>
12528                Make_Or_Else (Loc,
12529                  Left_Opnd =>
12530                    Make_Op_Eq (Loc,
12531                      Left_Opnd  => New_Occurrence_Of (C, Loc),
12532                      Right_Opnd =>
12533                        New_Occurrence_Of (RTE (RE_POK_Procedure), Loc)),
12534
12535                  Right_Opnd =>
12536                    Make_Or_Else (Loc,
12537                      Left_Opnd =>
12538                        Make_Op_Eq (Loc,
12539                          Left_Opnd  => New_Occurrence_Of (C, Loc),
12540                          Right_Opnd =>
12541                            New_Occurrence_Of (RTE (
12542                              RE_POK_Protected_Procedure), Loc)),
12543                      Right_Opnd =>
12544                        Make_Op_Eq (Loc,
12545                          Left_Opnd  => New_Occurrence_Of (C, Loc),
12546                          Right_Opnd =>
12547                            New_Occurrence_Of
12548                              (RTE (RE_POK_Task_Procedure), Loc)))),
12549
12550              Then_Statements => New_List (E_Call)));
12551
12552          Append_To (Conc_Typ_Stmts,
12553            Make_Implicit_If_Statement (N,
12554              Condition       => New_Occurrence_Of (B, Loc),
12555              Then_Statements => N_Stats));
12556
12557          --  Generate:
12558          --    <dispatching-call>;
12559          --    B := True;
12560
12561          Lim_Typ_Stmts :=
12562            New_List (New_Copy_Tree (E_Call),
12563              Make_Assignment_Statement (Loc,
12564                Name       => New_Occurrence_Of (B, Loc),
12565                Expression => New_Occurrence_Of (Standard_True, Loc)));
12566
12567          --  Generate:
12568          --    if K = Ada.Tags.TK_Limited_Tagged
12569          --         or else K = Ada.Tags.TK_Tagged
12570          --       then
12571          --       Lim_Typ_Stmts
12572          --    else
12573          --       Conc_Typ_Stmts
12574          --    end if;
12575
12576          Append_To (Stmts,
12577            Make_Implicit_If_Statement (N,
12578              Condition       => Build_Dispatching_Tag_Check (K, N),
12579              Then_Statements => Lim_Typ_Stmts,
12580              Else_Statements => Conc_Typ_Stmts));
12581
12582          --    Generate:
12583
12584          --    if B then
12585          --       <triggering-statements>
12586          --    else
12587          --       <timed-statements>
12588          --    end if;
12589
12590          Append_To (Stmts,
12591            Make_Implicit_If_Statement (N,
12592              Condition       => New_Occurrence_Of (B, Loc),
12593              Then_Statements => E_Stats,
12594              Else_Statements => D_Stats));
12595
12596       else
12597          --  Simple case of a non-dispatching trigger. Skip assignments to
12598          --  temporaries created for in-out parameters.
12599
12600          --  This makes unwarranted assumptions about the shape of the expanded
12601          --  tree for the call, and should be cleaned up ???
12602
12603          Stmt := First (Stmts);
12604          while Nkind (Stmt) /= N_Procedure_Call_Statement loop
12605             Next (Stmt);
12606          end loop;
12607
12608          --  Do the assignment at this stage only because the evaluation
12609          --  of the expression must not occur before (see ACVC C97302A).
12610
12611          Insert_Before (Stmt,
12612            Make_Assignment_Statement (Loc,
12613              Name       => New_Occurrence_Of (D, Loc),
12614              Expression => D_Conv));
12615
12616          Call   := Stmt;
12617          Params := Parameter_Associations (Call);
12618
12619          --  For a protected type, we build a Timed_Protected_Entry_Call
12620
12621          if Is_Protected_Type (Etype (Concval)) then
12622
12623             --  Create a new call statement
12624
12625             Param := First (Params);
12626             while Present (Param)
12627               and then not Is_RTE (Etype (Param), RE_Call_Modes)
12628             loop
12629                Next (Param);
12630             end loop;
12631
12632             Dummy := Remove_Next (Next (Param));
12633
12634             --  Remove garbage is following the Cancel_Param if present
12635
12636             Dummy := Next (Param);
12637
12638             --  Remove the mode of the Protected_Entry_Call call, then remove
12639             --  the Communication_Block of the Protected_Entry_Call call, and
12640             --  finally add Duration and a Delay_Mode parameter
12641
12642             pragma Assert (Present (Param));
12643             Rewrite (Param, New_Occurrence_Of (D, Loc));
12644
12645             Rewrite (Dummy, New_Occurrence_Of (M, Loc));
12646
12647             --  Add a Boolean flag for successful entry call
12648
12649             Append_To (Params, New_Occurrence_Of (B, Loc));
12650
12651             case Corresponding_Runtime_Package (Etype (Concval)) is
12652                when System_Tasking_Protected_Objects_Entries =>
12653                   Rewrite (Call,
12654                     Make_Procedure_Call_Statement (Loc,
12655                       Name =>
12656                         New_Occurrence_Of
12657                           (RTE (RE_Timed_Protected_Entry_Call), Loc),
12658                       Parameter_Associations => Params));
12659
12660                when others =>
12661                   raise Program_Error;
12662             end case;
12663
12664          --  For the task case, build a Timed_Task_Entry_Call
12665
12666          else
12667             --  Create a new call statement
12668
12669             Append_To (Params, New_Occurrence_Of (D, Loc));
12670             Append_To (Params, New_Occurrence_Of (M, Loc));
12671             Append_To (Params, New_Occurrence_Of (B, Loc));
12672
12673             Rewrite (Call,
12674               Make_Procedure_Call_Statement (Loc,
12675                 Name =>
12676                   New_Occurrence_Of (RTE (RE_Timed_Task_Entry_Call), Loc),
12677                 Parameter_Associations => Params));
12678          end if;
12679
12680          Append_To (Stmts,
12681            Make_Implicit_If_Statement (N,
12682              Condition       => New_Occurrence_Of (B, Loc),
12683              Then_Statements => E_Stats,
12684              Else_Statements => D_Stats));
12685       end if;
12686
12687       Rewrite (N,
12688         Make_Block_Statement (Loc,
12689           Declarations               => Decls,
12690           Handled_Statement_Sequence =>
12691             Make_Handled_Sequence_Of_Statements (Loc, Stmts)));
12692
12693       Analyze (N);
12694    end Expand_N_Timed_Entry_Call;
12695
12696    ----------------------------------------
12697    -- Expand_Protected_Body_Declarations --
12698    ----------------------------------------
12699
12700    procedure Expand_Protected_Body_Declarations
12701      (N       : Node_Id;
12702       Spec_Id : Entity_Id)
12703    is
12704    begin
12705       if No_Run_Time_Mode then
12706          Error_Msg_CRT ("protected body", N);
12707          return;
12708
12709       elsif Expander_Active then
12710
12711          --  Associate discriminals with the first subprogram or entry body to
12712          --  be expanded.
12713
12714          if Present (First_Protected_Operation (Declarations (N))) then
12715             Set_Discriminals (Parent (Spec_Id));
12716          end if;
12717       end if;
12718    end Expand_Protected_Body_Declarations;
12719
12720    -------------------------
12721    -- External_Subprogram --
12722    -------------------------
12723
12724    function External_Subprogram (E : Entity_Id) return Entity_Id is
12725       Subp : constant Entity_Id := Protected_Body_Subprogram (E);
12726
12727    begin
12728       --  The internal and external subprograms follow each other on the entity
12729       --  chain. Note that previously private operations had no separate
12730       --  external subprogram. We now create one in all cases, because a
12731       --  private operation may actually appear in an external call, through
12732       --  a 'Access reference used for a callback.
12733
12734       --  If the operation is a function that returns an anonymous access type,
12735       --  the corresponding itype appears before the operation, and must be
12736       --  skipped.
12737
12738       --  This mechanism is fragile, there should be a real link between the
12739       --  two versions of the operation, but there is no place to put it ???
12740
12741       if Is_Access_Type (Next_Entity (Subp)) then
12742          return Next_Entity (Next_Entity (Subp));
12743       else
12744          return Next_Entity (Subp);
12745       end if;
12746    end External_Subprogram;
12747
12748    ------------------------------
12749    -- Extract_Dispatching_Call --
12750    ------------------------------
12751
12752    procedure Extract_Dispatching_Call
12753      (N        : Node_Id;
12754       Call_Ent : out Entity_Id;
12755       Object   : out Entity_Id;
12756       Actuals  : out List_Id;
12757       Formals  : out List_Id)
12758    is
12759       Call_Nam : Node_Id;
12760
12761    begin
12762       pragma Assert (Nkind (N) = N_Procedure_Call_Statement);
12763
12764       if Present (Original_Node (N)) then
12765          Call_Nam := Name (Original_Node (N));
12766       else
12767          Call_Nam := Name (N);
12768       end if;
12769
12770       --  Retrieve the name of the dispatching procedure. It contains the
12771       --  dispatch table slot number.
12772
12773       loop
12774          case Nkind (Call_Nam) is
12775             when N_Identifier =>
12776                exit;
12777
12778             when N_Selected_Component =>
12779                Call_Nam := Selector_Name (Call_Nam);
12780
12781             when others =>
12782                raise Program_Error;
12783
12784          end case;
12785       end loop;
12786
12787       Actuals  := Parameter_Associations (N);
12788       Call_Ent := Entity (Call_Nam);
12789       Formals  := Parameter_Specifications (Parent (Call_Ent));
12790       Object   := First (Actuals);
12791
12792       if Present (Original_Node (Object)) then
12793          Object := Original_Node (Object);
12794       end if;
12795
12796       --  If the type of the dispatching object is an access type then return
12797       --  an explicit dereference.
12798
12799       if Is_Access_Type (Etype (Object)) then
12800          Object := Make_Explicit_Dereference (Sloc (N), Object);
12801          Analyze (Object);
12802       end if;
12803    end Extract_Dispatching_Call;
12804
12805    -------------------
12806    -- Extract_Entry --
12807    -------------------
12808
12809    procedure Extract_Entry
12810      (N       : Node_Id;
12811       Concval : out Node_Id;
12812       Ename   : out Node_Id;
12813       Index   : out Node_Id)
12814    is
12815       Nam : constant Node_Id := Name (N);
12816
12817    begin
12818       --  For a simple entry, the name is a selected component, with the
12819       --  prefix being the task value, and the selector being the entry.
12820
12821       if Nkind (Nam) = N_Selected_Component then
12822          Concval := Prefix (Nam);
12823          Ename   := Selector_Name (Nam);
12824          Index   := Empty;
12825
12826       --  For a member of an entry family, the name is an indexed component
12827       --  where the prefix is a selected component, whose prefix in turn is
12828       --  the task value, and whose selector is the entry family. The single
12829       --  expression in the expressions list of the indexed component is the
12830       --  subscript for the family.
12831
12832       else pragma Assert (Nkind (Nam) = N_Indexed_Component);
12833          Concval := Prefix (Prefix (Nam));
12834          Ename   := Selector_Name (Prefix (Nam));
12835          Index   := First (Expressions (Nam));
12836       end if;
12837
12838       --  Through indirection, the type may actually be a limited view of a
12839       --  concurrent type. When compiling a call, the non-limited view of the
12840       --  type is visible.
12841
12842       if From_Limited_With (Etype (Concval)) then
12843          Set_Etype (Concval, Non_Limited_View (Etype (Concval)));
12844       end if;
12845    end Extract_Entry;
12846
12847    -------------------
12848    -- Family_Offset --
12849    -------------------
12850
12851    function Family_Offset
12852      (Loc  : Source_Ptr;
12853       Hi   : Node_Id;
12854       Lo   : Node_Id;
12855       Ttyp : Entity_Id;
12856       Cap  : Boolean) return Node_Id
12857    is
12858       Ityp : Entity_Id;
12859       Real_Hi : Node_Id;
12860       Real_Lo : Node_Id;
12861
12862       function Convert_Discriminant_Ref (Bound : Node_Id) return Node_Id;
12863       --  If one of the bounds is a reference to a discriminant, replace with
12864       --  corresponding discriminal of type. Within the body of a task retrieve
12865       --  the renamed discriminant by simple visibility, using its generated
12866       --  name. Within a protected object, find the original discriminant and
12867       --  replace it with the discriminal of the current protected operation.
12868
12869       ------------------------------
12870       -- Convert_Discriminant_Ref --
12871       ------------------------------
12872
12873       function Convert_Discriminant_Ref (Bound : Node_Id) return Node_Id is
12874          Loc : constant Source_Ptr := Sloc (Bound);
12875          B   : Node_Id;
12876          D   : Entity_Id;
12877
12878       begin
12879          if Is_Entity_Name (Bound)
12880            and then Ekind (Entity (Bound)) = E_Discriminant
12881          then
12882             if Is_Task_Type (Ttyp) and then Has_Completion (Ttyp) then
12883                B := Make_Identifier (Loc, Chars (Entity (Bound)));
12884                Find_Direct_Name (B);
12885
12886             elsif Is_Protected_Type (Ttyp) then
12887                D := First_Discriminant (Ttyp);
12888                while Chars (D) /= Chars (Entity (Bound)) loop
12889                   Next_Discriminant (D);
12890                end loop;
12891
12892                B := New_Occurrence_Of  (Discriminal (D), Loc);
12893
12894             else
12895                B := New_Occurrence_Of (Discriminal (Entity (Bound)), Loc);
12896             end if;
12897
12898          elsif Nkind (Bound) = N_Attribute_Reference then
12899             return Bound;
12900
12901          else
12902             B := New_Copy_Tree (Bound);
12903          end if;
12904
12905          return
12906            Make_Attribute_Reference (Loc,
12907              Attribute_Name => Name_Pos,
12908              Prefix => New_Occurrence_Of (Etype (Bound), Loc),
12909              Expressions    => New_List (B));
12910       end Convert_Discriminant_Ref;
12911
12912    --  Start of processing for Family_Offset
12913
12914    begin
12915       Real_Hi := Convert_Discriminant_Ref (Hi);
12916       Real_Lo := Convert_Discriminant_Ref (Lo);
12917
12918       if Cap then
12919          if Is_Task_Type (Ttyp) then
12920             Ityp := RTE (RE_Task_Entry_Index);
12921          else
12922             Ityp := RTE (RE_Protected_Entry_Index);
12923          end if;
12924
12925          Real_Hi :=
12926            Make_Attribute_Reference (Loc,
12927              Prefix         => New_Occurrence_Of (Ityp, Loc),
12928              Attribute_Name => Name_Min,
12929              Expressions    => New_List (
12930                Real_Hi,
12931                Make_Integer_Literal (Loc, Entry_Family_Bound - 1)));
12932
12933          Real_Lo :=
12934            Make_Attribute_Reference (Loc,
12935              Prefix         => New_Occurrence_Of (Ityp, Loc),
12936              Attribute_Name => Name_Max,
12937              Expressions    => New_List (
12938                Real_Lo,
12939                Make_Integer_Literal (Loc, -Entry_Family_Bound)));
12940       end if;
12941
12942       return Make_Op_Subtract (Loc, Real_Hi, Real_Lo);
12943    end Family_Offset;
12944
12945    -----------------
12946    -- Family_Size --
12947    -----------------
12948
12949    function Family_Size
12950      (Loc  : Source_Ptr;
12951       Hi   : Node_Id;
12952       Lo   : Node_Id;
12953       Ttyp : Entity_Id;
12954       Cap  : Boolean) return Node_Id
12955    is
12956       Ityp : Entity_Id;
12957
12958    begin
12959       if Is_Task_Type (Ttyp) then
12960          Ityp := RTE (RE_Task_Entry_Index);
12961       else
12962          Ityp := RTE (RE_Protected_Entry_Index);
12963       end if;
12964
12965       return
12966         Make_Attribute_Reference (Loc,
12967           Prefix         => New_Occurrence_Of (Ityp, Loc),
12968           Attribute_Name => Name_Max,
12969           Expressions    => New_List (
12970             Make_Op_Add (Loc,
12971               Left_Opnd  => Family_Offset (Loc, Hi, Lo, Ttyp, Cap),
12972               Right_Opnd => Make_Integer_Literal (Loc, 1)),
12973             Make_Integer_Literal (Loc, 0)));
12974    end Family_Size;
12975
12976    ----------------------------
12977    -- Find_Enclosing_Context --
12978    ----------------------------
12979
12980    procedure Find_Enclosing_Context
12981      (N             : Node_Id;
12982       Context       : out Node_Id;
12983       Context_Id    : out Entity_Id;
12984       Context_Decls : out List_Id)
12985    is
12986    begin
12987       --  Traverse the parent chain looking for an enclosing body, block,
12988       --  package or return statement.
12989
12990       Context := Parent (N);
12991       while not Nkind_In (Context, N_Block_Statement,
12992                                    N_Entry_Body,
12993                                    N_Extended_Return_Statement,
12994                                    N_Package_Body,
12995                                    N_Package_Declaration,
12996                                    N_Subprogram_Body,
12997                                    N_Task_Body)
12998       loop
12999          Context := Parent (Context);
13000       end loop;
13001
13002       --  Extract the constituents of the context
13003
13004       if Nkind (Context) = N_Extended_Return_Statement then
13005          Context_Decls := Return_Object_Declarations (Context);
13006          Context_Id    := Return_Statement_Entity (Context);
13007
13008       --  Package declarations and bodies use a common library-level activation
13009       --  chain or task master, therefore return the package declaration as the
13010       --  proper carrier for the appropriate flag.
13011
13012       elsif Nkind (Context) = N_Package_Body then
13013          Context_Decls := Declarations (Context);
13014          Context_Id    := Corresponding_Spec (Context);
13015          Context       := Parent (Context_Id);
13016
13017          if Nkind (Context) = N_Defining_Program_Unit_Name then
13018             Context := Parent (Parent (Context));
13019          else
13020             Context := Parent (Context);
13021          end if;
13022
13023       elsif Nkind (Context) = N_Package_Declaration then
13024          Context_Decls := Visible_Declarations (Specification (Context));
13025          Context_Id    := Defining_Unit_Name (Specification (Context));
13026
13027          if Nkind (Context_Id) = N_Defining_Program_Unit_Name then
13028             Context_Id := Defining_Identifier (Context_Id);
13029          end if;
13030
13031       else
13032          Context_Decls := Declarations (Context);
13033
13034          if Nkind (Context) = N_Block_Statement then
13035             Context_Id := Entity (Identifier (Context));
13036
13037          elsif Nkind (Context) = N_Entry_Body then
13038             Context_Id := Defining_Identifier (Context);
13039
13040          elsif Nkind (Context) = N_Subprogram_Body then
13041             if Present (Corresponding_Spec (Context)) then
13042                Context_Id := Corresponding_Spec (Context);
13043             else
13044                Context_Id := Defining_Unit_Name (Specification (Context));
13045
13046                if Nkind (Context_Id) = N_Defining_Program_Unit_Name then
13047                   Context_Id := Defining_Identifier (Context_Id);
13048                end if;
13049             end if;
13050
13051          elsif Nkind (Context) = N_Task_Body then
13052             Context_Id := Corresponding_Spec (Context);
13053
13054          else
13055             raise Program_Error;
13056          end if;
13057       end if;
13058
13059       pragma Assert (Present (Context));
13060       pragma Assert (Present (Context_Id));
13061       pragma Assert (Present (Context_Decls));
13062    end Find_Enclosing_Context;
13063
13064    -----------------------
13065    -- Find_Master_Scope --
13066    -----------------------
13067
13068    function Find_Master_Scope (E : Entity_Id) return Entity_Id is
13069       S : Entity_Id;
13070
13071    begin
13072       --  In Ada 2005, the master is the innermost enclosing scope that is not
13073       --  transient. If the enclosing block is the rewriting of a call or the
13074       --  scope is an extended return statement this is valid master. The
13075       --  master in an extended return is only used within the return, and is
13076       --  subsequently overwritten in Move_Activation_Chain, but it must exist
13077       --  now before that overwriting occurs.
13078
13079       S := Scope (E);
13080
13081       if Ada_Version >= Ada_2005 then
13082          while Is_Internal (S) loop
13083             if Nkind (Parent (S)) = N_Block_Statement
13084               and then
13085                 Nkind (Original_Node (Parent (S))) = N_Procedure_Call_Statement
13086             then
13087                exit;
13088
13089             elsif Ekind (S) = E_Return_Statement then
13090                exit;
13091
13092             else
13093                S := Scope (S);
13094             end if;
13095          end loop;
13096       end if;
13097
13098       return S;
13099    end Find_Master_Scope;
13100
13101    -------------------------------
13102    -- First_Protected_Operation --
13103    -------------------------------
13104
13105    function First_Protected_Operation (D : List_Id) return Node_Id is
13106       First_Op : Node_Id;
13107
13108    begin
13109       First_Op := First (D);
13110       while Present (First_Op)
13111         and then not Nkind_In (First_Op, N_Subprogram_Body, N_Entry_Body)
13112       loop
13113          Next (First_Op);
13114       end loop;
13115
13116       return First_Op;
13117    end First_Protected_Operation;
13118
13119    ---------------------------------------
13120    -- Install_Private_Data_Declarations --
13121    ---------------------------------------
13122
13123    procedure Install_Private_Data_Declarations
13124      (Loc      : Source_Ptr;
13125       Spec_Id  : Entity_Id;
13126       Conc_Typ : Entity_Id;
13127       Body_Nod : Node_Id;
13128       Decls    : List_Id;
13129       Barrier  : Boolean := False;
13130       Family   : Boolean := False)
13131    is
13132       Is_Protected : constant Boolean := Is_Protected_Type (Conc_Typ);
13133       Decl         : Node_Id;
13134       Def          : Node_Id;
13135       Insert_Node  : Node_Id := Empty;
13136       Obj_Ent      : Entity_Id;
13137
13138       procedure Add (Decl : Node_Id);
13139       --  Add a single declaration after Insert_Node. If this is the first
13140       --  addition, Decl is added to the front of Decls and it becomes the
13141       --  insertion node.
13142
13143       function Replace_Bound (Bound : Node_Id) return Node_Id;
13144       --  The bounds of an entry index may depend on discriminants, create a
13145       --  reference to the corresponding prival. Otherwise return a duplicate
13146       --  of the original bound.
13147
13148       ---------
13149       -- Add --
13150       ---------
13151
13152       procedure Add (Decl : Node_Id) is
13153       begin
13154          if No (Insert_Node) then
13155             Prepend_To (Decls, Decl);
13156          else
13157             Insert_After (Insert_Node, Decl);
13158          end if;
13159
13160          Insert_Node := Decl;
13161       end Add;
13162
13163       --------------------------
13164       -- Replace_Discriminant --
13165       --------------------------
13166
13167       function Replace_Bound (Bound : Node_Id) return Node_Id is
13168       begin
13169          if Nkind (Bound) = N_Identifier
13170            and then Is_Discriminal (Entity (Bound))
13171          then
13172             return Make_Identifier (Loc, Chars (Entity (Bound)));
13173          else
13174             return Duplicate_Subexpr (Bound);
13175          end if;
13176       end Replace_Bound;
13177
13178    --  Start of processing for Install_Private_Data_Declarations
13179
13180    begin
13181       --  Step 1: Retrieve the concurrent object entity. Obj_Ent can denote
13182       --  formal parameter _O, _object or _task depending on the context.
13183
13184       Obj_Ent := Concurrent_Object (Spec_Id, Conc_Typ);
13185
13186       --  Special processing of _O for barrier functions, protected entries
13187       --  and families.
13188
13189       if Barrier
13190         or else
13191           (Is_Protected
13192              and then
13193                (Ekind (Spec_Id) = E_Entry
13194                   or else Ekind (Spec_Id) = E_Entry_Family))
13195       then
13196          declare
13197             Conc_Rec : constant Entity_Id :=
13198                          Corresponding_Record_Type (Conc_Typ);
13199             Typ_Id   : constant Entity_Id :=
13200                          Make_Defining_Identifier (Loc,
13201                            New_External_Name (Chars (Conc_Rec), 'P'));
13202          begin
13203             --  Generate:
13204             --    type prot_typVP is access prot_typV;
13205
13206             Decl :=
13207               Make_Full_Type_Declaration (Loc,
13208                 Defining_Identifier => Typ_Id,
13209                 Type_Definition     =>
13210                   Make_Access_To_Object_Definition (Loc,
13211                     Subtype_Indication =>
13212                       New_Occurrence_Of (Conc_Rec, Loc)));
13213             Add (Decl);
13214
13215             --  Generate:
13216             --    _object : prot_typVP := prot_typV (_O);
13217
13218             Decl :=
13219               Make_Object_Declaration (Loc,
13220                 Defining_Identifier =>
13221                   Make_Defining_Identifier (Loc, Name_uObject),
13222                 Object_Definition   => New_Occurrence_Of (Typ_Id, Loc),
13223                 Expression          =>
13224                   Unchecked_Convert_To (Typ_Id,
13225                     New_Occurrence_Of (Obj_Ent, Loc)));
13226             Add (Decl);
13227
13228             --  Set the reference to the concurrent object
13229
13230             Obj_Ent := Defining_Identifier (Decl);
13231          end;
13232       end if;
13233
13234       --  Step 2: Create the Protection object and build its declaration for
13235       --  any protected entry (family) of subprogram. Note for the lock-free
13236       --  implementation, the Protection object is not needed anymore.
13237
13238       if Is_Protected and then not Uses_Lock_Free (Conc_Typ) then
13239          declare
13240             Prot_Ent : constant Entity_Id := Make_Temporary (Loc, 'R');
13241             Prot_Typ : RE_Id;
13242
13243          begin
13244             Set_Protection_Object (Spec_Id, Prot_Ent);
13245
13246             --  Determine the proper protection type
13247
13248             if Has_Attach_Handler (Conc_Typ)
13249               and then not Restricted_Profile
13250             then
13251                Prot_Typ := RE_Static_Interrupt_Protection;
13252
13253             elsif Has_Interrupt_Handler (Conc_Typ)
13254               and then not Restriction_Active (No_Dynamic_Attachment)
13255             then
13256                Prot_Typ := RE_Dynamic_Interrupt_Protection;
13257
13258             else
13259                case Corresponding_Runtime_Package (Conc_Typ) is
13260                   when System_Tasking_Protected_Objects_Entries =>
13261                      Prot_Typ := RE_Protection_Entries;
13262
13263                   when System_Tasking_Protected_Objects_Single_Entry =>
13264                      Prot_Typ := RE_Protection_Entry;
13265
13266                   when System_Tasking_Protected_Objects =>
13267                      Prot_Typ := RE_Protection;
13268
13269                   when others =>
13270                      raise Program_Error;
13271                end case;
13272             end if;
13273
13274             --  Generate:
13275             --    conc_typR : protection_typ renames _object._object;
13276
13277             Decl :=
13278               Make_Object_Renaming_Declaration (Loc,
13279                 Defining_Identifier => Prot_Ent,
13280                 Subtype_Mark =>
13281                   New_Occurrence_Of (RTE (Prot_Typ), Loc),
13282                 Name =>
13283                   Make_Selected_Component (Loc,
13284                     Prefix        => New_Occurrence_Of (Obj_Ent, Loc),
13285                     Selector_Name => Make_Identifier (Loc, Name_uObject)));
13286             Add (Decl);
13287          end;
13288       end if;
13289
13290       --  Step 3: Add discriminant renamings (if any)
13291
13292       if Has_Discriminants (Conc_Typ) then
13293          declare
13294             D : Entity_Id;
13295
13296          begin
13297             D := First_Discriminant (Conc_Typ);
13298             while Present (D) loop
13299
13300                --  Adjust the source location
13301
13302                Set_Sloc (Discriminal (D), Loc);
13303
13304                --  Generate:
13305                --    discr_name : discr_typ renames _object.discr_name;
13306                --      or
13307                --    discr_name : discr_typ renames _task.discr_name;
13308
13309                Decl :=
13310                  Make_Object_Renaming_Declaration (Loc,
13311                    Defining_Identifier => Discriminal (D),
13312                    Subtype_Mark        => New_Occurrence_Of (Etype (D), Loc),
13313                    Name                =>
13314                      Make_Selected_Component (Loc,
13315                        Prefix        => New_Occurrence_Of (Obj_Ent, Loc),
13316                        Selector_Name => Make_Identifier (Loc, Chars (D))));
13317                Add (Decl);
13318
13319                Next_Discriminant (D);
13320             end loop;
13321          end;
13322       end if;
13323
13324       --  Step 4: Add private component renamings (if any)
13325
13326       if Is_Protected then
13327          Def := Protected_Definition (Parent (Conc_Typ));
13328
13329          if Present (Private_Declarations (Def)) then
13330             declare
13331                Comp    : Node_Id;
13332                Comp_Id : Entity_Id;
13333                Decl_Id : Entity_Id;
13334
13335             begin
13336                Comp := First (Private_Declarations (Def));
13337                while Present (Comp) loop
13338                   if Nkind (Comp) = N_Component_Declaration then
13339                      Comp_Id := Defining_Identifier (Comp);
13340                      Decl_Id :=
13341                        Make_Defining_Identifier (Loc, Chars (Comp_Id));
13342
13343                      --  Minimal decoration
13344
13345                      if Ekind (Spec_Id) = E_Function then
13346                         Set_Ekind (Decl_Id, E_Constant);
13347                      else
13348                         Set_Ekind (Decl_Id, E_Variable);
13349                      end if;
13350
13351                      Set_Prival      (Comp_Id, Decl_Id);
13352                      Set_Prival_Link (Decl_Id, Comp_Id);
13353                      Set_Is_Aliased  (Decl_Id, Is_Aliased (Comp_Id));
13354
13355                      --  Generate:
13356                      --    comp_name : comp_typ renames _object.comp_name;
13357
13358                      Decl :=
13359                        Make_Object_Renaming_Declaration (Loc,
13360                          Defining_Identifier => Decl_Id,
13361                          Subtype_Mark =>
13362                            New_Occurrence_Of (Etype (Comp_Id), Loc),
13363                          Name =>
13364                            Make_Selected_Component (Loc,
13365                              Prefix =>
13366                                New_Occurrence_Of (Obj_Ent, Loc),
13367                              Selector_Name =>
13368                                Make_Identifier (Loc, Chars (Comp_Id))));
13369                      Add (Decl);
13370                   end if;
13371
13372                   Next (Comp);
13373                end loop;
13374             end;
13375          end if;
13376       end if;
13377
13378       --  Step 5: Add the declaration of the entry index and the associated
13379       --  type for barrier functions and entry families.
13380
13381       if (Barrier and Family) or else Ekind (Spec_Id) = E_Entry_Family then
13382          declare
13383             E         : constant Entity_Id := Index_Object (Spec_Id);
13384             Index     : constant Entity_Id :=
13385                           Defining_Identifier
13386                             (Entry_Index_Specification
13387                                (Entry_Body_Formal_Part (Body_Nod)));
13388             Index_Con : constant Entity_Id :=
13389                           Make_Defining_Identifier (Loc, Chars (Index));
13390             High      : Node_Id;
13391             Index_Typ : Entity_Id;
13392             Low       : Node_Id;
13393
13394          begin
13395             --  Minimal decoration
13396
13397             Set_Ekind                (Index_Con, E_Constant);
13398             Set_Entry_Index_Constant (Index, Index_Con);
13399             Set_Discriminal_Link     (Index_Con, Index);
13400
13401             --  Retrieve the bounds of the entry family
13402
13403             High := Type_High_Bound (Etype (Index));
13404             Low  := Type_Low_Bound  (Etype (Index));
13405
13406             --  In the simple case the entry family is given by a subtype
13407             --  mark and the index constant has the same type.
13408
13409             if Is_Entity_Name (Original_Node (
13410                  Discrete_Subtype_Definition (Parent (Index))))
13411             then
13412                Index_Typ := Etype (Index);
13413
13414             --  Otherwise a new subtype declaration is required
13415
13416             else
13417                High := Replace_Bound (High);
13418                Low  := Replace_Bound (Low);
13419
13420                Index_Typ := Make_Temporary (Loc, 'J');
13421
13422                --  Generate:
13423                --    subtype Jnn is <Etype of Index> range Low .. High;
13424
13425                Decl :=
13426                  Make_Subtype_Declaration (Loc,
13427                    Defining_Identifier => Index_Typ,
13428                    Subtype_Indication =>
13429                      Make_Subtype_Indication (Loc,
13430                        Subtype_Mark =>
13431                          New_Occurrence_Of (Base_Type (Etype (Index)), Loc),
13432                        Constraint =>
13433                          Make_Range_Constraint (Loc,
13434                            Range_Expression =>
13435                              Make_Range (Loc, Low, High))));
13436                Add (Decl);
13437             end if;
13438
13439             Set_Etype (Index_Con, Index_Typ);
13440
13441             --  Create the object which designates the index:
13442             --    J : constant Jnn :=
13443             --          Jnn'Val (_E - <index expr> + Jnn'Pos (Jnn'First));
13444             --
13445             --  where Jnn is the subtype created above or the original type of
13446             --  the index, _E is a formal of the protected body subprogram and
13447             --  <index expr> is the index of the first family member.
13448
13449             Decl :=
13450               Make_Object_Declaration (Loc,
13451                 Defining_Identifier => Index_Con,
13452                 Constant_Present => True,
13453                 Object_Definition =>
13454                   New_Occurrence_Of (Index_Typ, Loc),
13455
13456                 Expression =>
13457                   Make_Attribute_Reference (Loc,
13458                     Prefix =>
13459                       New_Occurrence_Of (Index_Typ, Loc),
13460                     Attribute_Name => Name_Val,
13461
13462                     Expressions => New_List (
13463
13464                       Make_Op_Add (Loc,
13465                         Left_Opnd =>
13466                           Make_Op_Subtract (Loc,
13467                             Left_Opnd  => New_Occurrence_Of (E, Loc),
13468                             Right_Opnd =>
13469                               Entry_Index_Expression (Loc,
13470                                 Defining_Identifier (Body_Nod),
13471                                 Empty, Conc_Typ)),
13472
13473                         Right_Opnd =>
13474                           Make_Attribute_Reference (Loc,
13475                             Prefix         =>
13476                               New_Occurrence_Of (Index_Typ, Loc),
13477                             Attribute_Name => Name_Pos,
13478                             Expressions    => New_List (
13479                               Make_Attribute_Reference (Loc,
13480                                 Prefix         =>
13481                                   New_Occurrence_Of (Index_Typ, Loc),
13482                                 Attribute_Name => Name_First)))))));
13483             Add (Decl);
13484          end;
13485       end if;
13486    end Install_Private_Data_Declarations;
13487
13488    -----------------------
13489    -- Is_Exception_Safe --
13490    -----------------------
13491
13492    function Is_Exception_Safe (Subprogram : Node_Id) return Boolean is
13493
13494       function Has_Side_Effect (N : Node_Id) return Boolean;
13495       --  Return True whenever encountering a subprogram call or raise
13496       --  statement of any kind in the sequence of statements
13497
13498       ---------------------
13499       -- Has_Side_Effect --
13500       ---------------------
13501
13502       --  What is this doing buried two levels down in exp_ch9. It seems like a
13503       --  generally useful function, and indeed there may be code duplication
13504       --  going on here ???
13505
13506       function Has_Side_Effect (N : Node_Id) return Boolean is
13507          Stmt : Node_Id;
13508          Expr : Node_Id;
13509
13510          function Is_Call_Or_Raise (N : Node_Id) return Boolean;
13511          --  Indicate whether N is a subprogram call or a raise statement
13512
13513          ----------------------
13514          -- Is_Call_Or_Raise --
13515          ----------------------
13516
13517          function Is_Call_Or_Raise (N : Node_Id) return Boolean is
13518          begin
13519             return Nkind_In (N, N_Procedure_Call_Statement,
13520                                 N_Function_Call,
13521                                 N_Raise_Statement,
13522                                 N_Raise_Constraint_Error,
13523                                 N_Raise_Program_Error,
13524                                 N_Raise_Storage_Error);
13525          end Is_Call_Or_Raise;
13526
13527       --  Start of processing for Has_Side_Effect
13528
13529       begin
13530          Stmt := N;
13531          while Present (Stmt) loop
13532             if Is_Call_Or_Raise (Stmt) then
13533                return True;
13534             end if;
13535
13536             --  An object declaration can also contain a function call or a
13537             --  raise statement.
13538
13539             if Nkind (Stmt) = N_Object_Declaration then
13540                Expr := Expression (Stmt);
13541
13542                if Present (Expr) and then Is_Call_Or_Raise (Expr) then
13543                   return True;
13544                end if;
13545             end if;
13546
13547             Next (Stmt);
13548          end loop;
13549
13550          return False;
13551       end Has_Side_Effect;
13552
13553    --  Start of processing for Is_Exception_Safe
13554
13555    begin
13556       --  When exceptions can't be propagated, the subprogram returns normally
13557
13558       if No_Exception_Handlers_Set then
13559          return True;
13560       end if;
13561
13562       --  If the checks handled by the back end are not disabled, we cannot
13563       --  ensure that no exception will be raised.
13564
13565       if not Access_Checks_Suppressed (Empty)
13566         or else not Discriminant_Checks_Suppressed (Empty)
13567         or else not Range_Checks_Suppressed (Empty)
13568         or else not Index_Checks_Suppressed (Empty)
13569         or else Opt.Stack_Checking_Enabled
13570       then
13571          return False;
13572       end if;
13573
13574       if Has_Side_Effect (First (Declarations (Subprogram)))
13575         or else
13576           Has_Side_Effect
13577             (First (Statements (Handled_Statement_Sequence (Subprogram))))
13578       then
13579          return False;
13580       else
13581          return True;
13582       end if;
13583    end Is_Exception_Safe;
13584
13585    ---------------------------------
13586    -- Is_Potentially_Large_Family --
13587    ---------------------------------
13588
13589    function Is_Potentially_Large_Family
13590      (Base_Index : Entity_Id;
13591       Conctyp    : Entity_Id;
13592       Lo         : Node_Id;
13593       Hi         : Node_Id) return Boolean
13594    is
13595    begin
13596       return Scope (Base_Index) = Standard_Standard
13597         and then Base_Index = Base_Type (Standard_Integer)
13598         and then Has_Discriminants (Conctyp)
13599         and then
13600           Present (Discriminant_Default_Value (First_Discriminant (Conctyp)))
13601         and then
13602           (Denotes_Discriminant (Lo, True)
13603              or else
13604            Denotes_Discriminant (Hi, True));
13605    end Is_Potentially_Large_Family;
13606
13607    -------------------------------------
13608    -- Is_Private_Primitive_Subprogram --
13609    -------------------------------------
13610
13611    function Is_Private_Primitive_Subprogram (Id : Entity_Id) return Boolean is
13612    begin
13613       return
13614         (Ekind (Id) = E_Function or else Ekind (Id) = E_Procedure)
13615           and then Is_Private_Primitive (Id);
13616    end Is_Private_Primitive_Subprogram;
13617
13618    ------------------
13619    -- Index_Object --
13620    ------------------
13621
13622    function Index_Object (Spec_Id : Entity_Id) return Entity_Id is
13623       Bod_Subp : constant Entity_Id := Protected_Body_Subprogram (Spec_Id);
13624       Formal   : Entity_Id;
13625
13626    begin
13627       Formal := First_Formal (Bod_Subp);
13628       while Present (Formal) loop
13629
13630          --  Look for formal parameter _E
13631
13632          if Chars (Formal) = Name_uE then
13633             return Formal;
13634          end if;
13635
13636          Next_Formal (Formal);
13637       end loop;
13638
13639       --  A protected body subprogram should always have the parameter in
13640       --  question.
13641
13642       raise Program_Error;
13643    end Index_Object;
13644
13645    --------------------------------
13646    -- Make_Initialize_Protection --
13647    --------------------------------
13648
13649    function Make_Initialize_Protection
13650      (Protect_Rec : Entity_Id) return List_Id
13651    is
13652       Loc         : constant Source_Ptr := Sloc (Protect_Rec);
13653       P_Arr       : Entity_Id;
13654       Pdec        : Node_Id;
13655       Ptyp        : constant Node_Id    :=
13656                       Corresponding_Concurrent_Type (Protect_Rec);
13657       Args        : List_Id;
13658       L           : constant List_Id    := New_List;
13659       Has_Entry   : constant Boolean    := Has_Entries (Ptyp);
13660       Prio_Type   : Entity_Id;
13661       Prio_Var    : Entity_Id           := Empty;
13662       Restricted  : constant Boolean    := Restricted_Profile;
13663
13664    begin
13665       --  We may need two calls to properly initialize the object, one to
13666       --  Initialize_Protection, and possibly one to Install_Handlers if we
13667       --  have a pragma Attach_Handler.
13668
13669       --  Get protected declaration. In the case of a task type declaration,
13670       --  this is simply the parent of the protected type entity. In the single
13671       --  protected object declaration, this parent will be the implicit type,
13672       --  and we can find the corresponding single protected object declaration
13673       --  by searching forward in the declaration list in the tree.
13674
13675       --  Is the test for N_Single_Protected_Declaration needed here??? Nodes
13676       --  of this type should have been removed during semantic analysis.
13677
13678       Pdec := Parent (Ptyp);
13679       while not Nkind_In (Pdec, N_Protected_Type_Declaration,
13680                                 N_Single_Protected_Declaration)
13681       loop
13682          Next (Pdec);
13683       end loop;
13684
13685       --  Build the parameter list for the call. Note that _Init is the name
13686       --  of the formal for the object to be initialized, which is the task
13687       --  value record itself.
13688
13689       Args := New_List;
13690
13691       --  For lock-free implementation, skip initializations of the Protection
13692       --  object.
13693
13694       if not Uses_Lock_Free (Defining_Identifier (Pdec)) then
13695
13696          --  Object parameter. This is a pointer to the object of type
13697          --  Protection used by the GNARL to control the protected object.
13698
13699          Append_To (Args,
13700            Make_Attribute_Reference (Loc,
13701              Prefix =>
13702                Make_Selected_Component (Loc,
13703                  Prefix        => Make_Identifier (Loc, Name_uInit),
13704                  Selector_Name => Make_Identifier (Loc, Name_uObject)),
13705              Attribute_Name => Name_Unchecked_Access));
13706
13707          --  Priority parameter. Set to Unspecified_Priority unless there is a
13708          --  Priority rep item, in which case we take the value from the pragma
13709          --  or attribute definition clause, or there is an Interrupt_Priority
13710          --  rep item and no Priority rep item, and we set the ceiling to
13711          --  Interrupt_Priority'Last, an implementation-defined value, see
13712          --  (RM D.3(10)).
13713
13714          if Has_Rep_Item (Ptyp, Name_Priority, Check_Parents => False) then
13715             declare
13716                Prio_Clause : constant Node_Id :=
13717                                Get_Rep_Item
13718                                  (Ptyp, Name_Priority, Check_Parents => False);
13719
13720                Prio : Node_Id;
13721
13722             begin
13723                --  Pragma Priority
13724
13725                if Nkind (Prio_Clause) = N_Pragma then
13726                   Prio :=
13727                     Expression
13728                      (First (Pragma_Argument_Associations (Prio_Clause)));
13729
13730                   --  Get_Rep_Item returns either priority pragma.
13731
13732                   if Pragma_Name (Prio_Clause) = Name_Priority then
13733                      Prio_Type := RTE (RE_Any_Priority);
13734                   else
13735                      Prio_Type := RTE (RE_Interrupt_Priority);
13736                   end if;
13737
13738                --  Attribute definition clause Priority
13739
13740                else
13741                   if Chars (Prio_Clause) = Name_Priority then
13742                      Prio_Type := RTE (RE_Any_Priority);
13743                   else
13744                      Prio_Type := RTE (RE_Interrupt_Priority);
13745                   end if;
13746
13747                   Prio := Expression (Prio_Clause);
13748                end if;
13749
13750                --  Always create a locale variable to capture the priority.
13751                --  The priority is also passed to Install_Restriced_Handlers.
13752                --  Note that it is really necessary to create this variable
13753                --  explicitly. It might be thought that removing side effects
13754                --  would the appropriate approach, but that could generate
13755                --  declarations improperly placed in the enclosing scope.
13756
13757                Prio_Var := Make_Temporary (Loc, 'R', Prio);
13758                Append_To (L,
13759                  Make_Object_Declaration (Loc,
13760                    Defining_Identifier => Prio_Var,
13761                    Object_Definition   => New_Occurrence_Of (Prio_Type,  Loc),
13762                    Expression          => Relocate_Node (Prio)));
13763
13764                Append_To (Args, New_Occurrence_Of (Prio_Var, Loc));
13765             end;
13766
13767          --  When no priority is specified but an xx_Handler pragma is, we
13768          --  default to System.Interrupts.Default_Interrupt_Priority, see
13769          --  D.3(10).
13770
13771          elsif Has_Attach_Handler (Ptyp)
13772            or else Has_Interrupt_Handler (Ptyp)
13773          then
13774             Append_To (Args,
13775               New_Occurrence_Of (RTE (RE_Default_Interrupt_Priority), Loc));
13776
13777          --  Normal case, no priority or xx_Handler specified, default priority
13778
13779          else
13780             Append_To (Args,
13781               New_Occurrence_Of (RTE (RE_Unspecified_Priority), Loc));
13782          end if;
13783
13784          --  Test for Compiler_Info parameter. This parameter allows entry body
13785          --  procedures and barrier functions to be called from the runtime. It
13786          --  is a pointer to the record generated by the compiler to represent
13787          --  the protected object.
13788
13789          --  A protected type without entries that covers an interface and
13790          --  overrides the abstract routines with protected procedures is
13791          --  considered equivalent to a protected type with entries in the
13792          --  context of dispatching select statements.
13793
13794          --  Protected types with interrupt handlers (when not using a
13795          --  restricted profile) are also considered equivalent to protected
13796          --  types with entries.
13797
13798          --  The types which are used (Static_Interrupt_Protection and
13799          --  Dynamic_Interrupt_Protection) are derived from Protection_Entries.
13800
13801          declare
13802             Pkg_Id : constant RTU_Id := Corresponding_Runtime_Package (Ptyp);
13803
13804             Called_Subp : RE_Id;
13805
13806          begin
13807             case Pkg_Id is
13808                when System_Tasking_Protected_Objects_Entries =>
13809                   Called_Subp := RE_Initialize_Protection_Entries;
13810
13811                   --  Argument Compiler_Info
13812
13813                   Append_To (Args,
13814                     Make_Attribute_Reference (Loc,
13815                       Prefix         => Make_Identifier (Loc, Name_uInit),
13816                       Attribute_Name => Name_Address));
13817
13818                when System_Tasking_Protected_Objects_Single_Entry =>
13819                   Called_Subp := RE_Initialize_Protection_Entry;
13820
13821                   --  Argument Compiler_Info
13822
13823                   Append_To (Args,
13824                     Make_Attribute_Reference (Loc,
13825                       Prefix         => Make_Identifier (Loc, Name_uInit),
13826                       Attribute_Name => Name_Address));
13827
13828                when System_Tasking_Protected_Objects =>
13829                   Called_Subp := RE_Initialize_Protection;
13830
13831                when others =>
13832                      raise Program_Error;
13833             end case;
13834
13835             --  Entry_Bodies parameter. This is a pointer to an array of
13836             --  pointers to the entry body procedures and barrier functions of
13837             --  the object. If the protected type has no entries this object
13838             --  will not exist, in this case, pass a null (it can happen when
13839             --  there are protected interrupt handlers or interfaces).
13840
13841             if Has_Entry then
13842                P_Arr := Entry_Bodies_Array (Ptyp);
13843
13844                --  Argument Entry_Body (for single entry) or Entry_Bodies (for
13845                --  multiple entries).
13846
13847                Append_To (Args,
13848                  Make_Attribute_Reference (Loc,
13849                    Prefix         => New_Occurrence_Of (P_Arr, Loc),
13850                    Attribute_Name => Name_Unrestricted_Access));
13851
13852                if Pkg_Id = System_Tasking_Protected_Objects_Entries then
13853
13854                   --  Find index mapping function (clumsy but ok for now)
13855
13856                   while Ekind (P_Arr) /= E_Function loop
13857                      Next_Entity (P_Arr);
13858                   end loop;
13859
13860                   Append_To (Args,
13861                     Make_Attribute_Reference (Loc,
13862                       Prefix         => New_Occurrence_Of (P_Arr, Loc),
13863                       Attribute_Name => Name_Unrestricted_Access));
13864                end if;
13865
13866             elsif Pkg_Id = System_Tasking_Protected_Objects_Single_Entry then
13867
13868                --  This is the case where we have a protected object with
13869                --  interfaces and no entries, and the single entry restriction
13870                --  is in effect. We pass a null pointer for the entry
13871                --  parameter because there is no actual entry.
13872
13873                Append_To (Args, Make_Null (Loc));
13874
13875             elsif Pkg_Id = System_Tasking_Protected_Objects_Entries then
13876
13877                --  This is the case where we have a protected object with no
13878                --  entries and:
13879                --    - either interrupt handlers with non restricted profile,
13880                --    - or interfaces
13881                --  Note that the types which are used for interrupt handlers
13882                --  (Static/Dynamic_Interrupt_Protection) are derived from
13883                --  Protection_Entries. We pass two null pointers because there
13884                --  is no actual entry, and the initialization procedure needs
13885                --  both Entry_Bodies and Find_Body_Index.
13886
13887                Append_To (Args, Make_Null (Loc));
13888                Append_To (Args, Make_Null (Loc));
13889             end if;
13890
13891             Append_To (L,
13892               Make_Procedure_Call_Statement (Loc,
13893                 Name                   =>
13894                   New_Occurrence_Of (RTE (Called_Subp), Loc),
13895                 Parameter_Associations => Args));
13896          end;
13897       end if;
13898
13899       if Has_Attach_Handler (Ptyp) then
13900
13901          --  We have a list of N Attach_Handler (ProcI, ExprI), and we have to
13902          --  make the following call:
13903
13904          --  Install_Handlers (_object,
13905          --    ((Expr1, Proc1'access), ...., (ExprN, ProcN'access));
13906
13907          --  or, in the case of Ravenscar:
13908
13909          --  Install_Restricted_Handlers
13910          --    (Prio, (Expr1, Proc1'access), ...., (ExprN, ProcN'access));
13911
13912          declare
13913             Args  : constant List_Id := New_List;
13914             Table : constant List_Id := New_List;
13915             Ritem : Node_Id          := First_Rep_Item (Ptyp);
13916
13917          begin
13918             --  Build the Priority parameter (only for ravenscar)
13919
13920             if Restricted then
13921
13922                --  Priority comes from a pragma
13923
13924                if Present (Prio_Var) then
13925                   Append_To (Args, New_Occurrence_Of (Prio_Var, Loc));
13926
13927                --  Priority is the default one
13928
13929                else
13930                   Append_To (Args,
13931                     New_Occurrence_Of
13932                       (RTE (RE_Default_Interrupt_Priority), Loc));
13933                end if;
13934             end if;
13935
13936             --  Build the Attach_Handler table argument
13937
13938             while Present (Ritem) loop
13939                if Nkind (Ritem) = N_Pragma
13940                  and then Pragma_Name (Ritem) = Name_Attach_Handler
13941                then
13942                   declare
13943                      Handler : constant Node_Id :=
13944                                  First (Pragma_Argument_Associations (Ritem));
13945
13946                      Interrupt : constant Node_Id := Next (Handler);
13947                      Expr      : constant Node_Id := Expression (Interrupt);
13948
13949                   begin
13950                      Append_To (Table,
13951                        Make_Aggregate (Loc, Expressions => New_List (
13952                          Unchecked_Convert_To
13953                           (RTE (RE_System_Interrupt_Id), Expr),
13954                          Make_Attribute_Reference (Loc,
13955                            Prefix         =>
13956                              Make_Selected_Component (Loc,
13957                                Prefix        =>
13958                                  Make_Identifier (Loc, Name_uInit),
13959                                Selector_Name =>
13960                                  Duplicate_Subexpr_No_Checks
13961                                    (Expression (Handler))),
13962                            Attribute_Name => Name_Access))));
13963                   end;
13964                end if;
13965
13966                Next_Rep_Item (Ritem);
13967             end loop;
13968
13969             --  Append the table argument we just built
13970
13971             Append_To (Args, Make_Aggregate (Loc, Table));
13972
13973             --  Append the Install_Handlers (or Install_Restricted_Handlers)
13974             --  call to the statements.
13975
13976             if Restricted then
13977                --  Call a simplified version of Install_Handlers to be used
13978                --  when the Ravenscar restrictions are in effect
13979                --  (Install_Restricted_Handlers).
13980
13981                Append_To (L,
13982                  Make_Procedure_Call_Statement (Loc,
13983                    Name =>
13984                      New_Occurrence_Of
13985                        (RTE (RE_Install_Restricted_Handlers), Loc),
13986                    Parameter_Associations => Args));
13987
13988             else
13989                if not Uses_Lock_Free (Defining_Identifier (Pdec)) then
13990
13991                   --  First, prepends the _object argument
13992
13993                   Prepend_To (Args,
13994                     Make_Attribute_Reference (Loc,
13995                       Prefix         =>
13996                         Make_Selected_Component (Loc,
13997                           Prefix        => Make_Identifier (Loc, Name_uInit),
13998                           Selector_Name =>
13999                             Make_Identifier (Loc, Name_uObject)),
14000                       Attribute_Name => Name_Unchecked_Access));
14001                end if;
14002
14003                --  Then, insert call to Install_Handlers
14004
14005                Append_To (L,
14006                  Make_Procedure_Call_Statement (Loc,
14007                    Name                   =>
14008                      New_Occurrence_Of (RTE (RE_Install_Handlers), Loc),
14009                    Parameter_Associations => Args));
14010             end if;
14011          end;
14012       end if;
14013
14014       return L;
14015    end Make_Initialize_Protection;
14016
14017    ---------------------------
14018    -- Make_Task_Create_Call --
14019    ---------------------------
14020
14021    function Make_Task_Create_Call (Task_Rec : Entity_Id) return Node_Id is
14022       Loc    : constant Source_Ptr := Sloc (Task_Rec);
14023       Args   : List_Id;
14024       Ecount : Node_Id;
14025       Name   : Node_Id;
14026       Tdec   : Node_Id;
14027       Tdef   : Node_Id;
14028       Tnam   : Name_Id;
14029       Ttyp   : Node_Id;
14030
14031    begin
14032       Ttyp := Corresponding_Concurrent_Type (Task_Rec);
14033       Tnam := Chars (Ttyp);
14034
14035       --  Get task declaration. In the case of a task type declaration, this is
14036       --  simply the parent of the task type entity. In the single task
14037       --  declaration, this parent will be the implicit type, and we can find
14038       --  the corresponding single task declaration by searching forward in the
14039       --  declaration list in the tree.
14040
14041       --  Is the test for N_Single_Task_Declaration needed here??? Nodes of
14042       --  this type should have been removed during semantic analysis.
14043
14044       Tdec := Parent (Ttyp);
14045       while not Nkind_In (Tdec, N_Task_Type_Declaration,
14046                                 N_Single_Task_Declaration)
14047       loop
14048          Next (Tdec);
14049       end loop;
14050
14051       --  Now we can find the task definition from this declaration
14052
14053       Tdef := Task_Definition (Tdec);
14054
14055       --  Build the parameter list for the call. Note that _Init is the name
14056       --  of the formal for the object to be initialized, which is the task
14057       --  value record itself.
14058
14059       Args := New_List;
14060
14061       --  Priority parameter. Set to Unspecified_Priority unless there is a
14062       --  Priority rep item, in which case we take the value from the rep item.
14063
14064       if Has_Rep_Item (Ttyp, Name_Priority, Check_Parents => False) then
14065          Append_To (Args,
14066            Make_Selected_Component (Loc,
14067              Prefix        => Make_Identifier (Loc, Name_uInit),
14068              Selector_Name => Make_Identifier (Loc, Name_uPriority)));
14069       else
14070          Append_To (Args,
14071            New_Occurrence_Of (RTE (RE_Unspecified_Priority), Loc));
14072       end if;
14073
14074       --  Optional Stack parameter
14075
14076       if Restricted_Profile then
14077
14078          --  If the stack has been preallocated by the expander then
14079          --  pass its address. Otherwise, pass a null address.
14080
14081          if Preallocated_Stacks_On_Target then
14082             Append_To (Args,
14083               Make_Attribute_Reference (Loc,
14084                 Prefix         =>
14085                   Make_Selected_Component (Loc,
14086                     Prefix        => Make_Identifier (Loc, Name_uInit),
14087                     Selector_Name => Make_Identifier (Loc, Name_uStack)),
14088                 Attribute_Name => Name_Address));
14089
14090          else
14091             Append_To (Args,
14092               New_Occurrence_Of (RTE (RE_Null_Address), Loc));
14093          end if;
14094       end if;
14095
14096       --  Size parameter. If no Storage_Size pragma is present, then
14097       --  the size is taken from the taskZ variable for the type, which
14098       --  is either Unspecified_Size, or has been reset by the use of
14099       --  a Storage_Size attribute definition clause. If a pragma is
14100       --  present, then the size is taken from the _Size field of the
14101       --  task value record, which was set from the pragma value.
14102
14103       if Present (Tdef) and then Has_Storage_Size_Pragma (Tdef) then
14104          Append_To (Args,
14105            Make_Selected_Component (Loc,
14106              Prefix        => Make_Identifier (Loc, Name_uInit),
14107              Selector_Name => Make_Identifier (Loc, Name_uSize)));
14108
14109       else
14110          Append_To (Args,
14111            New_Occurrence_Of (Storage_Size_Variable (Ttyp), Loc));
14112       end if;
14113
14114       --  Task_Info parameter. Set to Unspecified_Task_Info unless there is a
14115       --  Task_Info pragma, in which case we take the value from the pragma.
14116
14117       if Has_Rep_Pragma (Ttyp, Name_Task_Info, Check_Parents => False) then
14118          Append_To (Args,
14119            Make_Selected_Component (Loc,
14120              Prefix        => Make_Identifier (Loc, Name_uInit),
14121              Selector_Name => Make_Identifier (Loc, Name_uTask_Info)));
14122
14123       else
14124          Append_To (Args,
14125            New_Occurrence_Of (RTE (RE_Unspecified_Task_Info), Loc));
14126       end if;
14127
14128       --  CPU parameter. Set to Unspecified_CPU unless there is a CPU rep item,
14129       --  in which case we take the value from the rep item. The parameter is
14130       --  passed as an Integer because in the case of unspecified CPU the
14131       --  value is not in the range of CPU_Range.
14132
14133       if Has_Rep_Item (Ttyp, Name_CPU, Check_Parents => False) then
14134          Append_To (Args,
14135            Convert_To (Standard_Integer,
14136              Make_Selected_Component (Loc,
14137                Prefix        => Make_Identifier (Loc, Name_uInit),
14138                Selector_Name => Make_Identifier (Loc, Name_uCPU))));
14139       else
14140          Append_To (Args,
14141            New_Occurrence_Of (RTE (RE_Unspecified_CPU), Loc));
14142       end if;
14143
14144       if not Restricted_Profile then
14145
14146          --  Deadline parameter. If no Relative_Deadline pragma is present,
14147          --  then the deadline is Time_Span_Zero. If a pragma is present, then
14148          --  the deadline is taken from the _Relative_Deadline field of the
14149          --  task value record, which was set from the pragma value. Note that
14150          --  this parameter must not be generated for the restricted profiles
14151          --  since Ravenscar does not allow deadlines.
14152
14153          --  Case where pragma Relative_Deadline applies: use given value
14154
14155          if Present (Tdef) and then Has_Relative_Deadline_Pragma (Tdef) then
14156             Append_To (Args,
14157               Make_Selected_Component (Loc,
14158                 Prefix        => Make_Identifier (Loc, Name_uInit),
14159                 Selector_Name =>
14160                   Make_Identifier (Loc, Name_uRelative_Deadline)));
14161
14162          --  No pragma Relative_Deadline apply to the task
14163
14164          else
14165             Append_To (Args,
14166               New_Occurrence_Of (RTE (RE_Time_Span_Zero), Loc));
14167          end if;
14168
14169          --  Dispatching_Domain parameter. If no Dispatching_Domain rep item is
14170          --  present, then the dispatching domain is null. If a rep item is
14171          --  present, then the dispatching domain is taken from the
14172          --  _Dispatching_Domain field of the task value record, which was set
14173          --  from the rep item value.
14174
14175          --  Case where Dispatching_Domain rep item applies: use given value
14176
14177          if Has_Rep_Item
14178               (Ttyp, Name_Dispatching_Domain, Check_Parents => False)
14179          then
14180             Append_To (Args,
14181               Make_Selected_Component (Loc,
14182                 Prefix        =>
14183                   Make_Identifier (Loc, Name_uInit),
14184                 Selector_Name =>
14185                   Make_Identifier (Loc, Name_uDispatching_Domain)));
14186
14187          --  No pragma or aspect Dispatching_Domain applies to the task
14188
14189          else
14190             Append_To (Args, Make_Null (Loc));
14191          end if;
14192
14193          --  Number of entries. This is an expression of the form:
14194
14195          --    n + _Init.a'Length + _Init.a'B'Length + ...
14196
14197          --  where a,b... are the entry family names for the task definition
14198
14199          Ecount :=
14200            Build_Entry_Count_Expression
14201              (Ttyp,
14202               Component_Items
14203                 (Component_List
14204                    (Type_Definition
14205                       (Parent (Corresponding_Record_Type (Ttyp))))),
14206               Loc);
14207          Append_To (Args, Ecount);
14208
14209          --  Master parameter. This is a reference to the _Master parameter of
14210          --  the initialization procedure, except in the case of the pragma
14211          --  Restrictions (No_Task_Hierarchy) where the value is fixed to
14212          --  System.Tasking.Library_Task_Level.
14213
14214          if Restriction_Active (No_Task_Hierarchy) = False then
14215             Append_To (Args, Make_Identifier (Loc, Name_uMaster));
14216          else
14217             Append_To (Args,
14218               New_Occurrence_Of (RTE (RE_Library_Task_Level), Loc));
14219          end if;
14220       end if;
14221
14222       --  State parameter. This is a pointer to the task body procedure. The
14223       --  required value is obtained by taking 'Unrestricted_Access of the task
14224       --  body procedure and converting it (with an unchecked conversion) to
14225       --  the type required by the task kernel. For further details, see the
14226       --  description of Expand_N_Task_Body. We use 'Unrestricted_Access rather
14227       --  than 'Address in order to avoid creating trampolines.
14228
14229       declare
14230          Body_Proc    : constant Node_Id := Get_Task_Body_Procedure (Ttyp);
14231          Subp_Ptr_Typ : constant Node_Id :=
14232                           Create_Itype (E_Access_Subprogram_Type, Tdec);
14233          Ref          : constant Node_Id := Make_Itype_Reference (Loc);
14234
14235       begin
14236          Set_Directly_Designated_Type (Subp_Ptr_Typ, Body_Proc);
14237          Set_Etype (Subp_Ptr_Typ, Subp_Ptr_Typ);
14238
14239          --  Be sure to freeze a reference to the access-to-subprogram type,
14240          --  otherwise gigi will complain that it's in the wrong scope, because
14241          --  it's actually inside the init procedure for the record type that
14242          --  corresponds to the task type.
14243
14244          Set_Itype (Ref, Subp_Ptr_Typ);
14245          Append_Freeze_Action (Task_Rec, Ref);
14246
14247          Append_To (Args,
14248            Unchecked_Convert_To (RTE (RE_Task_Procedure_Access),
14249              Make_Qualified_Expression (Loc,
14250                Subtype_Mark => New_Occurrence_Of (Subp_Ptr_Typ, Loc),
14251                Expression   =>
14252                  Make_Attribute_Reference (Loc,
14253                    Prefix         => New_Occurrence_Of (Body_Proc, Loc),
14254                    Attribute_Name => Name_Unrestricted_Access))));
14255       end;
14256
14257       --  Discriminants parameter. This is just the address of the task
14258       --  value record itself (which contains the discriminant values
14259
14260       Append_To (Args,
14261         Make_Attribute_Reference (Loc,
14262           Prefix => Make_Identifier (Loc, Name_uInit),
14263           Attribute_Name => Name_Address));
14264
14265       --  Elaborated parameter. This is an access to the elaboration Boolean
14266
14267       Append_To (Args,
14268         Make_Attribute_Reference (Loc,
14269           Prefix => Make_Identifier (Loc, New_External_Name (Tnam, 'E')),
14270           Attribute_Name => Name_Unchecked_Access));
14271
14272       --  Add Chain parameter (not done for sequential elaboration policy, see
14273       --  comment for Create_Restricted_Task_Sequential in s-tarest.ads).
14274
14275       if Partition_Elaboration_Policy /= 'S' then
14276          Append_To (Args, Make_Identifier (Loc, Name_uChain));
14277       end if;
14278
14279       --  Task name parameter. Take this from the _Task_Id parameter to the
14280       --  init call unless there is a Task_Name pragma, in which case we take
14281       --  the value from the pragma.
14282
14283       if Has_Rep_Pragma (Ttyp, Name_Task_Name, Check_Parents => False) then
14284          --  Copy expression in full, because it may be dynamic and have
14285          --  side effects.
14286
14287          Append_To (Args,
14288            New_Copy_Tree
14289              (Expression
14290                (First
14291                  (Pragma_Argument_Associations
14292                    (Get_Rep_Pragma
14293                      (Ttyp, Name_Task_Name, Check_Parents => False))))));
14294
14295       else
14296          Append_To (Args, Make_Identifier (Loc, Name_uTask_Name));
14297       end if;
14298
14299       --  Created_Task parameter. This is the _Task_Id field of the task
14300       --  record value
14301
14302       Append_To (Args,
14303         Make_Selected_Component (Loc,
14304           Prefix        => Make_Identifier (Loc, Name_uInit),
14305           Selector_Name => Make_Identifier (Loc, Name_uTask_Id)));
14306
14307       declare
14308          Create_RE : RE_Id;
14309
14310       begin
14311          if Restricted_Profile then
14312             if Partition_Elaboration_Policy = 'S' then
14313                Create_RE := RE_Create_Restricted_Task_Sequential;
14314             else
14315                Create_RE := RE_Create_Restricted_Task;
14316             end if;
14317          else
14318             Create_RE := RE_Create_Task;
14319          end if;
14320
14321          Name := New_Occurrence_Of (RTE (Create_RE), Loc);
14322       end;
14323
14324       return
14325         Make_Procedure_Call_Statement (Loc,
14326           Name                   => Name,
14327           Parameter_Associations => Args);
14328    end Make_Task_Create_Call;
14329
14330    ------------------------------
14331    -- Next_Protected_Operation --
14332    ------------------------------
14333
14334    function Next_Protected_Operation (N : Node_Id) return Node_Id is
14335       Next_Op : Node_Id;
14336
14337    begin
14338       --  Check whether there is a subsequent body for a protected operation
14339       --  in the current protected body. In Ada2012 that includes expression
14340       --  functions that are completions.
14341
14342       Next_Op := Next (N);
14343       while Present (Next_Op)
14344         and then not Nkind_In (Next_Op,
14345            N_Subprogram_Body, N_Entry_Body, N_Expression_Function)
14346       loop
14347          Next (Next_Op);
14348       end loop;
14349
14350       return Next_Op;
14351    end Next_Protected_Operation;
14352
14353    ---------------------
14354    -- Null_Statements --
14355    ---------------------
14356
14357    function Null_Statements (Stats : List_Id) return Boolean is
14358       Stmt : Node_Id;
14359
14360    begin
14361       Stmt := First (Stats);
14362       while Nkind (Stmt) /= N_Empty
14363         and then (Nkind_In (Stmt, N_Null_Statement, N_Label)
14364                    or else
14365                      (Nkind (Stmt) = N_Pragma
14366                        and then
14367                          Nam_In (Pragma_Name (Stmt), Name_Unreferenced,
14368                                                      Name_Unmodified,
14369                                                      Name_Warnings)))
14370       loop
14371          Next (Stmt);
14372       end loop;
14373
14374       return Nkind (Stmt) = N_Empty;
14375    end Null_Statements;
14376
14377    --------------------------
14378    -- Parameter_Block_Pack --
14379    --------------------------
14380
14381    function Parameter_Block_Pack
14382      (Loc     : Source_Ptr;
14383       Blk_Typ : Entity_Id;
14384       Actuals : List_Id;
14385       Formals : List_Id;
14386       Decls   : List_Id;
14387       Stmts   : List_Id) return Node_Id
14388    is
14389       Actual    : Entity_Id;
14390       Expr      : Node_Id := Empty;
14391       Formal    : Entity_Id;
14392       Has_Param : Boolean := False;
14393       P         : Entity_Id;
14394       Params    : List_Id;
14395       Temp_Asn  : Node_Id;
14396       Temp_Nam  : Node_Id;
14397
14398    begin
14399       Actual := First (Actuals);
14400       Formal := Defining_Identifier (First (Formals));
14401       Params := New_List;
14402       while Present (Actual) loop
14403          if Is_By_Copy_Type (Etype (Actual)) then
14404             --  Generate:
14405             --    Jnn : aliased <formal-type>
14406
14407             Temp_Nam := Make_Temporary (Loc, 'J');
14408
14409             Append_To (Decls,
14410               Make_Object_Declaration (Loc,
14411                 Aliased_Present     => True,
14412                 Defining_Identifier => Temp_Nam,
14413                 Object_Definition   =>
14414                   New_Occurrence_Of (Etype (Formal), Loc)));
14415
14416             if Ekind (Formal) /= E_Out_Parameter then
14417
14418                --  Generate:
14419                --    Jnn := <actual>
14420
14421                Temp_Asn :=
14422                  New_Occurrence_Of (Temp_Nam, Loc);
14423
14424                Set_Assignment_OK (Temp_Asn);
14425
14426                Append_To (Stmts,
14427                  Make_Assignment_Statement (Loc,
14428                    Name       => Temp_Asn,
14429                    Expression => New_Copy_Tree (Actual)));
14430             end if;
14431
14432             --  Generate:
14433             --    Jnn'unchecked_access
14434
14435             Append_To (Params,
14436               Make_Attribute_Reference (Loc,
14437                 Attribute_Name => Name_Unchecked_Access,
14438                 Prefix         => New_Occurrence_Of (Temp_Nam, Loc)));
14439
14440             Has_Param := True;
14441
14442          --  The controlling parameter is omitted
14443
14444          else
14445             if not Is_Controlling_Actual (Actual) then
14446                Append_To (Params,
14447                  Make_Reference (Loc, New_Copy_Tree (Actual)));
14448
14449                Has_Param := True;
14450             end if;
14451          end if;
14452
14453          Next_Actual (Actual);
14454          Next_Formal_With_Extras (Formal);
14455       end loop;
14456
14457       if Has_Param then
14458          Expr := Make_Aggregate (Loc, Params);
14459       end if;
14460
14461       --  Generate:
14462       --    P : Ann := (
14463       --      J1'unchecked_access;
14464       --      <actual2>'reference;
14465       --      ...);
14466
14467       P := Make_Temporary (Loc, 'P');
14468
14469       Append_To (Decls,
14470         Make_Object_Declaration (Loc,
14471           Defining_Identifier => P,
14472           Object_Definition   => New_Occurrence_Of (Blk_Typ, Loc),
14473           Expression          => Expr));
14474
14475       return P;
14476    end Parameter_Block_Pack;
14477
14478    ----------------------------
14479    -- Parameter_Block_Unpack --
14480    ----------------------------
14481
14482    function Parameter_Block_Unpack
14483      (Loc     : Source_Ptr;
14484       P       : Entity_Id;
14485       Actuals : List_Id;
14486       Formals : List_Id) return List_Id
14487    is
14488       Actual    : Entity_Id;
14489       Asnmt     : Node_Id;
14490       Formal    : Entity_Id;
14491       Has_Asnmt : Boolean := False;
14492       Result    : constant List_Id := New_List;
14493
14494    begin
14495       Actual := First (Actuals);
14496       Formal := Defining_Identifier (First (Formals));
14497       while Present (Actual) loop
14498          if Is_By_Copy_Type (Etype (Actual))
14499            and then Ekind (Formal) /= E_In_Parameter
14500          then
14501             --  Generate:
14502             --    <actual> := P.<formal>;
14503
14504             Asnmt :=
14505               Make_Assignment_Statement (Loc,
14506                 Name       =>
14507                   New_Copy (Actual),
14508                 Expression =>
14509                   Make_Explicit_Dereference (Loc,
14510                     Make_Selected_Component (Loc,
14511                       Prefix        =>
14512                         New_Occurrence_Of (P, Loc),
14513                       Selector_Name =>
14514                         Make_Identifier (Loc, Chars (Formal)))));
14515
14516             Set_Assignment_OK (Name (Asnmt));
14517             Append_To (Result, Asnmt);
14518
14519             Has_Asnmt := True;
14520          end if;
14521
14522          Next_Actual (Actual);
14523          Next_Formal_With_Extras (Formal);
14524       end loop;
14525
14526       if Has_Asnmt then
14527          return Result;
14528       else
14529          return New_List (Make_Null_Statement (Loc));
14530       end if;
14531    end Parameter_Block_Unpack;
14532
14533    ----------------------
14534    -- Set_Discriminals --
14535    ----------------------
14536
14537    procedure Set_Discriminals (Dec : Node_Id) is
14538       D       : Entity_Id;
14539       Pdef    : Entity_Id;
14540       D_Minal : Entity_Id;
14541
14542    begin
14543       pragma Assert (Nkind (Dec) = N_Protected_Type_Declaration);
14544       Pdef := Defining_Identifier (Dec);
14545
14546       if Has_Discriminants (Pdef) then
14547          D := First_Discriminant (Pdef);
14548          while Present (D) loop
14549             D_Minal :=
14550               Make_Defining_Identifier (Sloc (D),
14551                 Chars => New_External_Name (Chars (D), 'D'));
14552
14553             Set_Ekind (D_Minal, E_Constant);
14554             Set_Etype (D_Minal, Etype (D));
14555             Set_Scope (D_Minal, Pdef);
14556             Set_Discriminal (D, D_Minal);
14557             Set_Discriminal_Link (D_Minal, D);
14558
14559             Next_Discriminant (D);
14560          end loop;
14561       end if;
14562    end Set_Discriminals;
14563
14564    -----------------------
14565    -- Trivial_Accept_OK --
14566    -----------------------
14567
14568    function Trivial_Accept_OK return Boolean is
14569    begin
14570       case Opt.Task_Dispatching_Policy is
14571
14572          --  If we have the default task dispatching policy in effect, we can
14573          --  definitely do the optimization (one way of looking at this is to
14574          --  think of the formal definition of the default policy being allowed
14575          --  to run any task it likes after a rendezvous, so even if notionally
14576          --  a full rescheduling occurs, we can say that our dispatching policy
14577          --  (i.e. the default dispatching policy) reorders the queue to be the
14578          --  same as just before the call.
14579
14580          when ' ' =>
14581             return True;
14582
14583          --  FIFO_Within_Priorities certainly does not permit this
14584          --  optimization since the Rendezvous is a scheduling action that may
14585          --  require some other task to be run.
14586
14587          when 'F' =>
14588             return False;
14589
14590          --  For now, disallow the optimization for all other policies. This
14591          --  may be over-conservative, but it is certainly not incorrect.
14592
14593          when others =>
14594             return False;
14595
14596       end case;
14597    end Trivial_Accept_OK;
14598
14599 end Exp_Ch9;