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

Subversion Repositories openrisc_me

[/] [openrisc/] [trunk/] [gnu-src/] [gcc-4.5.1/] [gcc/] [ada/] [exp_ch9.adb] - Blame information for rev 290

Go to most recent revision | Details | Compare with Previous | View Log

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

powered by: WebSVN 2.1.0

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