OpenCores
URL https://opencores.org/ocsvn/openrisc/openrisc/trunk

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [gnu-dev/] [or1k-gcc/] [gcc/] [ada/] [exp_ch9.adb] - Blame information for rev 706

Details | Compare with Previous | View Log

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

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.