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

Subversion Repositories scarts

[/] [scarts/] [trunk/] [toolchain/] [scarts-gcc/] [gcc-4.1.1/] [gcc/] [ada/] [exp_ch9.adb] - Blame information for rev 16

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

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

powered by: WebSVN 2.1.0

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