1 ------------------------------------------------------------------------------
3 -- GNAT COMPILER COMPONENTS --
9 -- Copyright (C) 1992-2023, Free Software Foundation, Inc. --
11 -- GNAT is free software; you can redistribute it and/or modify it under --
12 -- terms of the GNU General Public License as published by the Free Soft- --
13 -- ware Foundation; either version 3, or (at your option) any later ver- --
14 -- sion. GNAT is distributed in the hope that it will be useful, but WITH- --
15 -- OUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY --
16 -- or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License --
17 -- for more details. You should have received a copy of the GNU General --
18 -- Public License distributed with GNAT; see file COPYING3. If not, go to --
19 -- http://www.gnu.org/licenses for a complete copy of the license. --
21 -- GNAT was originally developed by the GNAT team at New York University. --
22 -- Extensive contributions were provided by Ada Core Technologies Inc. --
24 ------------------------------------------------------------------------------
26 with Accessibility
; use Accessibility
;
27 with Atree
; use Atree
;
28 with Aspects
; use Aspects
;
29 with Checks
; use Checks
;
30 with Contracts
; use Contracts
;
31 with Einfo
; use Einfo
;
32 with Einfo
.Entities
; use Einfo
.Entities
;
33 with Einfo
.Utils
; use Einfo
.Utils
;
34 with Elists
; use Elists
;
35 with Errout
; use Errout
;
36 with Exp_Ch3
; use Exp_Ch3
;
37 with Exp_Ch6
; use Exp_Ch6
;
38 with Exp_Ch11
; use Exp_Ch11
;
39 with Exp_Dbug
; use Exp_Dbug
;
40 with Exp_Sel
; use Exp_Sel
;
41 with Exp_Smem
; use Exp_Smem
;
42 with Exp_Tss
; use Exp_Tss
;
43 with Exp_Util
; use Exp_Util
;
44 with Freeze
; use Freeze
;
46 with Itypes
; use Itypes
;
47 with Namet
; use Namet
;
48 with Nlists
; use Nlists
;
49 with Nmake
; use Nmake
;
51 with Restrict
; use Restrict
;
52 with Rident
; use Rident
;
53 with Rtsfind
; use Rtsfind
;
55 with Sem_Aux
; use Sem_Aux
;
56 with Sem_Ch5
; use Sem_Ch5
;
57 with Sem_Ch6
; use Sem_Ch6
;
58 with Sem_Ch8
; use Sem_Ch8
;
59 with Sem_Ch9
; use Sem_Ch9
;
60 with Sem_Ch11
; use Sem_Ch11
;
61 with Sem_Ch13
; use Sem_Ch13
;
62 with Sem_Elab
; use Sem_Elab
;
63 with Sem_Eval
; use Sem_Eval
;
64 with Sem_Res
; use Sem_Res
;
65 with Sem_Util
; use Sem_Util
;
66 with Sinfo
; use Sinfo
;
67 with Sinfo
.Nodes
; use Sinfo
.Nodes
;
68 with Sinfo
.Utils
; use Sinfo
.Utils
;
69 with Snames
; use Snames
;
70 with Stand
; use Stand
;
71 with Targparm
; use Targparm
;
72 with Tbuild
; use Tbuild
;
73 with Uintp
; use Uintp
;
74 with Validsw
; use Validsw
;
76 package body Exp_Ch9
is
78 -- The following constant establishes the upper bound for the index of
79 -- an entry family. It is used to limit the allocated size of protected
80 -- types with defaulted discriminant of an integer type, when the bound
81 -- of some entry family depends on a discriminant. The limitation to entry
82 -- families of 128K should be reasonable in all cases, and is a documented
83 -- implementation restriction.
85 Entry_Family_Bound
: constant Pos
:= 2**16;
87 -----------------------
88 -- Local Subprograms --
89 -----------------------
91 function Actual_Index_Expression
95 Tsk
: Entity_Id
) return Node_Id
;
96 -- Compute the index position for an entry call. Tsk is the target task. If
97 -- the bounds of some entry family depend on discriminants, the expression
98 -- computed by this function uses the discriminants of the target task.
100 procedure Add_Object_Pointer
102 Conc_Typ
: Entity_Id
;
104 -- Prepend an object pointer declaration to the declaration list Decls.
105 -- This object pointer is initialized to a type conversion of the System.
106 -- Address pointer passed to entry barrier functions and entry body
109 procedure Add_Formal_Renamings
114 -- Create renaming declarations for the formals, inside the procedure that
115 -- implements an entry body. The renamings make the original names of the
116 -- formals accessible to gdb, and serve no other purpose.
117 -- Spec is the specification of the procedure being built.
118 -- Decls is the list of declarations to be enhanced.
119 -- Ent is the entity for the original entry body.
121 function Build_Accept_Body
(Astat
: Node_Id
) return Node_Id
;
122 -- Transform accept statement into a block with added exception handler.
123 -- Used both for simple accept statements and for accept alternatives in
124 -- select statements. Astat is the accept statement.
126 function Build_Barrier_Function
129 Pid
: Entity_Id
) return Node_Id
;
130 -- Build the function body returning the value of the barrier expression
131 -- for the specified entry body.
133 function Build_Barrier_Function_Specification
135 Def_Id
: Entity_Id
) return Node_Id
;
136 -- Build a specification for a function implementing the protected entry
137 -- barrier of the specified entry body.
139 function Build_Corresponding_Record
142 Loc
: Source_Ptr
) return Node_Id
;
143 -- Common to tasks and protected types. Copy discriminant specifications,
144 -- build record declaration. N is the type declaration, Ctyp is the
145 -- concurrent entity (task type or protected type).
147 function Build_Dispatching_Tag_Check
149 N
: Node_Id
) return Node_Id
;
150 -- Utility to create the tree to check whether the dispatching call in
151 -- a timed entry call, a conditional entry call, or an asynchronous
152 -- transfer of control is a call to a primitive of a non-synchronized type.
153 -- K is the temporary that holds the tagged kind of the target object, and
154 -- N is the enclosing construct.
156 function Build_Entry_Count_Expression
157 (Concurrent_Type
: Entity_Id
;
158 Loc
: Source_Ptr
) return Node_Id
;
159 -- Compute number of entries for concurrent object. This is a count of
160 -- simple entries, followed by an expression that computes the length
161 -- of the range of each entry family. A single array with that size is
162 -- allocated for each concurrent object of the type.
164 function Build_Find_Body_Index
(Typ
: Entity_Id
) return Node_Id
;
165 -- Build the function that translates the entry index in the call
166 -- (which depends on the size of entry families) into an index into the
167 -- Entry_Bodies_Array, to determine the body and barrier function used
168 -- in a protected entry call. A pointer to this function appears in every
171 function Build_Find_Body_Index_Spec
(Typ
: Entity_Id
) return Node_Id
;
172 -- Build subprogram declaration for previous one
174 function Build_Lock_Free_Protected_Subprogram_Body
177 Unprot_Spec
: Node_Id
) return Node_Id
;
178 -- N denotes a subprogram body of protected type Prot_Typ. Unprot_Spec is
179 -- the subprogram specification of the unprotected version of N. Transform
180 -- N such that it invokes the unprotected version of the body.
182 function Build_Lock_Free_Unprotected_Subprogram_Body
184 Prot_Typ
: Node_Id
) return Node_Id
;
185 -- N denotes a subprogram body of protected type Prot_Typ. Build a version
186 -- of N where the original statements of N are synchronized through atomic
187 -- actions such as compare and exchange. Prior to invoking this routine, it
188 -- has been established that N can be implemented in a lock-free fashion.
190 function Build_Parameter_Block
194 Decls
: List_Id
) return Entity_Id
;
195 -- Generate an access type for each actual parameter in the list Actuals.
196 -- Create an encapsulating record that contains all the actuals and return
197 -- its type. Generate:
198 -- type Ann1 is access all <actual1-type>
200 -- type AnnN is access all <actualN-type>
201 -- type Pnn is record
207 function Build_Protected_Entry
210 Pid
: Node_Id
) return Node_Id
;
211 -- Build the procedure implementing the statement sequence of the specified
214 function Build_Protected_Entry_Specification
217 Ent_Id
: Entity_Id
) return Node_Id
;
218 -- Build a specification for the procedure implementing the statements of
219 -- the specified entry body. Add attributes associating it with the entry
220 -- defining identifier Ent_Id.
222 function Build_Protected_Spec
224 Obj_Type
: Entity_Id
;
226 Unprotected
: Boolean := False) return List_Id
;
227 -- Utility shared by Build_Protected_Sub_Spec and Expand_Access_Protected_
228 -- Subprogram_Type. Builds signature of protected subprogram, adding the
229 -- formal that corresponds to the object itself. For an access to protected
230 -- subprogram, there is no object type to specify, so the parameter has
231 -- type Address and mode In. An indirect call through such a pointer will
232 -- convert the address to a reference to the actual object. The object is
233 -- a limited record and therefore a by_reference type.
235 function Build_Protected_Subprogram_Body
238 N_Op_Spec
: Node_Id
) return Node_Id
;
239 -- This function is used to construct the protected version of a protected
240 -- subprogram. Its statement sequence first defers abort, then locks the
241 -- associated protected object, and then enters a block that contains a
242 -- call to the unprotected version of the subprogram (for details, see
243 -- Build_Unprotected_Subprogram_Body). This block statement requires a
244 -- cleanup handler that unlocks the object in all cases. For details,
245 -- see Exp_Ch7.Expand_Cleanup_Actions.
247 function Build_Renamed_Formal_Declaration
251 Renamed_Formal
: Node_Id
) return Node_Id
;
252 -- Create a renaming declaration for a formal, within a protected entry
253 -- body or an accept body. The renamed object is a component of the
254 -- parameter block that is a parameter in the entry call.
256 -- In Ada 2012, if the formal is an incomplete tagged type, the renaming
257 -- does not dereference the corresponding component to prevent an illegal
258 -- use of the incomplete type (AI05-0151).
260 function Build_Selected_Name
262 Selector
: Entity_Id
;
263 Append_Char
: Character := ' ') return Name_Id
;
264 -- Build a name in the form of Prefix__Selector, with an optional character
265 -- appended. This is used for internal subprograms generated for operations
266 -- of protected types, including barrier functions. For the subprograms
267 -- generated for entry bodies and entry barriers, the generated name
268 -- includes a sequence number that makes names unique in the presence of
269 -- entry overloading. This is necessary because entry body procedures and
270 -- barrier functions all have the same signature.
272 procedure Build_Simple_Entry_Call
277 -- Build the call corresponding to the task entry call. N is the task entry
278 -- call, Concval is the concurrent object, Ename is the entry name and
279 -- Index is the entry family index.
280 -- Note that N might be expanded into an N_Block_Statement if it gets
283 function Build_Task_Proc_Specification
(T
: Entity_Id
) return Node_Id
;
284 -- This routine constructs a specification for the procedure that we will
285 -- build for the task body for task type T. The spec has the form:
287 -- procedure tnameB (_Task : access tnameV);
289 -- where name is the character name taken from the task type entity that
290 -- is passed as the argument to the procedure, and tnameV is the task
291 -- value type that is associated with the task type.
293 function Build_Unprotected_Subprogram_Body
295 Pid
: Node_Id
) return Node_Id
;
296 -- This routine constructs the unprotected version of a protected
297 -- subprogram body, which contains all of the code in the original,
298 -- unexpanded body. This is the version of the protected subprogram that is
299 -- called from all protected operations on the same object, including the
300 -- protected version of the same subprogram.
302 procedure Build_Wrapper_Bodies
306 -- Ada 2005 (AI-345): Typ is either a concurrent type or the corresponding
307 -- record of a concurrent type. N is the insertion node where all bodies
308 -- will be placed. This routine builds the bodies of the subprograms which
309 -- serve as an indirection mechanism to overriding primitives of concurrent
310 -- types, entries and protected procedures. Any new body is analyzed.
312 procedure Build_Wrapper_Specs
316 -- Ada 2005 (AI-345): Typ is either a concurrent type or the corresponding
317 -- record of a concurrent type. N is the insertion node where all specs
318 -- will be placed. This routine builds the specs of the subprograms which
319 -- serve as an indirection mechanism to overriding primitives of concurrent
320 -- types, entries and protected procedures. Any new spec is analyzed.
322 procedure Collect_Entry_Families
325 Current_Node
: in out Node_Id
;
326 Conctyp
: Entity_Id
);
327 -- For each entry family in a concurrent type, create an anonymous array
328 -- type of the right size, and add a component to the corresponding_record.
330 function Concurrent_Object
331 (Spec_Id
: Entity_Id
;
332 Conc_Typ
: Entity_Id
) return Entity_Id
;
333 -- Given a subprogram entity Spec_Id and concurrent type Conc_Typ, return
334 -- the entity associated with the concurrent object in the Protected_Body_
335 -- Subprogram or the Task_Body_Procedure of Spec_Id. The returned entity
336 -- denotes formal parameter _O, _object or _task.
338 function Copy_Result_Type
(Res
: Node_Id
) return Node_Id
;
339 -- Copy the result type of a function specification, when building the
340 -- internal operation corresponding to a protected function, or when
341 -- expanding an access to protected function. If the result is an anonymous
342 -- access to subprogram itself, we need to create a new signature with the
343 -- same parameter names and the same resolved types, but with new entities
346 function Create_Secondary_Stack_For_Task
(T
: Node_Id
) return Boolean;
347 -- Return whether a secondary stack for the task T should be created by the
348 -- expander. The secondary stack for a task will be created by the expander
349 -- if the size of the stack has been specified by the Secondary_Stack_Size
350 -- representation aspect and either the No_Implicit_Heap_Allocations or
351 -- No_Implicit_Task_Allocations restrictions are in effect and the
352 -- No_Secondary_Stack restriction is not.
354 procedure Debug_Private_Data_Declarations
(Decls
: List_Id
);
355 -- Decls is a list which may contain the declarations created by Install_
356 -- Private_Data_Declarations. All generated entities are marked as needing
357 -- debug info and debug nodes are manually generation where necessary. This
358 -- step of the expansion must to be done after private data has been moved
359 -- to its final resting scope to ensure proper visibility of debug objects.
361 procedure Ensure_Statement_Present
(Loc
: Source_Ptr
; Alt
: Node_Id
);
362 -- If control flow optimizations are suppressed, and Alt is an accept,
363 -- delay, or entry call alternative with no trailing statements, insert
364 -- a null trailing statement with the given Loc (which is the sloc of
365 -- the accept, delay, or entry call statement). There might not be any
366 -- generated code for the accept, delay, or entry call itself (the effect
367 -- of these statements is part of the general processing done for the
368 -- enclosing selective accept, timed entry call, or asynchronous select),
369 -- and the null statement is there to carry the sloc of that statement to
370 -- the back-end for trace-based coverage analysis purposes.
372 procedure Extract_Dispatching_Call
374 Call_Ent
: out Entity_Id
;
375 Object
: out Entity_Id
;
376 Actuals
: out List_Id
;
377 Formals
: out List_Id
);
378 -- Given a dispatching call, extract the entity of the name of the call,
379 -- its actual dispatching object, its actual parameters and the formal
380 -- parameters of the overridden interface-level version. If the type of
381 -- the dispatching object is an access type then an explicit dereference
382 -- is returned in Object.
384 procedure Extract_Entry
386 Concval
: out Node_Id
;
388 Index
: out Node_Id
);
389 -- Given an entry call, returns the associated concurrent object, the entry
390 -- name, and the entry family index.
392 function Family_Offset
397 Cap
: Boolean) return Node_Id
;
398 -- Compute (Hi - Lo) for two entry family indexes. Hi is the index in an
399 -- accept statement, or the upper bound in the discrete subtype of an entry
400 -- declaration. Lo is the corresponding lower bound. Ttyp is the concurrent
401 -- type of the entry. If Cap is true, the result is capped according to
402 -- Entry_Family_Bound.
409 Cap
: Boolean) return Node_Id
;
410 -- Compute (Hi - Lo) + 1 Max 0, to determine the number of entries in a
411 -- family, and handle properly the superflat case. This is equivalent to
412 -- the use of 'Length on the index type, but must use Family_Offset to
413 -- handle properly the case of bounds that depend on discriminants. If
414 -- Cap is true, the result is capped according to Entry_Family_Bound.
416 procedure Find_Enclosing_Context
418 Context
: out Node_Id
;
419 Context_Id
: out Entity_Id
;
420 Context_Decls
: out List_Id
);
421 -- Subsidiary routine to procedures Build_Activation_Chain_Entity and
422 -- Build_Master_Entity. Given an arbitrary node in the tree, find the
423 -- nearest enclosing body, block, package, or return statement and return
424 -- its constituents. Context is the enclosing construct, Context_Id is
425 -- the scope of Context_Id and Context_Decls is the declarative list of
428 function Index_Object
(Spec_Id
: Entity_Id
) return Entity_Id
;
429 -- Given a subprogram identifier, return the entity which is associated
430 -- with the protection entry index in the Protected_Body_Subprogram or
431 -- the Task_Body_Procedure of Spec_Id. The returned entity denotes formal
434 function Is_Potentially_Large_Family
435 (Base_Index
: Entity_Id
;
438 Hi
: Node_Id
) return Boolean;
439 -- Determine whether an entry family is potentially large because one of
440 -- its bounds denotes a discrminant.
442 function Is_Private_Primitive_Subprogram
(Id
: Entity_Id
) return Boolean;
443 -- Determine whether Id is a function or a procedure and is marked as a
444 -- private primitive.
446 function Null_Statements
(Stats
: List_Id
) return Boolean;
447 -- Used to check DO-END sequence. Checks for equivalent of DO NULL; END.
448 -- Allows labels, and pragma Warnings/Unreferenced in the sequence as well
449 -- to still count as null. Returns True for a null sequence. The argument
450 -- is the list of statements from the DO-END sequence.
452 function Parameter_Block_Pack
458 Stmts
: List_Id
) return Entity_Id
;
459 -- Set the components of the generated parameter block with the values
460 -- of the actual parameters. Generate aliased temporaries to capture the
461 -- values for types that are passed by copy. Otherwise generate a reference
462 -- to the actual's value. Return the address of the aggregate block.
464 -- Jnn1 : alias <formal-type1>;
465 -- Jnn1 := <actual1>;
468 -- Jnn1'unchecked_access;
469 -- <actual2>'reference;
472 function Parameter_Block_Unpack
476 Formals
: List_Id
) return List_Id
;
477 -- Retrieve the values of the components from the parameter block and
478 -- assign then to the original actual parameters. Generate:
479 -- <actual1> := P.<formal1>;
481 -- <actualN> := P.<formalN>;
483 procedure Reset_Scopes_To
(Bod
: Node_Id
; E
: Entity_Id
);
484 -- Reset the scope of declarations and blocks at the top level of Bod to
485 -- be E. Bod is either a block or a subprogram body. Used after expanding
486 -- various kinds of entry bodies into their corresponding constructs. This
487 -- is needed during unnesting to determine whether a body generated for an
488 -- entry or an accept alternative includes uplevel references.
490 function Trivial_Accept_OK
return Boolean;
491 -- If there is no DO-END block for an accept, or if the DO-END block has
492 -- only null statements, then it is possible to do the Rendezvous with much
493 -- less overhead using the Accept_Trivial routine in the run-time library.
494 -- However, this is not always a valid optimization. Whether it is valid or
495 -- not depends on the Task_Dispatching_Policy. The issue is whether a full
496 -- rescheduling action is required or not. In FIFO_Within_Priorities, such
497 -- a rescheduling is required, so this optimization is not allowed. This
498 -- function returns True if the optimization is permitted.
500 -----------------------------
501 -- Actual_Index_Expression --
502 -----------------------------
504 function Actual_Index_Expression
508 Tsk
: Entity_Id
) return Node_Id
510 Ttyp
: constant Entity_Id
:= Etype
(Tsk
);
518 function Actual_Family_Offset
(Hi
, Lo
: Node_Id
) return Node_Id
;
519 -- Compute difference between bounds of entry family
521 --------------------------
522 -- Actual_Family_Offset --
523 --------------------------
525 function Actual_Family_Offset
(Hi
, Lo
: Node_Id
) return Node_Id
is
527 function Actual_Discriminant_Ref
(Bound
: Node_Id
) return Node_Id
;
528 -- Replace a reference to a discriminant with a selected component
529 -- denoting the discriminant of the target task.
531 -----------------------------
532 -- Actual_Discriminant_Ref --
533 -----------------------------
535 function Actual_Discriminant_Ref
(Bound
: Node_Id
) return Node_Id
is
536 Typ
: constant Entity_Id
:= Etype
(Bound
);
540 if not Is_Entity_Name
(Bound
)
541 or else Ekind
(Entity
(Bound
)) /= E_Discriminant
543 if Nkind
(Bound
) = N_Attribute_Reference
then
546 B
:= New_Copy_Tree
(Bound
);
551 Make_Selected_Component
(Sloc
,
552 Prefix
=> New_Copy_Tree
(Tsk
),
553 Selector_Name
=> New_Occurrence_Of
(Entity
(Bound
), Sloc
));
555 Analyze_And_Resolve
(B
, Typ
);
559 Make_Attribute_Reference
(Sloc
,
560 Attribute_Name
=> Name_Pos
,
561 Prefix
=> New_Occurrence_Of
(Etype
(Bound
), Sloc
),
562 Expressions
=> New_List
(B
));
563 end Actual_Discriminant_Ref
;
565 -- Start of processing for Actual_Family_Offset
569 Make_Op_Subtract
(Sloc
,
570 Left_Opnd
=> Actual_Discriminant_Ref
(Hi
),
571 Right_Opnd
=> Actual_Discriminant_Ref
(Lo
));
572 end Actual_Family_Offset
;
574 -- Start of processing for Actual_Index_Expression
577 -- The queues of entries and entry families appear in textual order in
578 -- the associated record. The entry index is computed as the sum of the
579 -- number of queues for all entries that precede the designated one, to
580 -- which is added the index expression, if this expression denotes a
581 -- member of a family.
583 -- The following is a place holder for the count of simple entries
585 Num
:= Make_Integer_Literal
(Sloc
, 1);
587 -- We construct an expression which is a series of addition operations.
588 -- See comments in Entry_Index_Expression, which is identical in
591 if Present
(Index
) then
592 S
:= Entry_Index_Type
(Ent
);
594 -- First make sure the index is in range if requested. The index type
595 -- has been directly set on the prefix, see Resolve_Entry.
597 if Do_Range_Check
(Index
) then
599 (Index
, Etype
(Prefix
(Parent
(Index
))), CE_Range_Check_Failed
);
606 Actual_Family_Offset
(
607 Make_Attribute_Reference
(Sloc
,
608 Attribute_Name
=> Name_Pos
,
609 Prefix
=> New_Occurrence_Of
(Base_Type
(S
), Sloc
),
610 Expressions
=> New_List
(Relocate_Node
(Index
))),
611 Type_Low_Bound
(S
)));
616 -- Now add lengths of preceding entries and entry families
618 Prev
:= First_Entity
(Ttyp
);
619 while Chars
(Prev
) /= Chars
(Ent
)
620 or else Ekind
(Prev
) /= Ekind
(Ent
)
621 or else not Sem_Ch6
.Type_Conformant
(Ent
, Prev
)
623 if Ekind
(Prev
) = E_Entry
then
624 Set_Intval
(Num
, Intval
(Num
) + 1);
626 elsif Ekind
(Prev
) = E_Entry_Family
then
627 S
:= Entry_Index_Type
(Prev
);
629 -- The need for the following full view retrieval stems from this
630 -- complex case of nested generics and tasking:
633 -- type Formal_Index is range <>;
636 -- type Index is private;
643 -- type Index is new Formal_Index range 1 .. 10;
646 -- package body Outer is
648 -- entry Fam (Index); -- (2)
651 -- package body Inner is -- (3)
659 -- We are currently building the index expression for the entry
660 -- call "T.E" (1). Part of the expansion must mention the range
661 -- of the discrete type "Index" (2) of entry family "Fam".
663 -- However only the private view of type "Index" is available to
664 -- the inner generic (3) because there was no prior mention of
665 -- the type inside "Inner". This visibility requirement is
666 -- implicit and cannot be detected during the construction of
667 -- the generic trees and needs special handling.
670 and then Is_Private_Type
(S
)
671 and then Present
(Full_View
(S
))
676 Lo
:= Type_Low_Bound
(S
);
677 Hi
:= Type_High_Bound
(S
);
684 Left_Opnd
=> Actual_Family_Offset
(Hi
, Lo
),
685 Right_Opnd
=> Make_Integer_Literal
(Sloc
, 1)));
687 -- Other components are anonymous types to be ignored
697 end Actual_Index_Expression
;
699 --------------------------
700 -- Add_Formal_Renamings --
701 --------------------------
703 procedure Add_Formal_Renamings
709 Ptr
: constant Entity_Id
:=
711 (Next
(First
(Parameter_Specifications
(Spec
))));
712 -- The name of the formal that holds the address of the parameter block
719 Renamed_Formal
: Node_Id
;
722 Formal
:= First_Formal
(Ent
);
723 while Present
(Formal
) loop
724 Comp
:= Entry_Component
(Formal
);
726 Make_Defining_Identifier
(Sloc
(Formal
),
727 Chars
=> Chars
(Formal
));
728 Set_Etype
(New_F
, Etype
(Formal
));
729 Set_Scope
(New_F
, Ent
);
731 -- Now we set debug info needed on New_F even though it does not come
732 -- from source, so that the debugger will get the right information
733 -- for these generated names.
735 Set_Debug_Info_Needed
(New_F
);
737 if Ekind
(Formal
) = E_In_Parameter
then
738 Mutate_Ekind
(New_F
, E_Constant
);
740 Mutate_Ekind
(New_F
, E_Variable
);
741 Set_Extra_Constrained
(New_F
, Extra_Constrained
(Formal
));
744 Set_Actual_Subtype
(New_F
, Actual_Subtype
(Formal
));
747 Make_Selected_Component
(Loc
,
749 Make_Explicit_Dereference
(Loc
,
750 Unchecked_Convert_To
(Entry_Parameters_Type
(Ent
),
751 Make_Identifier
(Loc
, Chars
(Ptr
)))),
752 Selector_Name
=> New_Occurrence_Of
(Comp
, Loc
));
755 Build_Renamed_Formal_Declaration
756 (New_F
, Formal
, Comp
, Renamed_Formal
);
758 Append
(Decl
, Decls
);
759 Set_Renamed_Object
(Formal
, New_F
);
760 Next_Formal
(Formal
);
762 end Add_Formal_Renamings
;
764 ------------------------
765 -- Add_Object_Pointer --
766 ------------------------
768 procedure Add_Object_Pointer
770 Conc_Typ
: Entity_Id
;
773 Rec_Typ
: constant Entity_Id
:= Corresponding_Record_Type
(Conc_Typ
);
778 -- Create the renaming declaration for the Protection object of a
779 -- protected type. _Object is used by Complete_Entry_Body.
780 -- ??? An attempt to make this a renaming was unsuccessful.
782 -- Build the entity for the access type
785 Make_Defining_Identifier
(Loc
,
786 New_External_Name
(Chars
(Rec_Typ
), 'P'));
789 -- _object : poVP := poVP!O;
792 Make_Object_Declaration
(Loc
,
793 Defining_Identifier
=> Make_Defining_Identifier
(Loc
, Name_uObject
),
794 Object_Definition
=> New_Occurrence_Of
(Obj_Ptr
, Loc
),
796 Unchecked_Convert_To
(Obj_Ptr
, Make_Identifier
(Loc
, Name_uO
)));
797 Set_Debug_Info_Needed
(Defining_Identifier
(Decl
));
798 Prepend_To
(Decls
, Decl
);
801 -- type poVP is access poV;
804 Make_Full_Type_Declaration
(Loc
,
805 Defining_Identifier
=>
808 Make_Access_To_Object_Definition
(Loc
,
809 Subtype_Indication
=>
810 New_Occurrence_Of
(Rec_Typ
, Loc
)));
811 Set_Debug_Info_Needed
(Defining_Identifier
(Decl
));
812 Prepend_To
(Decls
, Decl
);
813 end Add_Object_Pointer
;
815 -----------------------
816 -- Build_Accept_Body --
817 -----------------------
819 function Build_Accept_Body
(Astat
: Node_Id
) return Node_Id
is
820 Loc
: constant Source_Ptr
:= Sloc
(Astat
);
821 Stats
: constant Node_Id
:= Handled_Statement_Sequence
(Astat
);
828 -- At the end of the statement sequence, Complete_Rendezvous is called.
829 -- A label skipping the Complete_Rendezvous, and all other accept
830 -- processing, has already been added for the expansion of requeue
831 -- statements. The Sloc is copied from the last statement since it
832 -- is really part of this last statement.
836 (Sloc
(Last
(Statements
(Stats
))), RE_Complete_Rendezvous
);
837 Insert_Before
(Last
(Statements
(Stats
)), Call
);
840 -- Ada 2022 (AI12-0279)
842 if Has_Yield_Aspect
(Entity
(Entry_Direct_Name
(Astat
)))
843 and then RTE_Available
(RE_Yield
)
845 Insert_Action_After
(Call
,
846 Make_Procedure_Call_Statement
(Loc
,
847 New_Occurrence_Of
(RTE
(RE_Yield
), Loc
)));
850 -- If exception handlers are present, then append Complete_Rendezvous
851 -- calls to the handlers, and construct the required outer block. As
852 -- above, the Sloc is copied from the last statement in the sequence.
854 if Present
(Exception_Handlers
(Stats
)) then
855 Hand
:= First
(Exception_Handlers
(Stats
));
856 while Present
(Hand
) loop
859 (Sloc
(Last
(Statements
(Hand
))), RE_Complete_Rendezvous
);
860 Append
(Call
, Statements
(Hand
));
863 -- Ada 2022 (AI12-0279)
865 if Has_Yield_Aspect
(Entity
(Entry_Direct_Name
(Astat
)))
866 and then RTE_Available
(RE_Yield
)
868 Insert_Action_After
(Call
,
869 Make_Procedure_Call_Statement
(Loc
,
870 New_Occurrence_Of
(RTE
(RE_Yield
), Loc
)));
877 Make_Handled_Sequence_Of_Statements
(Loc
,
878 Statements
=> New_List
(
879 Make_Block_Statement
(Loc
,
880 Handled_Statement_Sequence
=> Stats
)));
886 -- At this stage we know that the new statement sequence does
887 -- not have an exception handler part, so we supply one to call
888 -- Exceptional_Complete_Rendezvous. This handler is
890 -- when all others =>
891 -- Exceptional_Complete_Rendezvous (Get_GNAT_Exception);
893 -- We handle Abort_Signal to make sure that we properly catch the abort
894 -- case and wake up the caller.
897 Make_Procedure_Call_Statement
(Sloc
(Stats
),
898 Name
=> New_Occurrence_Of
(
899 RTE
(RE_Exceptional_Complete_Rendezvous
), Sloc
(Stats
)),
900 Parameter_Associations
=> New_List
(
901 Make_Function_Call
(Sloc
(Stats
),
904 (RTE
(RE_Get_GNAT_Exception
), Sloc
(Stats
)))));
906 Ohandle
:= Make_Others_Choice
(Loc
);
907 Set_All_Others
(Ohandle
);
909 Set_Exception_Handlers
(New_S
,
911 Make_Implicit_Exception_Handler
(Loc
,
912 Exception_Choices
=> New_List
(Ohandle
),
914 Statements
=> New_List
(Call
))));
916 -- Ada 2022 (AI12-0279)
918 if Has_Yield_Aspect
(Entity
(Entry_Direct_Name
(Astat
)))
919 and then RTE_Available
(RE_Yield
)
921 Insert_Action_After
(Call
,
922 Make_Procedure_Call_Statement
(Loc
,
923 New_Occurrence_Of
(RTE
(RE_Yield
), Loc
)));
926 Set_Parent
(New_S
, Astat
); -- temp parent for Analyze call
927 Analyze_Exception_Handlers
(Exception_Handlers
(New_S
));
928 Expand_Exception_Handlers
(New_S
);
930 -- Exceptional_Complete_Rendezvous must be called with abort still
931 -- deferred, which is the case for a "when all others" handler.
934 end Build_Accept_Body
;
936 -----------------------------------
937 -- Build_Activation_Chain_Entity --
938 -----------------------------------
940 procedure Build_Activation_Chain_Entity
(N
: Node_Id
) is
941 function Has_Activation_Chain
(Stmt
: Node_Id
) return Boolean;
942 -- Determine whether an extended return statement has activation chain
944 --------------------------
945 -- Has_Activation_Chain --
946 --------------------------
948 function Has_Activation_Chain
(Stmt
: Node_Id
) return Boolean is
952 Decl
:= First
(Return_Object_Declarations
(Stmt
));
953 while Present
(Decl
) loop
954 if Nkind
(Decl
) = N_Object_Declaration
955 and then Chars
(Defining_Identifier
(Decl
)) = Name_uChain
964 end Has_Activation_Chain
;
969 Context_Id
: Entity_Id
;
972 -- Start of processing for Build_Activation_Chain_Entity
975 -- No action needed if the run-time has no tasking support
977 if Global_No_Tasking
then
981 -- Activation chain is never used for sequential elaboration policy, see
982 -- comment for Create_Restricted_Task_Sequential in s-tarest.ads).
984 if Partition_Elaboration_Policy
= 'S' then
988 Find_Enclosing_Context
(N
, Context
, Context_Id
, Decls
);
990 -- If activation chain entity has not been declared already, create one
992 if Nkind
(Context
) = N_Extended_Return_Statement
993 or else No
(Activation_Chain_Entity
(Context
))
995 -- Since extended return statements do not store the entity of the
996 -- chain, examine the return object declarations to avoid creating
999 if Nkind
(Context
) = N_Extended_Return_Statement
1000 and then Has_Activation_Chain
(Context
)
1006 Loc
: constant Source_Ptr
:= Sloc
(Context
);
1011 Chain
:= Make_Defining_Identifier
(Sloc
(N
), Name_uChain
);
1013 -- Note: An extended return statement is not really a task
1014 -- activator, but it does have an activation chain on which to
1015 -- store the tasks temporarily. On successful return, the tasks
1016 -- on this chain are moved to the chain passed in by the caller.
1017 -- We do not build an Activation_Chain_Entity for an extended
1018 -- return statement, because we do not want to build a call to
1019 -- Activate_Tasks. Task activation is the responsibility of the
1022 if Nkind
(Context
) /= N_Extended_Return_Statement
then
1023 Set_Activation_Chain_Entity
(Context
, Chain
);
1027 Make_Object_Declaration
(Loc
,
1028 Defining_Identifier
=> Chain
,
1029 Aliased_Present
=> True,
1030 Object_Definition
=>
1031 New_Occurrence_Of
(RTE
(RE_Activation_Chain
), Loc
));
1033 Prepend_To
(Decls
, Decl
);
1035 -- Ensure that _chain appears in the proper scope of the context
1037 if Context_Id
/= Current_Scope
then
1038 Push_Scope
(Context_Id
);
1046 end Build_Activation_Chain_Entity
;
1048 ----------------------------
1049 -- Build_Barrier_Function --
1050 ----------------------------
1052 function Build_Barrier_Function
1055 Pid
: Entity_Id
) return Node_Id
1057 Ent_Formals
: constant Node_Id
:= Entry_Body_Formal_Part
(N
);
1058 Cond
: constant Node_Id
:= Condition
(Ent_Formals
);
1059 Loc
: constant Source_Ptr
:= Sloc
(Cond
);
1060 Func_Id
: constant Entity_Id
:= Barrier_Function
(Ent
);
1061 Op_Decls
: constant List_Id
:= New_List
;
1063 Func_Body
: Node_Id
;
1066 -- Add a declaration for the Protection object, renaming declarations
1067 -- for the discriminals and privals and finally a declaration for the
1068 -- entry family index (if applicable).
1070 Install_Private_Data_Declarations
(Sloc
(N
),
1076 Family
=> Ekind
(Ent
) = E_Entry_Family
);
1078 -- If compiling with -fpreserve-control-flow, make sure we insert an
1079 -- IF statement so that the back-end knows to generate a conditional
1080 -- branch instruction, even if the condition is just the name of a
1081 -- boolean object. Note that Expand_N_If_Statement knows to preserve
1082 -- such redundant IF statements under -fpreserve-control-flow
1083 -- (whether coming from this routine, or directly from source).
1085 if Opt
.Suppress_Control_Flow_Optimizations
then
1087 Make_Implicit_If_Statement
(Cond
,
1089 Then_Statements
=> New_List
(
1090 Make_Simple_Return_Statement
(Loc
,
1091 New_Occurrence_Of
(Standard_True
, Loc
))),
1093 Else_Statements
=> New_List
(
1094 Make_Simple_Return_Statement
(Loc
,
1095 New_Occurrence_Of
(Standard_False
, Loc
))));
1098 Stmt
:= Make_Simple_Return_Statement
(Loc
, Cond
);
1101 -- Note: the condition in the barrier function needs to be properly
1102 -- processed for the C/Fortran boolean possibility, but this happens
1103 -- automatically since the return statement does this normalization.
1106 Make_Subprogram_Body
(Loc
,
1108 Build_Barrier_Function_Specification
(Loc
,
1109 Make_Defining_Identifier
(Loc
, Chars
(Func_Id
))),
1110 Declarations
=> Op_Decls
,
1111 Handled_Statement_Sequence
=>
1112 Make_Handled_Sequence_Of_Statements
(Loc
,
1113 Statements
=> New_List
(Stmt
)));
1114 Set_Is_Entry_Barrier_Function
(Func_Body
);
1117 end Build_Barrier_Function
;
1119 ------------------------------------------
1120 -- Build_Barrier_Function_Specification --
1121 ------------------------------------------
1123 function Build_Barrier_Function_Specification
1125 Def_Id
: Entity_Id
) return Node_Id
1128 Set_Debug_Info_Needed
(Def_Id
);
1131 Make_Function_Specification
(Loc
,
1132 Defining_Unit_Name
=> Def_Id
,
1133 Parameter_Specifications
=> New_List
(
1134 Make_Parameter_Specification
(Loc
,
1135 Defining_Identifier
=>
1136 Make_Defining_Identifier
(Loc
, Name_uO
),
1138 New_Occurrence_Of
(RTE
(RE_Address
), Loc
)),
1140 Make_Parameter_Specification
(Loc
,
1141 Defining_Identifier
=>
1142 Make_Defining_Identifier
(Loc
, Name_uE
),
1144 New_Occurrence_Of
(RTE
(RE_Protected_Entry_Index
), Loc
))),
1146 Result_Definition
=>
1147 New_Occurrence_Of
(Standard_Boolean
, Loc
));
1148 end Build_Barrier_Function_Specification
;
1150 --------------------------
1151 -- Build_Call_With_Task --
1152 --------------------------
1154 function Build_Call_With_Task
1156 E
: Entity_Id
) return Node_Id
1158 Loc
: constant Source_Ptr
:= Sloc
(N
);
1161 Make_Function_Call
(Loc
,
1162 Name
=> New_Occurrence_Of
(E
, Loc
),
1163 Parameter_Associations
=> New_List
(Concurrent_Ref
(N
)));
1164 end Build_Call_With_Task
;
1166 -----------------------------
1167 -- Build_Class_Wide_Master --
1168 -----------------------------
1170 procedure Build_Class_Wide_Master
(Typ
: Entity_Id
) is
1171 Loc
: constant Source_Ptr
:= Sloc
(Typ
);
1172 Master_Decl
: Node_Id
;
1173 Master_Id
: Entity_Id
;
1174 Master_Scope
: Entity_Id
;
1176 Related_Node
: Node_Id
;
1180 -- No action needed if the run-time has no tasking support
1182 if Global_No_Tasking
then
1186 -- Find the declaration that created the access type, which is either a
1187 -- type declaration, or an object declaration with an access definition,
1188 -- in which case the type is anonymous.
1190 if Is_Itype
(Typ
) then
1191 Related_Node
:= Associated_Node_For_Itype
(Typ
);
1193 Related_Node
:= Parent
(Typ
);
1196 Master_Scope
:= Find_Master_Scope
(Typ
);
1198 -- Nothing to do if the master scope already contains a _master entity.
1199 -- The only exception to this is the following scenario:
1202 -- Transient_Scope_1
1205 -- Transient_Scope_2
1208 -- In this case the source scope is marked as having the master entity
1209 -- even though the actual declaration appears inside an inner scope. If
1210 -- the second transient scope requires a _master, it cannot use the one
1211 -- already declared because the entity is not visible.
1213 Name_Id
:= Make_Identifier
(Loc
, Name_uMaster
);
1214 Master_Decl
:= Empty
;
1216 if not Has_Master_Entity
(Master_Scope
)
1217 or else No
(Current_Entity_In_Scope
(Name_Id
))
1224 Master_Decl
:= Build_Master_Declaration
(Loc
);
1226 -- Ensure that the master declaration is placed before its use
1228 Ins_Nod
:= Find_Hook_Context
(Related_Node
);
1229 while not Is_List_Member
(Ins_Nod
) loop
1230 Ins_Nod
:= Parent
(Ins_Nod
);
1233 Par_Nod
:= Parent
(List_Containing
(Ins_Nod
));
1235 -- For internal blocks created by Wrap_Loop_Statement, Wrap_
1236 -- Statements_In_Block, and Build_Abort_Undefer_Block, remember
1237 -- that they have a task master entity declaration; required by
1238 -- Build_Master_Entity to avoid creating another master entity,
1239 -- and also ensures that subsequent calls to Find_Master_Scope
1240 -- return this scope as the master scope of Typ.
1242 if Is_Internal_Block
(Par_Nod
) then
1243 Set_Has_Master_Entity
(Entity
(Identifier
(Par_Nod
)));
1245 elsif Nkind
(Par_Nod
) = N_Handled_Sequence_Of_Statements
1246 and then Is_Internal_Block
(Parent
(Par_Nod
))
1248 Set_Has_Master_Entity
(Entity
(Identifier
(Parent
(Par_Nod
))));
1250 -- Otherwise remember that this scope has an associated task
1251 -- master entity declaration.
1254 Set_Has_Master_Entity
(Master_Scope
);
1257 Insert_Before
(First
(List_Containing
(Ins_Nod
)), Master_Decl
);
1258 Analyze
(Master_Decl
);
1260 -- Mark the containing scope as a task master. Masters associated
1261 -- with return statements are already marked at this stage (see
1262 -- Analyze_Subprogram_Body).
1264 if Ekind
(Current_Scope
) /= E_Return_Statement
then
1266 Par
: Node_Id
:= Related_Node
;
1269 while Nkind
(Par
) /= N_Compilation_Unit
loop
1270 Par
:= Parent
(Par
);
1272 -- If we fall off the top, we are at the outer level,
1273 -- and the environment task is our effective master,
1274 -- so nothing to mark.
1277 N_Block_Statement | N_Subprogram_Body | N_Task_Body
1279 Set_Is_Task_Master
(Par
);
1289 Make_Defining_Identifier
(Loc
, New_External_Name
(Chars
(Typ
), 'M'));
1292 -- typeMnn renames _master;
1295 Make_Object_Renaming_Declaration
(Loc
,
1296 Defining_Identifier
=> Master_Id
,
1297 Subtype_Mark
=> New_Occurrence_Of
(Standard_Integer
, Loc
),
1300 -- If the master is declared locally, add the renaming declaration
1301 -- immediately after it, to prevent access-before-elaboration in the
1304 if Present
(Master_Decl
) then
1305 Insert_After
(Master_Decl
, Ren_Decl
);
1309 Insert_Action
(Related_Node
, Ren_Decl
);
1312 Set_Master_Id
(Typ
, Master_Id
);
1313 end Build_Class_Wide_Master
;
1315 --------------------------------
1316 -- Build_Corresponding_Record --
1317 --------------------------------
1319 function Build_Corresponding_Record
1322 Loc
: Source_Ptr
) return Node_Id
1324 Rec_Ent
: constant Entity_Id
:=
1325 Make_Defining_Identifier
1326 (Loc
, New_External_Name
(Chars
(Ctyp
), 'V'));
1329 New_Disc
: Entity_Id
;
1333 Set_Corresponding_Record_Type
(Ctyp
, Rec_Ent
);
1334 Mutate_Ekind
(Rec_Ent
, E_Record_Type
);
1335 Set_Has_Delayed_Freeze
(Rec_Ent
, Has_Delayed_Freeze
(Ctyp
));
1336 Set_Is_Concurrent_Record_Type
(Rec_Ent
, True);
1337 Set_Corresponding_Concurrent_Type
(Rec_Ent
, Ctyp
);
1338 Set_Stored_Constraint
(Rec_Ent
, No_Elist
);
1341 -- Use discriminals to create list of discriminants for record, and
1342 -- create new discriminals for use in default expressions, etc. It is
1343 -- worth noting that a task discriminant gives rise to 5 entities;
1345 -- a) The original discriminant.
1346 -- b) The discriminal for use in the task.
1347 -- c) The discriminant of the corresponding record.
1348 -- d) The discriminal for the init proc of the corresponding record.
1349 -- e) The local variable that renames the discriminant in the procedure
1350 -- for the task body.
1352 -- In fact the discriminals b) are used in the renaming declarations
1353 -- for e). See details in einfo (Handling of Discriminants).
1355 if Present
(Discriminant_Specifications
(N
)) then
1357 Disc
:= First_Discriminant
(Ctyp
);
1359 while Present
(Disc
) loop
1360 New_Disc
:= CR_Discriminant
(Disc
);
1363 Make_Discriminant_Specification
(Loc
,
1364 Defining_Identifier
=> New_Disc
,
1365 Discriminant_Type
=>
1366 New_Occurrence_Of
(Etype
(Disc
), Loc
),
1368 New_Copy
(Discriminant_Default_Value
(Disc
))));
1370 Next_Discriminant
(Disc
);
1377 -- Now we can construct the record type declaration. Note that this
1378 -- record is "limited tagged". It is "limited" to reflect the underlying
1379 -- limitedness of the task or protected object that it represents, and
1380 -- ensuring for example that it is properly passed by reference. It is
1381 -- "tagged" to give support to dispatching calls through interfaces. We
1382 -- propagate here the list of interfaces covered by the concurrent type
1383 -- (Ada 2005: AI-345).
1386 Make_Full_Type_Declaration
(Loc
,
1387 Defining_Identifier
=> Rec_Ent
,
1388 Discriminant_Specifications
=> Dlist
,
1390 Make_Record_Definition
(Loc
,
1392 Make_Component_List
(Loc
, Component_Items
=> Cdecls
),
1394 Ada_Version
>= Ada_2005
and then Is_Tagged_Type
(Ctyp
),
1395 Interface_List
=> Interface_List
(N
),
1396 Limited_Present
=> True));
1397 end Build_Corresponding_Record
;
1399 ---------------------------------
1400 -- Build_Dispatching_Tag_Check --
1401 ---------------------------------
1403 function Build_Dispatching_Tag_Check
1405 N
: Node_Id
) return Node_Id
1407 Loc
: constant Source_Ptr
:= Sloc
(N
);
1414 New_Occurrence_Of
(K
, Loc
),
1416 New_Occurrence_Of
(RTE
(RE_TK_Limited_Tagged
), Loc
)),
1420 New_Occurrence_Of
(K
, Loc
),
1422 New_Occurrence_Of
(RTE
(RE_TK_Tagged
), Loc
)));
1423 end Build_Dispatching_Tag_Check
;
1425 ----------------------------------
1426 -- Build_Entry_Count_Expression --
1427 ----------------------------------
1429 function Build_Entry_Count_Expression
1430 (Concurrent_Type
: Entity_Id
;
1431 Loc
: Source_Ptr
) return Node_Id
1442 -- Count number of non-family entries
1445 Ent
:= First_Entity
(Concurrent_Type
);
1446 while Present
(Ent
) loop
1447 if Ekind
(Ent
) = E_Entry
then
1454 Ecount
:= Make_Integer_Literal
(Loc
, Eindx
);
1456 -- Loop through entry families building the addition nodes
1458 Ent
:= First_Entity
(Concurrent_Type
);
1459 while Present
(Ent
) loop
1460 if Ekind
(Ent
) = E_Entry_Family
then
1461 Typ
:= Entry_Index_Type
(Ent
);
1462 Hi
:= Type_High_Bound
(Typ
);
1463 Lo
:= Type_Low_Bound
(Typ
);
1464 Large
:= Is_Potentially_Large_Family
1465 (Base_Type
(Typ
), Concurrent_Type
, Lo
, Hi
);
1468 Left_Opnd
=> Ecount
,
1470 Family_Size
(Loc
, Hi
, Lo
, Concurrent_Type
, Large
));
1477 end Build_Entry_Count_Expression
;
1479 ------------------------------
1480 -- Build_Master_Declaration --
1481 ------------------------------
1483 function Build_Master_Declaration
(Loc
: Source_Ptr
) return Node_Id
is
1484 Master_Decl
: Node_Id
;
1487 -- Generate a dummy master if tasks or tasking hierarchies are
1490 -- _Master : constant Integer := Library_Task_Level;
1492 if not Tasking_Allowed
1493 or else Restrictions
.Set
(No_Task_Hierarchy
)
1494 or else not RTE_Available
(RE_Current_Master
)
1497 Make_Object_Declaration
(Loc
,
1498 Defining_Identifier
=>
1499 Make_Defining_Identifier
(Loc
, Name_uMaster
),
1500 Constant_Present
=> True,
1501 Object_Definition
=>
1502 New_Occurrence_Of
(Standard_Integer
, Loc
),
1504 Make_Integer_Literal
(Loc
, Library_Task_Level
));
1507 -- _master : constant Integer := Current_Master.all;
1511 Make_Object_Declaration
(Loc
,
1512 Defining_Identifier
=>
1513 Make_Defining_Identifier
(Loc
, Name_uMaster
),
1514 Constant_Present
=> True,
1515 Object_Definition
=>
1516 New_Occurrence_Of
(Standard_Integer
, Loc
),
1518 Make_Explicit_Dereference
(Loc
,
1519 New_Occurrence_Of
(RTE
(RE_Current_Master
), Loc
)));
1523 end Build_Master_Declaration
;
1525 ---------------------------
1526 -- Build_Parameter_Block --
1527 ---------------------------
1529 function Build_Parameter_Block
1533 Decls
: List_Id
) return Entity_Id
1539 Has_Comp
: Boolean := False;
1543 Actual
:= First
(Actuals
);
1545 Formal
:= Defining_Identifier
(First
(Formals
));
1547 while Present
(Actual
) loop
1548 if not Is_Controlling_Actual
(Actual
) then
1551 -- type Ann is access all <actual-type>
1553 Comp_Nam
:= Make_Temporary
(Loc
, 'A');
1554 Set_Is_Param_Block_Component_Type
(Comp_Nam
);
1557 Make_Full_Type_Declaration
(Loc
,
1558 Defining_Identifier
=> Comp_Nam
,
1560 Make_Access_To_Object_Definition
(Loc
,
1561 All_Present
=> True,
1562 Constant_Present
=> Ekind
(Formal
) = E_In_Parameter
,
1563 Subtype_Indication
=>
1564 New_Occurrence_Of
(Etype
(Actual
), Loc
))));
1570 Make_Component_Declaration
(Loc
,
1571 Defining_Identifier
=>
1572 Make_Defining_Identifier
(Loc
, Chars
(Formal
)),
1573 Component_Definition
=>
1574 Make_Component_Definition
(Loc
,
1577 Subtype_Indication
=>
1578 New_Occurrence_Of
(Comp_Nam
, Loc
))));
1583 Next_Actual
(Actual
);
1584 Next_Formal_With_Extras
(Formal
);
1587 Rec_Nam
:= Make_Temporary
(Loc
, 'P');
1592 -- type Pnn is record
1597 -- where Pnn is a parameter wrapping record, Param1 .. ParamN are
1598 -- the original parameter names and Ann1 .. AnnN are the access to
1602 Make_Full_Type_Declaration
(Loc
,
1603 Defining_Identifier
=>
1606 Make_Record_Definition
(Loc
,
1608 Make_Component_List
(Loc
, Comps
))));
1611 -- type Pnn is null record;
1614 Make_Full_Type_Declaration
(Loc
,
1615 Defining_Identifier
=>
1618 Make_Record_Definition
(Loc
,
1619 Null_Present
=> True,
1620 Component_List
=> Empty
)));
1624 end Build_Parameter_Block
;
1626 --------------------------------------
1627 -- Build_Renamed_Formal_Declaration --
1628 --------------------------------------
1630 function Build_Renamed_Formal_Declaration
1634 Renamed_Formal
: Node_Id
) return Node_Id
1636 Loc
: constant Source_Ptr
:= Sloc
(New_F
);
1640 -- If the formal is a tagged incomplete type, it is already passed
1641 -- by reference, so it is sufficient to rename the pointer component
1642 -- that corresponds to the actual. Otherwise we need to dereference
1643 -- the pointer component to obtain the actual.
1645 if Is_Incomplete_Type
(Etype
(Formal
))
1646 and then Is_Tagged_Type
(Etype
(Formal
))
1649 Make_Object_Renaming_Declaration
(Loc
,
1650 Defining_Identifier
=> New_F
,
1651 Subtype_Mark
=> New_Occurrence_Of
(Etype
(Comp
), Loc
),
1652 Name
=> Renamed_Formal
);
1656 Make_Object_Renaming_Declaration
(Loc
,
1657 Defining_Identifier
=> New_F
,
1658 Subtype_Mark
=> New_Occurrence_Of
(Etype
(Formal
), Loc
),
1660 Make_Explicit_Dereference
(Loc
, Renamed_Formal
));
1664 end Build_Renamed_Formal_Declaration
;
1666 --------------------------
1667 -- Build_Wrapper_Bodies --
1668 --------------------------
1670 procedure Build_Wrapper_Bodies
1675 Rec_Typ
: Entity_Id
;
1677 function Build_Wrapper_Body
1679 Subp_Id
: Entity_Id
;
1680 Obj_Typ
: Entity_Id
;
1681 Formals
: List_Id
) return Node_Id
;
1682 -- Ada 2005 (AI-345): Build the body that wraps a primitive operation
1683 -- associated with a protected or task type. Subp_Id is the subprogram
1684 -- name which will be wrapped. Obj_Typ is the type of the new formal
1685 -- parameter which handles dispatching and object notation. Formals are
1686 -- the original formals of Subp_Id which will be explicitly replicated.
1688 ------------------------
1689 -- Build_Wrapper_Body --
1690 ------------------------
1692 function Build_Wrapper_Body
1694 Subp_Id
: Entity_Id
;
1695 Obj_Typ
: Entity_Id
;
1696 Formals
: List_Id
) return Node_Id
1698 Body_Spec
: Node_Id
;
1701 Body_Spec
:= Build_Wrapper_Spec
(Subp_Id
, Obj_Typ
, Formals
);
1703 -- The subprogram is not overriding or is not a primitive declared
1704 -- between two views.
1706 if No
(Body_Spec
) then
1711 Actuals
: List_Id
:= No_List
;
1713 First_Form
: Node_Id
;
1718 -- Map formals to actuals. Use the list built for the wrapper
1719 -- spec, skipping the object notation parameter.
1721 First_Form
:= First
(Parameter_Specifications
(Body_Spec
));
1723 Formal
:= First_Form
;
1726 if Present
(Formal
) then
1727 Actuals
:= New_List
;
1728 while Present
(Formal
) loop
1730 Make_Identifier
(Loc
,
1731 Chars
=> Chars
(Defining_Identifier
(Formal
))));
1736 -- Special processing for primitives declared between a private
1737 -- type and its completion: the wrapper needs a properly typed
1738 -- parameter if the wrapped operation has a controlling first
1739 -- parameter. Note that this might not be the case for a function
1740 -- with a controlling result.
1742 if Is_Private_Primitive_Subprogram
(Subp_Id
) then
1743 if No
(Actuals
) then
1744 Actuals
:= New_List
;
1747 if Is_Controlling_Formal
(First_Formal
(Subp_Id
)) then
1748 Prepend_To
(Actuals
,
1749 Unchecked_Convert_To
1750 (Corresponding_Concurrent_Type
(Obj_Typ
),
1751 Make_Identifier
(Loc
, Name_uO
)));
1754 Prepend_To
(Actuals
,
1755 Make_Identifier
(Loc
,
1756 Chars
=> Chars
(Defining_Identifier
(First_Form
))));
1759 Nam
:= New_Occurrence_Of
(Subp_Id
, Loc
);
1761 -- An access-to-variable object parameter requires an explicit
1762 -- dereference in the unchecked conversion. This case occurs
1763 -- when a protected entry wrapper must override an interface
1764 -- level procedure with interface access as first parameter.
1766 -- O.all.Subp_Id (Formal_1, ..., Formal_N)
1768 if Nkind
(Parameter_Type
(First_Form
)) =
1772 Make_Explicit_Dereference
(Loc
,
1773 Prefix
=> Make_Identifier
(Loc
, Name_uO
));
1775 Conv_Id
:= Make_Identifier
(Loc
, Name_uO
);
1779 Make_Selected_Component
(Loc
,
1781 Unchecked_Convert_To
1782 (Corresponding_Concurrent_Type
(Obj_Typ
), Conv_Id
),
1783 Selector_Name
=> New_Occurrence_Of
(Subp_Id
, Loc
));
1786 -- Create the subprogram body. For a function, the call to the
1787 -- actual subprogram has to be converted to the corresponding
1788 -- record if it is a controlling result.
1790 if Ekind
(Subp_Id
) = E_Function
then
1796 Make_Function_Call
(Loc
,
1798 Parameter_Associations
=> Actuals
);
1800 if Has_Controlling_Result
(Subp_Id
) then
1802 Unchecked_Convert_To
1803 (Corresponding_Record_Type
(Etype
(Subp_Id
)), Res
);
1807 Make_Subprogram_Body
(Loc
,
1808 Specification
=> Body_Spec
,
1809 Declarations
=> Empty_List
,
1810 Handled_Statement_Sequence
=>
1811 Make_Handled_Sequence_Of_Statements
(Loc
,
1812 Statements
=> New_List
(
1813 Make_Simple_Return_Statement
(Loc
, Res
))));
1818 Make_Subprogram_Body
(Loc
,
1819 Specification
=> Body_Spec
,
1820 Declarations
=> Empty_List
,
1821 Handled_Statement_Sequence
=>
1822 Make_Handled_Sequence_Of_Statements
(Loc
,
1823 Statements
=> New_List
(
1824 Make_Procedure_Call_Statement
(Loc
,
1826 Parameter_Associations
=> Actuals
))));
1829 end Build_Wrapper_Body
;
1831 -- Start of processing for Build_Wrapper_Bodies
1834 if Is_Concurrent_Type
(Typ
) then
1835 Rec_Typ
:= Corresponding_Record_Type
(Typ
);
1840 -- Generate wrapper bodies for a concurrent type which implements an
1843 if Present
(Interfaces
(Rec_Typ
)) then
1845 Insert_Nod
: Node_Id
;
1847 Prim_Elmt
: Elmt_Id
;
1848 Prim_Decl
: Node_Id
;
1850 Wrap_Body
: Node_Id
;
1851 Wrap_Id
: Entity_Id
;
1856 -- Examine all primitive operations of the corresponding record
1857 -- type, looking for wrapper specs. Generate bodies in order to
1860 Prim_Elmt
:= First_Elmt
(Primitive_Operations
(Rec_Typ
));
1861 while Present
(Prim_Elmt
) loop
1862 Prim
:= Node
(Prim_Elmt
);
1864 if (Ekind
(Prim
) = E_Function
1865 or else Ekind
(Prim
) = E_Procedure
)
1866 and then Is_Primitive_Wrapper
(Prim
)
1868 Subp
:= Wrapped_Entity
(Prim
);
1869 Prim_Decl
:= Parent
(Parent
(Prim
));
1872 Build_Wrapper_Body
(Loc
,
1875 Formals
=> Parameter_Specifications
(Parent
(Subp
)));
1876 Wrap_Id
:= Defining_Unit_Name
(Specification
(Wrap_Body
));
1878 Set_Corresponding_Spec
(Wrap_Body
, Prim
);
1879 Set_Corresponding_Body
(Prim_Decl
, Wrap_Id
);
1881 Insert_After
(Insert_Nod
, Wrap_Body
);
1882 Insert_Nod
:= Wrap_Body
;
1884 Analyze
(Wrap_Body
);
1887 Next_Elmt
(Prim_Elmt
);
1891 end Build_Wrapper_Bodies
;
1893 ------------------------
1894 -- Build_Wrapper_Spec --
1895 ------------------------
1897 function Build_Wrapper_Spec
1898 (Subp_Id
: Entity_Id
;
1899 Obj_Typ
: Entity_Id
;
1900 Formals
: List_Id
) return Node_Id
1902 function Overriding_Possible
1903 (Iface_Op
: Entity_Id
;
1904 Wrapper
: Entity_Id
) return Boolean;
1905 -- Determine whether a primitive operation can be overridden by Wrapper.
1906 -- Iface_Op is the candidate primitive operation of an interface type,
1907 -- Wrapper is the generated entry wrapper.
1909 function Replicate_Formals
1911 Formals
: List_Id
) return List_Id
;
1912 -- An explicit parameter replication is required due to the Is_Entry_
1913 -- Formal flag being set for all the formals of an entry. The explicit
1914 -- replication removes the flag that would otherwise cause a different
1915 -- path of analysis.
1917 -------------------------
1918 -- Overriding_Possible --
1919 -------------------------
1921 function Overriding_Possible
1922 (Iface_Op
: Entity_Id
;
1923 Wrapper
: Entity_Id
) return Boolean
1925 Iface_Op_Spec
: constant Node_Id
:= Parent
(Iface_Op
);
1926 Wrapper_Spec
: constant Node_Id
:= Parent
(Wrapper
);
1928 function Type_Conformant_Parameters
1929 (Iface_Op_Params
: List_Id
;
1930 Wrapper_Params
: List_Id
) return Boolean;
1931 -- Determine whether the parameters of the generated entry wrapper
1932 -- and those of a primitive operation are type conformant. During
1933 -- this check, the first parameter of the primitive operation is
1934 -- skipped if it is a controlling argument: protected functions
1935 -- may have a controlling result.
1937 --------------------------------
1938 -- Type_Conformant_Parameters --
1939 --------------------------------
1941 function Type_Conformant_Parameters
1942 (Iface_Op_Params
: List_Id
;
1943 Wrapper_Params
: List_Id
) return Boolean
1945 Iface_Op_Param
: Node_Id
;
1946 Iface_Op_Typ
: Entity_Id
;
1947 Wrapper_Param
: Node_Id
;
1948 Wrapper_Typ
: Entity_Id
;
1951 -- Skip the first (controlling) parameter of primitive operation
1953 Iface_Op_Param
:= First
(Iface_Op_Params
);
1955 if Present
(First_Formal
(Iface_Op
))
1956 and then Is_Controlling_Formal
(First_Formal
(Iface_Op
))
1958 Next
(Iface_Op_Param
);
1961 Wrapper_Param
:= First
(Wrapper_Params
);
1962 while Present
(Iface_Op_Param
)
1963 and then Present
(Wrapper_Param
)
1965 Iface_Op_Typ
:= Find_Parameter_Type
(Iface_Op_Param
);
1966 Wrapper_Typ
:= Find_Parameter_Type
(Wrapper_Param
);
1968 -- The two parameters must be mode conformant
1970 if not Conforming_Types
1971 (Iface_Op_Typ
, Wrapper_Typ
, Mode_Conformant
)
1976 Next
(Iface_Op_Param
);
1977 Next
(Wrapper_Param
);
1980 -- One of the lists is longer than the other
1982 if Present
(Iface_Op_Param
) or else Present
(Wrapper_Param
) then
1987 end Type_Conformant_Parameters
;
1989 -- Start of processing for Overriding_Possible
1992 if Chars
(Iface_Op
) /= Chars
(Wrapper
) then
1996 -- If an inherited subprogram is implemented by a protected procedure
1997 -- or an entry, then the first parameter of the inherited subprogram
1998 -- must be of mode OUT or IN OUT, or access-to-variable parameter.
2000 if Ekind
(Iface_Op
) = E_Procedure
2001 and then Present
(Parameter_Specifications
(Iface_Op_Spec
))
2004 Obj_Param
: constant Node_Id
:=
2005 First
(Parameter_Specifications
(Iface_Op_Spec
));
2007 if not Out_Present
(Obj_Param
)
2008 and then Nkind
(Parameter_Type
(Obj_Param
)) /=
2017 Type_Conformant_Parameters
2018 (Parameter_Specifications
(Iface_Op_Spec
),
2019 Parameter_Specifications
(Wrapper_Spec
));
2020 end Overriding_Possible
;
2022 -----------------------
2023 -- Replicate_Formals --
2024 -----------------------
2026 function Replicate_Formals
2028 Formals
: List_Id
) return List_Id
2030 New_Formals
: constant List_Id
:= New_List
;
2032 Param_Type
: Node_Id
;
2035 Formal
:= First
(Formals
);
2037 -- Skip the object parameter when dealing with primitives declared
2038 -- between two views.
2040 if Is_Private_Primitive_Subprogram
(Subp_Id
)
2041 and then not Has_Controlling_Result
(Subp_Id
)
2046 while Present
(Formal
) loop
2048 -- Create an explicit copy of the entry parameter
2050 -- When creating the wrapper subprogram for a primitive operation
2051 -- of a protected interface we must construct an equivalent
2052 -- signature to that of the overriding operation. For regular
2053 -- parameters we can just use the type of the formal, but for
2054 -- access to subprogram parameters we need to reanalyze the
2055 -- parameter type to create local entities for the signature of
2056 -- the subprogram type. Using the entities of the overriding
2057 -- subprogram will result in out-of-scope errors in the back-end.
2059 if Nkind
(Parameter_Type
(Formal
)) = N_Access_Definition
then
2060 Param_Type
:= Copy_Separate_Tree
(Parameter_Type
(Formal
));
2063 New_Occurrence_Of
(Etype
(Parameter_Type
(Formal
)), Loc
);
2066 Append_To
(New_Formals
,
2067 Make_Parameter_Specification
(Loc
,
2068 Defining_Identifier
=>
2069 Make_Defining_Identifier
(Loc
,
2070 Chars
=> Chars
(Defining_Identifier
(Formal
))),
2071 In_Present
=> In_Present
(Formal
),
2072 Out_Present
=> Out_Present
(Formal
),
2073 Null_Exclusion_Present
=> Null_Exclusion_Present
(Formal
),
2074 Parameter_Type
=> Param_Type
));
2080 end Replicate_Formals
;
2084 Loc
: constant Source_Ptr
:= Sloc
(Subp_Id
);
2085 First_Param
: Node_Id
:= Empty
;
2087 Iface_Elmt
: Elmt_Id
;
2088 Iface_Op
: Entity_Id
;
2089 Iface_Op_Elmt
: Elmt_Id
;
2090 Overridden_Subp
: Entity_Id
;
2092 -- Start of processing for Build_Wrapper_Spec
2095 -- No point in building wrappers for untagged concurrent types
2097 pragma Assert
(Is_Tagged_Type
(Obj_Typ
));
2099 -- Check if this subprogram has a profile that matches some interface
2102 Check_Synchronized_Overriding
(Subp_Id
, Overridden_Subp
);
2104 if Present
(Overridden_Subp
) then
2106 First
(Parameter_Specifications
(Parent
(Overridden_Subp
)));
2108 -- An entry or a protected procedure can override a routine where the
2109 -- controlling formal is either IN OUT, OUT or is of access-to-variable
2110 -- type. Since the wrapper must have the exact same signature as that of
2111 -- the overridden subprogram, we try to find the overriding candidate
2112 -- and use its controlling formal.
2114 -- Check every implemented interface
2116 elsif Present
(Interfaces
(Obj_Typ
)) then
2117 Iface_Elmt
:= First_Elmt
(Interfaces
(Obj_Typ
));
2118 Search
: while Present
(Iface_Elmt
) loop
2119 Iface
:= Node
(Iface_Elmt
);
2121 -- Check every interface primitive
2123 if Present
(Primitive_Operations
(Iface
)) then
2124 Iface_Op_Elmt
:= First_Elmt
(Primitive_Operations
(Iface
));
2125 while Present
(Iface_Op_Elmt
) loop
2126 Iface_Op
:= Node
(Iface_Op_Elmt
);
2128 -- Ignore predefined primitives
2130 if not Is_Predefined_Dispatching_Operation
(Iface_Op
) then
2131 Iface_Op
:= Ultimate_Alias
(Iface_Op
);
2133 -- The current primitive operation can be overridden by
2134 -- the generated entry wrapper.
2136 if Overriding_Possible
(Iface_Op
, Subp_Id
) then
2138 First
(Parameter_Specifications
(Parent
(Iface_Op
)));
2144 Next_Elmt
(Iface_Op_Elmt
);
2148 Next_Elmt
(Iface_Elmt
);
2152 -- Do not generate the wrapper if no interface primitive is covered by
2153 -- the subprogram and it is not a primitive declared between two views
2154 -- (see Process_Full_View).
2157 and then not Is_Private_Primitive_Subprogram
(Subp_Id
)
2163 Wrapper_Id
: constant Entity_Id
:=
2164 Make_Defining_Identifier
(Loc
, Chars
(Subp_Id
));
2165 New_Formals
: List_Id
;
2166 Obj_Param
: Node_Id
;
2167 Obj_Param_Typ
: Entity_Id
;
2170 -- Minimum decoration is needed to catch the entity in
2171 -- Sem_Ch6.Override_Dispatching_Operation.
2173 if Ekind
(Subp_Id
) = E_Function
then
2174 Mutate_Ekind
(Wrapper_Id
, E_Function
);
2176 Mutate_Ekind
(Wrapper_Id
, E_Procedure
);
2179 Set_Is_Primitive_Wrapper
(Wrapper_Id
);
2180 Set_Wrapped_Entity
(Wrapper_Id
, Subp_Id
);
2181 Set_Is_Private_Primitive
(Wrapper_Id
,
2182 Is_Private_Primitive_Subprogram
(Subp_Id
));
2184 -- Process the formals
2186 New_Formals
:= Replicate_Formals
(Loc
, Formals
);
2188 -- A function with a controlling result and no first controlling
2189 -- formal needs no additional parameter.
2191 if Has_Controlling_Result
(Subp_Id
)
2193 (No
(First_Formal
(Subp_Id
))
2194 or else not Is_Controlling_Formal
(First_Formal
(Subp_Id
)))
2198 -- Routine Subp_Id has been found to override an interface primitive.
2199 -- If the interface operation has an access parameter, create a copy
2200 -- of it, with the same null exclusion indicator if present.
2202 elsif Present
(First_Param
) then
2203 if Nkind
(Parameter_Type
(First_Param
)) = N_Access_Definition
then
2205 Make_Access_Definition
(Loc
,
2207 New_Occurrence_Of
(Obj_Typ
, Loc
),
2208 Null_Exclusion_Present
=>
2209 Null_Exclusion_Present
(Parameter_Type
(First_Param
)),
2211 Constant_Present
(Parameter_Type
(First_Param
)));
2213 Obj_Param_Typ
:= New_Occurrence_Of
(Obj_Typ
, Loc
);
2217 Make_Parameter_Specification
(Loc
,
2218 Defining_Identifier
=>
2219 Make_Defining_Identifier
(Loc
,
2221 In_Present
=> In_Present
(First_Param
),
2222 Out_Present
=> Out_Present
(First_Param
),
2223 Parameter_Type
=> Obj_Param_Typ
);
2225 Prepend_To
(New_Formals
, Obj_Param
);
2227 -- If we are dealing with a primitive declared between two views,
2228 -- implemented by a synchronized operation, we need to create
2229 -- a default parameter. The mode of the parameter must match that
2230 -- of the primitive operation.
2233 pragma Assert
(Is_Private_Primitive_Subprogram
(Subp_Id
));
2236 Make_Parameter_Specification
(Loc
,
2237 Defining_Identifier
=>
2238 Make_Defining_Identifier
(Loc
, Name_uO
),
2240 In_Present
(Parent
(First_Entity
(Subp_Id
))),
2241 Out_Present
=> Ekind
(Subp_Id
) /= E_Function
,
2242 Parameter_Type
=> New_Occurrence_Of
(Obj_Typ
, Loc
));
2244 Prepend_To
(New_Formals
, Obj_Param
);
2247 -- Build the final spec. If it is a function with a controlling
2248 -- result, it is a primitive operation of the corresponding
2249 -- record type, so mark the spec accordingly.
2251 if Ekind
(Subp_Id
) = E_Function
then
2256 if Has_Controlling_Result
(Subp_Id
) then
2259 (Corresponding_Record_Type
(Etype
(Subp_Id
)), Loc
);
2261 Res_Def
:= New_Copy
(Result_Definition
(Parent
(Subp_Id
)));
2265 Make_Function_Specification
(Loc
,
2266 Defining_Unit_Name
=> Wrapper_Id
,
2267 Parameter_Specifications
=> New_Formals
,
2268 Result_Definition
=> Res_Def
);
2272 Make_Procedure_Specification
(Loc
,
2273 Defining_Unit_Name
=> Wrapper_Id
,
2274 Parameter_Specifications
=> New_Formals
);
2277 end Build_Wrapper_Spec
;
2279 -------------------------
2280 -- Build_Wrapper_Specs --
2281 -------------------------
2283 procedure Build_Wrapper_Specs
2289 Rec_Typ
: Entity_Id
;
2290 procedure Scan_Declarations
(L
: List_Id
);
2291 -- Common processing for visible and private declarations
2292 -- of a protected type.
2294 procedure Scan_Declarations
(L
: List_Id
) is
2296 Wrap_Decl
: Node_Id
;
2297 Wrap_Spec
: Node_Id
;
2305 while Present
(Decl
) loop
2308 if Nkind
(Decl
) = N_Entry_Declaration
2309 and then Ekind
(Defining_Identifier
(Decl
)) = E_Entry
2313 (Subp_Id
=> Defining_Identifier
(Decl
),
2315 Formals
=> Parameter_Specifications
(Decl
));
2317 elsif Nkind
(Decl
) = N_Subprogram_Declaration
then
2320 (Subp_Id
=> Defining_Unit_Name
(Specification
(Decl
)),
2323 Parameter_Specifications
(Specification
(Decl
)));
2326 if Present
(Wrap_Spec
) then
2328 Make_Subprogram_Declaration
(Loc
,
2329 Specification
=> Wrap_Spec
);
2331 Insert_After
(N
, Wrap_Decl
);
2334 Analyze
(Wrap_Decl
);
2339 end Scan_Declarations
;
2341 -- start of processing for Build_Wrapper_Specs
2344 if Is_Protected_Type
(Typ
) then
2345 Def
:= Protected_Definition
(Parent
(Typ
));
2346 else pragma Assert
(Is_Task_Type
(Typ
));
2347 Def
:= Task_Definition
(Parent
(Typ
));
2350 Rec_Typ
:= Corresponding_Record_Type
(Typ
);
2352 -- Generate wrapper specs for a concurrent type which implements an
2353 -- interface. Operations in both the visible and private parts may
2354 -- implement progenitor operations.
2356 if Present
(Interfaces
(Rec_Typ
)) and then Present
(Def
) then
2357 Scan_Declarations
(Visible_Declarations
(Def
));
2358 Scan_Declarations
(Private_Declarations
(Def
));
2360 end Build_Wrapper_Specs
;
2362 ---------------------------
2363 -- Build_Find_Body_Index --
2364 ---------------------------
2366 function Build_Find_Body_Index
(Typ
: Entity_Id
) return Node_Id
is
2367 Loc
: constant Source_Ptr
:= Sloc
(Typ
);
2370 Has_F
: Boolean := False;
2372 If_St
: Node_Id
:= Empty
;
2375 Decls
: List_Id
:= New_List
;
2376 Ret
: Node_Id
:= Empty
;
2378 Siz
: Node_Id
:= Empty
;
2380 procedure Add_If_Clause
(Expr
: Node_Id
);
2381 -- Add test for range of current entry
2383 function Convert_Discriminant_Ref
(Bound
: Node_Id
) return Node_Id
;
2384 -- If a bound of an entry is given by a discriminant, retrieve the
2385 -- actual value of the discriminant from the enclosing object.
2391 procedure Add_If_Clause
(Expr
: Node_Id
) is
2393 Stats
: constant List_Id
:=
2395 Make_Simple_Return_Statement
(Loc
,
2396 Expression
=> Make_Integer_Literal
(Loc
, Index
+ 1)));
2399 -- Index for current entry body
2403 -- Compute total length of entry queues so far
2411 Right_Opnd
=> Expr
);
2416 Left_Opnd
=> Make_Identifier
(Loc
, Name_uE
),
2419 -- Map entry queue indexes in the range of the current family
2420 -- into the current index, that designates the entry body.
2424 Make_Implicit_If_Statement
(Typ
,
2426 Then_Statements
=> Stats
,
2427 Elsif_Parts
=> New_List
);
2431 Append_To
(Elsif_Parts
(If_St
),
2432 Make_Elsif_Part
(Loc
,
2434 Then_Statements
=> Stats
));
2438 ------------------------------
2439 -- Convert_Discriminant_Ref --
2440 ------------------------------
2442 function Convert_Discriminant_Ref
(Bound
: Node_Id
) return Node_Id
is
2446 if Is_Entity_Name
(Bound
)
2447 and then Ekind
(Entity
(Bound
)) = E_Discriminant
2450 Make_Selected_Component
(Loc
,
2452 Unchecked_Convert_To
(Corresponding_Record_Type
(Typ
),
2453 Make_Explicit_Dereference
(Loc
,
2454 Make_Identifier
(Loc
, Name_uObject
))),
2455 Selector_Name
=> Make_Identifier
(Loc
, Chars
(Bound
)));
2456 Set_Etype
(B
, Etype
(Entity
(Bound
)));
2458 B
:= New_Copy_Tree
(Bound
);
2462 end Convert_Discriminant_Ref
;
2464 -- Start of processing for Build_Find_Body_Index
2467 Spec
:= Build_Find_Body_Index_Spec
(Typ
);
2469 Ent
:= First_Entity
(Typ
);
2470 while Present
(Ent
) loop
2471 if Ekind
(Ent
) = E_Entry_Family
then
2481 -- If the protected type has no entry families, there is a one-one
2482 -- correspondence between entry queue and entry body.
2485 Make_Simple_Return_Statement
(Loc
,
2486 Expression
=> Make_Identifier
(Loc
, Name_uE
));
2489 -- Suppose entries e1, e2, ... have size l1, l2, ... we generate
2492 -- if E <= l1 then return 1;
2493 -- elsif E <= l1 + l2 then return 2;
2498 Ent
:= First_Entity
(Typ
);
2500 Add_Object_Pointer
(Loc
, Typ
, Decls
);
2502 while Present
(Ent
) loop
2503 if Ekind
(Ent
) = E_Entry
then
2504 Add_If_Clause
(Make_Integer_Literal
(Loc
, 1));
2506 elsif Ekind
(Ent
) = E_Entry_Family
then
2507 E_Typ
:= Entry_Index_Type
(Ent
);
2508 Hi
:= Convert_Discriminant_Ref
(Type_High_Bound
(E_Typ
));
2509 Lo
:= Convert_Discriminant_Ref
(Type_Low_Bound
(E_Typ
));
2510 Add_If_Clause
(Family_Size
(Loc
, Hi
, Lo
, Typ
, False));
2519 Make_Simple_Return_Statement
(Loc
,
2520 Expression
=> Make_Integer_Literal
(Loc
, 1));
2523 -- Ranges are in increasing order, so last one doesn't need guard
2526 Nod
: constant Node_Id
:= Last
(Elsif_Parts
(Ret
));
2529 Set_Else_Statements
(Ret
, Then_Statements
(Nod
));
2531 -- If Elsif_Parts becomes empty then remove it entirely, as
2532 -- otherwise we would violate the invariant of If_Statement
2533 -- node described in Sinfo.
2535 if Is_Empty_List
(Elsif_Parts
(Ret
)) then
2536 pragma Assert
(Elsif_Parts
(Ret
) /= No_List
);
2537 Set_Elsif_Parts
(Ret
, No_List
);
2544 Make_Subprogram_Body
(Loc
,
2545 Specification
=> Spec
,
2546 Declarations
=> Decls
,
2547 Handled_Statement_Sequence
=>
2548 Make_Handled_Sequence_Of_Statements
(Loc
,
2549 Statements
=> New_List
(Ret
)));
2550 end Build_Find_Body_Index
;
2552 --------------------------------
2553 -- Build_Find_Body_Index_Spec --
2554 --------------------------------
2556 function Build_Find_Body_Index_Spec
(Typ
: Entity_Id
) return Node_Id
is
2557 Loc
: constant Source_Ptr
:= Sloc
(Typ
);
2558 Id
: constant Entity_Id
:=
2559 Make_Defining_Identifier
(Loc
,
2560 Chars
=> New_External_Name
(Chars
(Typ
), 'F'));
2561 Parm1
: constant Entity_Id
:= Make_Defining_Identifier
(Loc
, Name_uO
);
2562 Parm2
: constant Entity_Id
:= Make_Defining_Identifier
(Loc
, Name_uE
);
2566 Make_Function_Specification
(Loc
,
2567 Defining_Unit_Name
=> Id
,
2568 Parameter_Specifications
=> New_List
(
2569 Make_Parameter_Specification
(Loc
,
2570 Defining_Identifier
=> Parm1
,
2572 New_Occurrence_Of
(RTE
(RE_Address
), Loc
)),
2574 Make_Parameter_Specification
(Loc
,
2575 Defining_Identifier
=> Parm2
,
2577 New_Occurrence_Of
(RTE
(RE_Protected_Entry_Index
), Loc
))),
2579 Result_Definition
=> New_Occurrence_Of
(
2580 RTE
(RE_Protected_Entry_Index
), Loc
));
2581 end Build_Find_Body_Index_Spec
;
2583 -----------------------------------------------
2584 -- Build_Lock_Free_Protected_Subprogram_Body --
2585 -----------------------------------------------
2587 function Build_Lock_Free_Protected_Subprogram_Body
2590 Unprot_Spec
: Node_Id
) return Node_Id
2592 Actuals
: constant List_Id
:= New_List
;
2593 Loc
: constant Source_Ptr
:= Sloc
(N
);
2594 Spec
: constant Node_Id
:= Specification
(N
);
2595 Unprot_Id
: constant Entity_Id
:= Defining_Unit_Name
(Unprot_Spec
);
2597 Prot_Spec
: Node_Id
;
2601 -- Create the protected version of the body
2604 Build_Protected_Sub_Specification
(N
, Prot_Typ
, Protected_Mode
);
2606 -- Build the actual parameters which appear in the call to the
2607 -- unprotected version of the body.
2609 Formal
:= First
(Parameter_Specifications
(Prot_Spec
));
2610 while Present
(Formal
) loop
2612 Make_Identifier
(Loc
, Chars
(Defining_Identifier
(Formal
))));
2617 -- Function case, generate:
2618 -- return <Unprot_Func_Call>;
2620 if Nkind
(Spec
) = N_Function_Specification
then
2622 Make_Simple_Return_Statement
(Loc
,
2624 Make_Function_Call
(Loc
,
2626 Make_Identifier
(Loc
, Chars
(Unprot_Id
)),
2627 Parameter_Associations
=> Actuals
));
2629 -- Procedure case, call the unprotected version
2633 Make_Procedure_Call_Statement
(Loc
,
2635 Make_Identifier
(Loc
, Chars
(Unprot_Id
)),
2636 Parameter_Associations
=> Actuals
);
2640 Make_Subprogram_Body
(Loc
,
2641 Declarations
=> Empty_List
,
2642 Specification
=> Prot_Spec
,
2643 Handled_Statement_Sequence
=>
2644 Make_Handled_Sequence_Of_Statements
(Loc
,
2645 Statements
=> New_List
(Stmt
)));
2646 end Build_Lock_Free_Protected_Subprogram_Body
;
2648 -------------------------------------------------
2649 -- Build_Lock_Free_Unprotected_Subprogram_Body --
2650 -------------------------------------------------
2652 -- Procedures which meet the lock-free implementation requirements and
2653 -- reference a unique scalar component Comp are expanded in the following
2656 -- procedure P (...) is
2657 -- Expected_Comp : constant Comp_Type :=
2659 -- (System.Atomic_Primitives.Lock_Free_Read_N
2660 -- (_Object.Comp'Address));
2664 -- <original declarations before the object renaming declaration
2667 -- Desired_Comp : Comp_Type := Expected_Comp;
2668 -- Comp : Comp_Type renames Desired_Comp;
2670 -- <original declarations after the object renaming declaration
2674 -- <original statements>
2675 -- exit when System.Atomic_Primitives.Lock_Free_Try_Write_N
2676 -- (_Object.Comp'Address,
2677 -- Interfaces.Unsigned_N (Expected_Comp),
2678 -- Interfaces.Unsigned_N (Desired_Comp));
2683 -- Each return and raise statement of P is transformed into an atomic
2686 -- if System.Atomic_Primitives.Lock_Free_Try_Write_N
2687 -- (_Object.Comp'Address,
2688 -- Interfaces.Unsigned_N (Expected_Comp),
2689 -- Interfaces.Unsigned_N (Desired_Comp));
2691 -- <original statement>
2696 -- Functions which meet the lock-free implementation requirements and
2697 -- reference a unique scalar component Comp are expanded in the following
2700 -- function F (...) return ... is
2701 -- <original declarations before the object renaming declaration
2704 -- Expected_Comp : constant Comp_Type :=
2706 -- (System.Atomic_Primitives.Lock_Free_Read_N
2707 -- (_Object.Comp'Address));
2708 -- Comp : Comp_Type renames Expected_Comp;
2710 -- <original declarations after the object renaming declaration of
2714 -- <original statements>
2717 function Build_Lock_Free_Unprotected_Subprogram_Body
2719 Prot_Typ
: Node_Id
) return Node_Id
2721 function Referenced_Component
(N
: Node_Id
) return Entity_Id
;
2722 -- Subprograms which meet the lock-free implementation criteria are
2723 -- allowed to reference only one unique component. Return the prival
2724 -- of the said component.
2726 --------------------------
2727 -- Referenced_Component --
2728 --------------------------
2730 function Referenced_Component
(N
: Node_Id
) return Entity_Id
is
2733 Source_Comp
: Entity_Id
:= Empty
;
2736 -- Find the unique source component which N references in its
2739 for Index
in 1 .. Lock_Free_Subprogram_Table
.Last
loop
2741 Element
: Lock_Free_Subprogram
renames
2742 Lock_Free_Subprogram_Table
.Table
(Index
);
2744 if Element
.Sub_Body
= N
then
2745 Source_Comp
:= Element
.Comp_Id
;
2751 if No
(Source_Comp
) then
2755 -- Find the prival which corresponds to the source component within
2756 -- the declarations of N.
2758 Decl
:= First
(Declarations
(N
));
2759 while Present
(Decl
) loop
2761 -- Privals appear as object renamings
2763 if Nkind
(Decl
) = N_Object_Renaming_Declaration
then
2764 Comp
:= Defining_Identifier
(Decl
);
2766 if Present
(Prival_Link
(Comp
))
2767 and then Prival_Link
(Comp
) = Source_Comp
2777 end Referenced_Component
;
2781 Comp
: constant Entity_Id
:= Referenced_Component
(N
);
2782 Loc
: constant Source_Ptr
:= Sloc
(N
);
2783 Hand_Stmt_Seq
: Node_Id
:= Handled_Statement_Sequence
(N
);
2784 Decls
: List_Id
:= Declarations
(N
);
2786 -- Start of processing for Build_Lock_Free_Unprotected_Subprogram_Body
2789 -- Add renamings for the protection object, discriminals, privals, and
2790 -- the entry index constant for use by debugger.
2792 Debug_Private_Data_Declarations
(Decls
);
2794 -- Perform the lock-free expansion when the subprogram references a
2795 -- protected component.
2797 if Present
(Comp
) then
2798 Protected_Component_Ref
: declare
2799 Comp_Decl
: constant Node_Id
:= Parent
(Comp
);
2800 Comp_Sel_Nam
: constant Node_Id
:= Name
(Comp_Decl
);
2801 Comp_Type
: constant Entity_Id
:= Etype
(Comp
);
2803 Is_Procedure
: constant Boolean :=
2804 Ekind
(Corresponding_Spec
(N
)) = E_Procedure
;
2805 -- Indicates if N is a protected procedure body
2807 Block_Decls
: List_Id
:= No_List
;
2808 Try_Write
: Entity_Id
;
2809 Desired_Comp
: Entity_Id
;
2812 Label_Id
: Entity_Id
:= Empty
;
2814 Expected_Comp
: Entity_Id
;
2817 New_Copy_List_Tree
(Statements
(Hand_Stmt_Seq
));
2819 Unsigned
: Entity_Id
;
2821 function Process_Node
(N
: Node_Id
) return Traverse_Result
;
2822 -- Transform a single node if it is a return statement, a raise
2823 -- statement or a reference to Comp.
2825 procedure Process_Stmts
(Stmts
: List_Id
);
2826 -- Given a statement sequence Stmts, wrap any return or raise
2827 -- statements in the following manner:
2829 -- if System.Atomic_Primitives.Lock_Free_Try_Write_N
2830 -- (_Object.Comp'Address,
2831 -- Interfaces.Unsigned_N (Expected_Comp),
2832 -- Interfaces.Unsigned_N (Desired_Comp))
2843 function Process_Node
(N
: Node_Id
) return Traverse_Result
is
2845 procedure Wrap_Statement
(Stmt
: Node_Id
);
2846 -- Wrap an arbitrary statement inside an if statement where the
2847 -- condition does an atomic check on the state of the object.
2849 --------------------
2850 -- Wrap_Statement --
2851 --------------------
2853 procedure Wrap_Statement
(Stmt
: Node_Id
) is
2855 -- The first time through, create the declaration of a label
2856 -- which is used to skip the remainder of source statements
2857 -- if the state of the object has changed.
2859 if No
(Label_Id
) then
2861 Make_Identifier
(Loc
, New_External_Name
('L', 0));
2862 Set_Entity
(Label_Id
,
2863 Make_Defining_Identifier
(Loc
, Chars
(Label_Id
)));
2867 -- if System.Atomic_Primitives.Lock_Free_Try_Write_N
2868 -- (_Object.Comp'Address,
2869 -- Interfaces.Unsigned_N (Expected_Comp),
2870 -- Interfaces.Unsigned_N (Desired_Comp))
2878 Make_Implicit_If_Statement
(N
,
2880 Make_Function_Call
(Loc
,
2882 New_Occurrence_Of
(Try_Write
, Loc
),
2883 Parameter_Associations
=> New_List
(
2884 Make_Attribute_Reference
(Loc
,
2885 Prefix
=> Relocate_Node
(Comp_Sel_Nam
),
2886 Attribute_Name
=> Name_Address
),
2888 Unchecked_Convert_To
(Unsigned
,
2889 New_Occurrence_Of
(Expected_Comp
, Loc
)),
2891 Unchecked_Convert_To
(Unsigned
,
2892 New_Occurrence_Of
(Desired_Comp
, Loc
)))),
2894 Then_Statements
=> New_List
(Relocate_Node
(Stmt
)),
2896 Else_Statements
=> New_List
(
2897 Make_Goto_Statement
(Loc
,
2899 New_Occurrence_Of
(Entity
(Label_Id
), Loc
)))));
2902 -- Start of processing for Process_Node
2905 -- Wrap each return and raise statement that appear inside a
2906 -- procedure. Skip the last return statement which is added by
2907 -- default since it is transformed into an exit statement.
2910 and then ((Nkind
(N
) = N_Simple_Return_Statement
2911 and then N
/= Last
(Stmts
))
2912 or else Nkind
(N
) = N_Extended_Return_Statement
2913 or else (Nkind
(N
) in
2914 N_Raise_xxx_Error | N_Raise_Statement
2915 and then Comes_From_Source
(N
)))
2923 Set_Analyzed
(N
, False);
2928 procedure Process_Nodes
is new Traverse_Proc
(Process_Node
);
2934 procedure Process_Stmts
(Stmts
: List_Id
) is
2937 Stmt
:= First
(Stmts
);
2938 while Present
(Stmt
) loop
2939 Process_Nodes
(Stmt
);
2944 -- Start of processing for Protected_Component_Ref
2947 -- Get the type size
2949 if Known_Static_Esize
(Comp_Type
) then
2950 Typ_Size
:= UI_To_Int
(Esize
(Comp_Type
));
2952 -- If the Esize (Object_Size) is unknown at compile time, look at
2953 -- the RM_Size (Value_Size) since it may have been set by an
2954 -- explicit representation clause.
2956 elsif Known_Static_RM_Size
(Comp_Type
) then
2957 Typ_Size
:= UI_To_Int
(RM_Size
(Comp_Type
));
2959 -- Should not happen since this has already been checked in
2960 -- Allows_Lock_Free_Implementation (see Sem_Ch9).
2963 raise Program_Error
;
2966 -- Retrieve all relevant atomic routines and types
2970 Try_Write
:= RTE
(RE_Lock_Free_Try_Write_8
);
2971 Read
:= RTE
(RE_Lock_Free_Read_8
);
2972 Unsigned
:= RTE
(RE_Uint8
);
2975 Try_Write
:= RTE
(RE_Lock_Free_Try_Write_16
);
2976 Read
:= RTE
(RE_Lock_Free_Read_16
);
2977 Unsigned
:= RTE
(RE_Uint16
);
2980 Try_Write
:= RTE
(RE_Lock_Free_Try_Write_32
);
2981 Read
:= RTE
(RE_Lock_Free_Read_32
);
2982 Unsigned
:= RTE
(RE_Uint32
);
2985 Try_Write
:= RTE
(RE_Lock_Free_Try_Write_64
);
2986 Read
:= RTE
(RE_Lock_Free_Read_64
);
2987 Unsigned
:= RTE
(RE_Uint64
);
2990 raise Program_Error
;
2994 -- Expected_Comp : constant Comp_Type :=
2996 -- (System.Atomic_Primitives.Lock_Free_Read_N
2997 -- (_Object.Comp'Address));
3000 Make_Defining_Identifier
(Loc
,
3001 New_External_Name
(Chars
(Comp
), Suffix
=> "_saved"));
3004 Make_Object_Declaration
(Loc
,
3005 Defining_Identifier
=> Expected_Comp
,
3006 Object_Definition
=> New_Occurrence_Of
(Comp_Type
, Loc
),
3007 Constant_Present
=> True,
3009 Unchecked_Convert_To
(Comp_Type
,
3010 Make_Function_Call
(Loc
,
3011 Name
=> New_Occurrence_Of
(Read
, Loc
),
3012 Parameter_Associations
=> New_List
(
3013 Make_Attribute_Reference
(Loc
,
3014 Prefix
=> Relocate_Node
(Comp_Sel_Nam
),
3015 Attribute_Name
=> Name_Address
)))));
3017 -- Protected procedures
3019 if Is_Procedure
then
3020 -- Move the original declarations inside the generated block
3022 Block_Decls
:= Decls
;
3024 -- Reset the declarations list of the protected procedure to
3025 -- contain only Decl.
3027 Decls
:= New_List
(Decl
);
3030 -- Desired_Comp : Comp_Type := Expected_Comp;
3033 Make_Defining_Identifier
(Loc
,
3034 New_External_Name
(Chars
(Comp
), Suffix
=> "_current"));
3036 -- Insert the declarations of Expected_Comp and Desired_Comp in
3037 -- the block declarations right before the renaming of the
3038 -- protected component.
3040 Insert_Before
(Comp_Decl
,
3041 Make_Object_Declaration
(Loc
,
3042 Defining_Identifier
=> Desired_Comp
,
3043 Object_Definition
=> New_Occurrence_Of
(Comp_Type
, Loc
),
3045 New_Occurrence_Of
(Expected_Comp
, Loc
)));
3047 -- Protected function
3050 Desired_Comp
:= Expected_Comp
;
3052 -- Insert the declaration of Expected_Comp in the function
3053 -- declarations right before the renaming of the protected
3056 Insert_Before
(Comp_Decl
, Decl
);
3059 -- Rewrite the protected component renaming declaration to be a
3060 -- renaming of Desired_Comp.
3063 -- Comp : Comp_Type renames Desired_Comp;
3066 Make_Object_Renaming_Declaration
(Loc
,
3067 Defining_Identifier
=>
3068 Defining_Identifier
(Comp_Decl
),
3070 New_Occurrence_Of
(Comp_Type
, Loc
),
3072 New_Occurrence_Of
(Desired_Comp
, Loc
)));
3074 -- Wrap any return or raise statements in Stmts in same the manner
3075 -- described in Process_Stmts.
3077 Process_Stmts
(Stmts
);
3080 -- exit when System.Atomic_Primitives.Lock_Free_Try_Write_N
3081 -- (_Object.Comp'Address,
3082 -- Interfaces.Unsigned_N (Expected_Comp),
3083 -- Interfaces.Unsigned_N (Desired_Comp))
3085 if Is_Procedure
then
3087 Make_Exit_Statement
(Loc
,
3089 Make_Function_Call
(Loc
,
3091 New_Occurrence_Of
(Try_Write
, Loc
),
3092 Parameter_Associations
=> New_List
(
3093 Make_Attribute_Reference
(Loc
,
3094 Prefix
=> Relocate_Node
(Comp_Sel_Nam
),
3095 Attribute_Name
=> Name_Address
),
3097 Unchecked_Convert_To
(Unsigned
,
3098 New_Occurrence_Of
(Expected_Comp
, Loc
)),
3100 Unchecked_Convert_To
(Unsigned
,
3101 New_Occurrence_Of
(Desired_Comp
, Loc
)))));
3103 -- Small optimization: transform the default return statement
3104 -- of a procedure into the atomic exit statement.
3106 if Nkind
(Last
(Stmts
)) = N_Simple_Return_Statement
then
3107 Rewrite
(Last
(Stmts
), Stmt
);
3109 Append_To
(Stmts
, Stmt
);
3113 -- Create the declaration of the label used to skip the rest of
3114 -- the source statements when the object state changes.
3116 if Present
(Label_Id
) then
3117 Label
:= Make_Label
(Loc
, Label_Id
);
3119 Make_Implicit_Label_Declaration
(Loc
,
3120 Defining_Identifier
=> Entity
(Label_Id
),
3121 Label_Construct
=> Label
));
3122 Append_To
(Stmts
, Label
);
3134 if Is_Procedure
then
3137 Make_Loop_Statement
(Loc
,
3138 Statements
=> New_List
(
3139 Make_Block_Statement
(Loc
,
3140 Declarations
=> Block_Decls
,
3141 Handled_Statement_Sequence
=>
3142 Make_Handled_Sequence_Of_Statements
(Loc
,
3143 Statements
=> Stmts
))),
3144 End_Label
=> Empty
));
3148 Make_Handled_Sequence_Of_Statements
(Loc
, Statements
=> Stmts
);
3149 end Protected_Component_Ref
;
3152 -- Make an unprotected version of the subprogram for use within the same
3153 -- object, with new name and extra parameter representing the object.
3156 Make_Subprogram_Body
(Loc
,
3158 Build_Protected_Sub_Specification
(N
, Prot_Typ
, Unprotected_Mode
),
3159 Declarations
=> Decls
,
3160 Handled_Statement_Sequence
=> Hand_Stmt_Seq
);
3161 end Build_Lock_Free_Unprotected_Subprogram_Body
;
3163 -------------------------
3164 -- Build_Master_Entity --
3165 -------------------------
3167 procedure Build_Master_Entity
(Obj_Or_Typ
: Entity_Id
) is
3168 Loc
: constant Source_Ptr
:= Sloc
(Obj_Or_Typ
);
3170 Context_Id
: Entity_Id
;
3176 -- No action needed if the run-time has no tasking support
3178 if Global_No_Tasking
then
3182 if Is_Itype
(Obj_Or_Typ
) then
3183 Par
:= Associated_Node_For_Itype
(Obj_Or_Typ
);
3185 Par
:= Parent
(Obj_Or_Typ
);
3188 -- When creating a master for a record component which is either a task
3189 -- or access-to-task, the enclosing record is the master scope and the
3190 -- proper insertion point is the component list.
3192 if Is_Record_Type
(Current_Scope
) then
3194 Context_Id
:= Current_Scope
;
3195 Decls
:= List_Containing
(Context
);
3197 -- Default case for object declarations and access types. Note that the
3198 -- context is updated to the nearest enclosing body, block, package, or
3199 -- return statement.
3202 Find_Enclosing_Context
(Par
, Context
, Context_Id
, Decls
);
3205 -- When the enclosing context is a BIP function whose result type has
3206 -- tasks, the function has an extra formal that is the master of the
3207 -- tasks to be created by its returned object (that is, when its
3208 -- enclosing context is a return statement). However, if the body of
3209 -- the function creates tasks before its return statements, such tasks
3210 -- need their own master.
3212 if Has_Master_Entity
(Context_Id
)
3213 and then Ekind
(Context_Id
) = E_Function
3214 and then Is_Build_In_Place_Function
(Context_Id
)
3215 and then Needs_BIP_Task_Actuals
(Context_Id
)
3217 -- No need to add it again if previously added
3220 Master_Present
: Boolean;
3223 -- Handle transient scopes
3225 if Context_Id
/= Current_Scope
then
3226 Push_Scope
(Context_Id
);
3228 Present
(Current_Entity_In_Scope
(Name_uMaster
));
3232 Present
(Current_Entity_In_Scope
(Name_uMaster
));
3235 if Master_Present
then
3240 -- Nothing to do if the context already has a master; internally built
3241 -- finalizers don't need a master.
3243 elsif Has_Master_Entity
(Context_Id
)
3244 or else Is_Finalizer
(Context_Id
)
3249 Decl
:= Build_Master_Declaration
(Loc
);
3251 -- The master is inserted at the start of the declarative list of the
3254 Prepend_To
(Decls
, Decl
);
3256 -- In certain cases where transient scopes are involved, the immediate
3257 -- scope is not always the proper master scope. Ensure that the master
3258 -- declaration and entity appear in the same context.
3260 if Context_Id
/= Current_Scope
then
3261 Push_Scope
(Context_Id
);
3268 -- Mark the enclosing scope and its associated construct as being task
3271 Set_Has_Master_Entity
(Context_Id
);
3273 while Present
(Context
)
3274 and then Nkind
(Context
) /= N_Compilation_Unit
3276 if Nkind
(Context
) in
3277 N_Block_Statement | N_Subprogram_Body | N_Task_Body
3279 Set_Is_Task_Master
(Context
);
3282 elsif Nkind
(Parent
(Context
)) = N_Subunit
then
3283 Context
:= Corresponding_Stub
(Parent
(Context
));
3286 Context
:= Parent
(Context
);
3288 end Build_Master_Entity
;
3290 ---------------------------
3291 -- Build_Master_Renaming --
3292 ---------------------------
3294 procedure Build_Master_Renaming
3295 (Ptr_Typ
: Entity_Id
;
3296 Ins_Nod
: Node_Id
:= Empty
)
3298 Loc
: constant Source_Ptr
:= Sloc
(Ptr_Typ
);
3300 Master_Decl
: Node_Id
;
3301 Master_Id
: Entity_Id
;
3304 -- No action needed if the run-time has no tasking support
3306 if Global_No_Tasking
then
3310 -- Determine the proper context to insert the master renaming
3312 if Present
(Ins_Nod
) then
3315 elsif Is_Itype
(Ptr_Typ
) then
3316 Context
:= Associated_Node_For_Itype
(Ptr_Typ
);
3318 -- When the context references a discriminant or a component of a
3319 -- private type and we are processing declarations in the private
3320 -- part of the enclosing package, we must insert the master renaming
3321 -- before the full declaration of the private type; otherwise the
3322 -- master renaming would be inserted in the public part of the
3323 -- package (and hence before the declaration of _master).
3325 if In_Private_Part
(Current_Scope
) then
3327 Ctx
: Node_Id
:= Context
;
3330 if Nkind
(Context
) = N_Discriminant_Specification
then
3331 Ctx
:= Parent
(Ctx
);
3333 while Nkind
(Ctx
) in
3334 N_Component_Declaration | N_Component_List
3336 Ctx
:= Parent
(Ctx
);
3340 if Nkind
(Ctx
) in N_Private_Type_Declaration
3341 | N_Private_Extension_Declaration
3343 Context
:= Parent
(Full_View
(Defining_Identifier
(Ctx
)));
3349 Context
:= Parent
(Ptr_Typ
);
3353 -- <Ptr_Typ>M : Master_Id renames _Master;
3354 -- and add a numeric suffix to the name to ensure that it is
3355 -- unique in case other access types in nested constructs
3356 -- are homonyms of this one.
3359 Make_Defining_Identifier
(Loc
,
3360 New_External_Name
(Chars
(Ptr_Typ
), 'M', -1));
3363 Make_Object_Renaming_Declaration
(Loc
,
3364 Defining_Identifier
=> Master_Id
,
3366 New_Occurrence_Of
(Standard_Integer
, Loc
),
3367 Name
=> Make_Identifier
(Loc
, Name_uMaster
));
3369 Insert_Action
(Context
, Master_Decl
);
3371 -- The renamed master now services the access type
3373 Set_Master_Id
(Ptr_Typ
, Master_Id
);
3374 end Build_Master_Renaming
;
3376 ---------------------------
3377 -- Build_Protected_Entry --
3378 ---------------------------
3380 function Build_Protected_Entry
3383 Pid
: Node_Id
) return Node_Id
3385 Bod_Decls
: constant List_Id
:= New_List
;
3386 Decls
: constant List_Id
:= Declarations
(N
);
3387 End_Lab
: constant Node_Id
:=
3388 End_Label
(Handled_Statement_Sequence
(N
));
3389 End_Loc
: constant Source_Ptr
:=
3390 Sloc
(Last
(Statements
(Handled_Statement_Sequence
(N
))));
3391 -- Used for the generated call to Complete_Entry_Body
3393 Loc
: constant Source_Ptr
:= Sloc
(N
);
3395 Block_Id
: Entity_Id
;
3398 Bod_Stmts
: List_Id
;
3401 Proc_Body
: Node_Id
;
3403 EH_Loc
: Source_Ptr
;
3404 -- Used for the exception handler, inserted at end of the body
3407 -- Set the source location on the exception handler only when debugging
3408 -- the expanded code (see Make_Implicit_Exception_Handler).
3410 if Debug_Generated_Code
then
3413 -- Otherwise the inserted code should not be visible to the debugger
3416 EH_Loc
:= No_Location
;
3420 Make_Defining_Identifier
(Loc
,
3421 Chars
=> Chars
(Protected_Body_Subprogram
(Ent
)));
3422 Bod_Spec
:= Build_Protected_Entry_Specification
(Loc
, Bod_Id
, Empty
);
3424 -- Add the following declarations:
3426 -- type poVP is access poV;
3427 -- _object : poVP := poVP (_O);
3429 -- where _O is the formal parameter associated with the concurrent
3430 -- object. These declarations are needed for Complete_Entry_Body.
3432 Add_Object_Pointer
(Loc
, Pid
, Bod_Decls
);
3434 -- Add renamings for all formals, the Protection object, discriminals,
3435 -- privals and the entry index constant for use by debugger.
3437 Add_Formal_Renamings
(Bod_Spec
, Bod_Decls
, Ent
, Loc
);
3438 Debug_Private_Data_Declarations
(Decls
);
3440 -- Put the declarations and the statements from the entry
3444 Make_Block_Statement
(Loc
,
3445 Declarations
=> Decls
,
3446 Handled_Statement_Sequence
=> Handled_Statement_Sequence
(N
)));
3448 -- Analyze now and reset scopes for declarations so that Scope fields
3449 -- currently denoting the entry will now denote the block scope, and
3450 -- the block's scope will be set to the new procedure entity.
3452 Analyze_Statements
(Bod_Stmts
);
3454 Block_Id
:= Entity
(Identifier
(First
(Bod_Stmts
)));
3456 Set_Scope
(Block_Id
, Protected_Body_Subprogram
(Ent
));
3457 Set_Uses_Sec_Stack
(Block_Id
, Uses_Sec_Stack
(Corresponding_Spec
(N
)));
3459 Reset_Scopes_To
(First
(Bod_Stmts
), Block_Id
);
3460 Set_At_End_Proc
(First
(Bod_Stmts
), At_End_Proc
(N
));
3462 case Corresponding_Runtime_Package
(Pid
) is
3463 when System_Tasking_Protected_Objects_Entries
=>
3464 Append_To
(Bod_Stmts
,
3465 Make_Procedure_Call_Statement
(End_Loc
,
3467 New_Occurrence_Of
(RTE
(RE_Complete_Entry_Body
), Loc
),
3468 Parameter_Associations
=> New_List
(
3469 Make_Attribute_Reference
(End_Loc
,
3471 Make_Selected_Component
(End_Loc
,
3473 Make_Identifier
(End_Loc
, Name_uObject
),
3475 Make_Identifier
(End_Loc
, Name_uObject
)),
3476 Attribute_Name
=> Name_Unchecked_Access
))));
3478 when System_Tasking_Protected_Objects_Single_Entry
=>
3480 -- Historically, a call to Complete_Single_Entry_Body was
3481 -- inserted, but it was a null procedure.
3486 raise Program_Error
;
3489 -- When exceptions cannot be propagated, we never need to call
3490 -- Exception_Complete_Entry_Body.
3492 if No_Exception_Handlers_Set
then
3494 Make_Subprogram_Body
(Loc
,
3495 Specification
=> Bod_Spec
,
3496 Declarations
=> Bod_Decls
,
3497 Handled_Statement_Sequence
=>
3498 Make_Handled_Sequence_Of_Statements
(Loc
,
3499 Statements
=> Bod_Stmts
,
3500 End_Label
=> End_Lab
));
3503 Ohandle
:= Make_Others_Choice
(Loc
);
3504 Set_All_Others
(Ohandle
);
3506 case Corresponding_Runtime_Package
(Pid
) is
3507 when System_Tasking_Protected_Objects_Entries
=>
3510 (RTE
(RE_Exceptional_Complete_Entry_Body
), Loc
);
3512 when System_Tasking_Protected_Objects_Single_Entry
=>
3515 (RTE
(RE_Exceptional_Complete_Single_Entry_Body
), Loc
);
3518 raise Program_Error
;
3521 -- Create body of entry procedure. The renaming declarations are
3522 -- placed ahead of the block that contains the actual entry body.
3525 Make_Subprogram_Body
(Loc
,
3526 Specification
=> Bod_Spec
,
3527 Declarations
=> Bod_Decls
,
3528 Handled_Statement_Sequence
=>
3529 Make_Handled_Sequence_Of_Statements
(Loc
,
3530 Statements
=> Bod_Stmts
,
3531 End_Label
=> End_Lab
,
3532 Exception_Handlers
=> New_List
(
3533 Make_Implicit_Exception_Handler
(EH_Loc
,
3534 Exception_Choices
=> New_List
(Ohandle
),
3536 Statements
=> New_List
(
3537 Make_Procedure_Call_Statement
(EH_Loc
,
3539 Parameter_Associations
=> New_List
(
3540 Make_Attribute_Reference
(EH_Loc
,
3542 Make_Selected_Component
(EH_Loc
,
3544 Make_Identifier
(EH_Loc
, Name_uObject
),
3546 Make_Identifier
(EH_Loc
, Name_uObject
)),
3547 Attribute_Name
=> Name_Unchecked_Access
),
3549 Make_Function_Call
(EH_Loc
,
3552 (RTE
(RE_Get_GNAT_Exception
), Loc
)))))))));
3554 -- Establish link between subprogram body and source entry body
3556 Set_Corresponding_Entry_Body
(Proc_Body
, N
);
3558 Reset_Scopes_To
(Proc_Body
, Protected_Body_Subprogram
(Ent
));
3561 end Build_Protected_Entry
;
3563 -----------------------------------------
3564 -- Build_Protected_Entry_Specification --
3565 -----------------------------------------
3567 function Build_Protected_Entry_Specification
3570 Ent_Id
: Entity_Id
) return Node_Id
3572 P
: constant Entity_Id
:= Make_Defining_Identifier
(Loc
, Name_uP
);
3575 Set_Debug_Info_Needed
(Def_Id
);
3577 if Present
(Ent_Id
) then
3578 Append_Elmt
(P
, Accept_Address
(Ent_Id
));
3582 Make_Procedure_Specification
(Loc
,
3583 Defining_Unit_Name
=> Def_Id
,
3584 Parameter_Specifications
=> New_List
(
3585 Make_Parameter_Specification
(Loc
,
3586 Defining_Identifier
=>
3587 Make_Defining_Identifier
(Loc
, Name_uO
),
3589 New_Occurrence_Of
(RTE
(RE_Address
), Loc
)),
3591 Make_Parameter_Specification
(Loc
,
3592 Defining_Identifier
=> P
,
3594 New_Occurrence_Of
(RTE
(RE_Address
), Loc
)),
3596 Make_Parameter_Specification
(Loc
,
3597 Defining_Identifier
=>
3598 Make_Defining_Identifier
(Loc
, Name_uE
),
3600 New_Occurrence_Of
(RTE
(RE_Protected_Entry_Index
), Loc
))));
3601 end Build_Protected_Entry_Specification
;
3603 --------------------------
3604 -- Build_Protected_Spec --
3605 --------------------------
3607 function Build_Protected_Spec
3609 Obj_Type
: Entity_Id
;
3611 Unprotected
: Boolean := False) return List_Id
3613 Loc
: constant Source_Ptr
:= Sloc
(N
);
3617 New_Formal
: Entity_Id
;
3618 New_Plist
: List_Id
;
3621 New_Plist
:= New_List
;
3623 Formal
:= First_Formal
(Ident
);
3624 while Present
(Formal
) loop
3626 Make_Defining_Identifier
(Sloc
(Formal
), Chars
(Formal
));
3627 Set_Comes_From_Source
(New_Formal
, Comes_From_Source
(Formal
));
3630 Mutate_Ekind
(New_Formal
, Ekind
(Formal
));
3631 Set_Protected_Formal
(Formal
, New_Formal
);
3634 Append_To
(New_Plist
,
3635 Make_Parameter_Specification
(Loc
,
3636 Defining_Identifier
=> New_Formal
,
3637 Aliased_Present
=> Aliased_Present
(Parent
(Formal
)),
3638 In_Present
=> In_Present
(Parent
(Formal
)),
3639 Out_Present
=> Out_Present
(Parent
(Formal
)),
3640 Parameter_Type
=> New_Occurrence_Of
(Etype
(Formal
), Loc
)));
3642 Next_Formal
(Formal
);
3645 -- If the subprogram is a procedure and the context is not an access
3646 -- to protected subprogram, the parameter is in-out. Otherwise it is
3650 Make_Parameter_Specification
(Loc
,
3651 Defining_Identifier
=>
3652 Make_Defining_Identifier
(Loc
, Name_uObject
),
3655 (Etype
(Ident
) = Standard_Void_Type
3656 and then not Is_RTE
(Obj_Type
, RE_Address
)),
3658 New_Occurrence_Of
(Obj_Type
, Loc
));
3659 Set_Debug_Info_Needed
(Defining_Identifier
(Decl
));
3660 Prepend_To
(New_Plist
, Decl
);
3663 end Build_Protected_Spec
;
3665 ---------------------------------------
3666 -- Build_Protected_Sub_Specification --
3667 ---------------------------------------
3669 function Build_Protected_Sub_Specification
3671 Prot_Typ
: Entity_Id
;
3672 Mode
: Subprogram_Protection_Mode
) return Node_Id
3674 Loc
: constant Source_Ptr
:= Sloc
(N
);
3678 New_Plist
: List_Id
;
3681 Append_Chr
: constant array (Subprogram_Protection_Mode
) of Character :=
3682 (Dispatching_Mode
=> ' ',
3683 Protected_Mode
=> 'P',
3684 Unprotected_Mode
=> 'N');
3687 if Ekind
(Defining_Unit_Name
(Specification
(N
))) = E_Subprogram_Body
3689 Decl
:= Unit_Declaration_Node
(Corresponding_Spec
(N
));
3694 Def_Id
:= Defining_Unit_Name
(Specification
(Decl
));
3697 Build_Protected_Spec
3698 (Decl
, Corresponding_Record_Type
(Prot_Typ
), Def_Id
,
3699 Mode
= Unprotected_Mode
);
3701 Make_Defining_Identifier
(Loc
,
3702 Chars
=> Build_Selected_Name
(Prot_Typ
, Def_Id
, Append_Chr
(Mode
)));
3704 -- Reference the original nondispatching subprogram since the analysis
3705 -- of the object.operation notation may need its original name (see
3706 -- Sem_Ch4.Names_Match).
3708 if Mode
= Dispatching_Mode
then
3709 Mutate_Ekind
(New_Id
, Ekind
(Def_Id
));
3710 Set_Original_Protected_Subprogram
(New_Id
, Def_Id
);
3713 -- Link the protected or unprotected version to the original subprogram
3716 Mutate_Ekind
(New_Id
, Ekind
(Def_Id
));
3717 Set_Protected_Subprogram
(New_Id
, Def_Id
);
3719 -- The unprotected operation carries the user code, and debugging
3720 -- information must be generated for it, even though this spec does
3721 -- not come from source. It is also convenient to allow gdb to step
3722 -- into the protected operation, even though it only contains lock/
3725 Set_Debug_Info_Needed
(New_Id
);
3727 -- If a pragma Eliminate applies to the source entity, the internal
3728 -- subprograms will be eliminated as well.
3730 Set_Is_Eliminated
(New_Id
, Is_Eliminated
(Def_Id
));
3732 -- It seems we should set Has_Nested_Subprogram here, but instead we
3733 -- currently set it in Expand_N_Protected_Body, because the entity
3734 -- created here isn't the one that Corresponding_Spec of the body
3735 -- will later be set to, and that's the entity where it's needed. ???
3737 Set_Has_Nested_Subprogram
(New_Id
, Has_Nested_Subprogram
(Def_Id
));
3739 if Nkind
(Specification
(Decl
)) = N_Procedure_Specification
then
3741 Make_Procedure_Specification
(Loc
,
3742 Defining_Unit_Name
=> New_Id
,
3743 Parameter_Specifications
=> New_Plist
);
3745 -- Create a new specification for the anonymous subprogram type
3749 Make_Function_Specification
(Loc
,
3750 Defining_Unit_Name
=> New_Id
,
3751 Parameter_Specifications
=> New_Plist
,
3752 Result_Definition
=>
3753 Copy_Result_Type
(Result_Definition
(Specification
(Decl
))));
3755 Set_Return_Present
(Defining_Unit_Name
(New_Spec
));
3759 end Build_Protected_Sub_Specification
;
3761 -------------------------------------
3762 -- Build_Protected_Subprogram_Body --
3763 -------------------------------------
3765 function Build_Protected_Subprogram_Body
3768 N_Op_Spec
: Node_Id
) return Node_Id
3770 Might_Raise
: constant Boolean := Sem_Util
.Might_Raise
(N
);
3772 Loc
: constant Source_Ptr
:= Sloc
(N
);
3773 Op_Spec
: constant Node_Id
:= Specification
(N
);
3774 P_Op_Spec
: constant Node_Id
:=
3775 Build_Protected_Sub_Specification
(N
, Pid
, Protected_Mode
);
3778 Lock_Name
: Node_Id
;
3779 Lock_Stmt
: Node_Id
;
3780 Object_Parm
: Node_Id
;
3783 Return_Stmt
: Node_Id
:= Empty
; -- init to avoid gcc 3 warning
3784 Pre_Stmts
: List_Id
:= No_List
; -- init to avoid gcc 3 warning
3788 Unprot_Call
: Node_Id
;
3791 -- Build a list of the formal parameters of the protected version of
3792 -- the subprogram to use as the actual parameters of the unprotected
3795 Uactuals
:= New_List
;
3796 Pformal
:= First
(Parameter_Specifications
(P_Op_Spec
));
3797 while Present
(Pformal
) loop
3798 Append_To
(Uactuals
,
3799 Make_Identifier
(Loc
, Chars
(Defining_Identifier
(Pformal
))));
3803 -- Make a call to the unprotected version of the subprogram built above
3804 -- for use by the protected version built below.
3806 if Nkind
(Op_Spec
) = N_Function_Specification
then
3809 Make_Simple_Return_Statement
(Loc
,
3811 Make_Function_Call
(Loc
,
3813 Make_Identifier
(Loc
,
3814 Chars
=> Chars
(Defining_Unit_Name
(N_Op_Spec
))),
3815 Parameter_Associations
=> Uactuals
));
3818 R
:= Make_Temporary
(Loc
, 'R');
3821 Make_Object_Declaration
(Loc
,
3822 Defining_Identifier
=> R
,
3823 Constant_Present
=> True,
3824 Object_Definition
=>
3825 New_Copy
(Result_Definition
(N_Op_Spec
)),
3827 Make_Function_Call
(Loc
,
3829 Make_Identifier
(Loc
,
3830 Chars
=> Chars
(Defining_Unit_Name
(N_Op_Spec
))),
3831 Parameter_Associations
=> Uactuals
));
3834 Make_Simple_Return_Statement
(Loc
,
3835 Expression
=> New_Occurrence_Of
(R
, Loc
));
3838 if Has_Aspect
(Pid
, Aspect_Exclusive_Functions
)
3840 (No
(Find_Value_Of_Aspect
(Pid
, Aspect_Exclusive_Functions
))
3842 Is_True
(Static_Boolean
(Find_Value_Of_Aspect
3843 (Pid
, Aspect_Exclusive_Functions
))))
3845 Lock_Kind
:= RE_Lock
;
3847 Lock_Kind
:= RE_Lock_Read_Only
;
3851 Make_Procedure_Call_Statement
(Loc
,
3853 Make_Identifier
(Loc
, Chars
(Defining_Unit_Name
(N_Op_Spec
))),
3854 Parameter_Associations
=> Uactuals
);
3856 Lock_Kind
:= RE_Lock
;
3859 -- Wrap call in block that will be covered by an at_end handler
3863 Make_Block_Statement
(Loc
,
3864 Handled_Statement_Sequence
=>
3865 Make_Handled_Sequence_Of_Statements
(Loc
,
3866 Statements
=> New_List
(Unprot_Call
)));
3869 -- Make the protected subprogram body. This locks the protected
3870 -- object and calls the unprotected version of the subprogram.
3872 case Corresponding_Runtime_Package
(Pid
) is
3873 when System_Tasking_Protected_Objects_Entries
=>
3874 Lock_Name
:= New_Occurrence_Of
(RTE
(RE_Lock_Entries
), Loc
);
3876 when System_Tasking_Protected_Objects_Single_Entry
=>
3877 Lock_Name
:= New_Occurrence_Of
(RTE
(RE_Lock_Entry
), Loc
);
3879 when System_Tasking_Protected_Objects
=>
3880 Lock_Name
:= New_Occurrence_Of
(RTE
(Lock_Kind
), Loc
);
3883 raise Program_Error
;
3887 Make_Attribute_Reference
(Loc
,
3889 Make_Selected_Component
(Loc
,
3890 Prefix
=> Make_Identifier
(Loc
, Name_uObject
),
3891 Selector_Name
=> Make_Identifier
(Loc
, Name_uObject
)),
3892 Attribute_Name
=> Name_Unchecked_Access
);
3895 Make_Procedure_Call_Statement
(Loc
,
3897 Parameter_Associations
=> New_List
(Object_Parm
));
3899 if Abort_Allowed
then
3901 Build_Runtime_Call
(Loc
, RE_Abort_Defer
),
3905 Stmts
:= New_List
(Lock_Stmt
);
3909 Append
(Unprot_Call
, Stmts
);
3911 if Nkind
(Op_Spec
) = N_Function_Specification
then
3913 Stmts
:= Empty_List
;
3915 Append
(Unprot_Call
, Stmts
);
3918 Build_Protected_Subprogram_Call_Cleanup
(Op_Spec
, Pid
, Loc
, Stmts
);
3920 if Nkind
(Op_Spec
) = N_Function_Specification
then
3921 Append_To
(Stmts
, Return_Stmt
);
3922 Append_To
(Pre_Stmts
,
3923 Make_Block_Statement
(Loc
,
3924 Declarations
=> New_List
(Unprot_Call
),
3925 Handled_Statement_Sequence
=>
3926 Make_Handled_Sequence_Of_Statements
(Loc
,
3927 Statements
=> Stmts
)));
3933 Make_Subprogram_Body
(Loc
,
3934 Declarations
=> Empty_List
,
3935 Specification
=> P_Op_Spec
,
3936 Handled_Statement_Sequence
=>
3937 Make_Handled_Sequence_Of_Statements
(Loc
, Statements
=> Stmts
));
3939 -- Mark this subprogram as a protected subprogram body so that the
3940 -- cleanup will be inserted. This is done only in the Might_Raise
3941 -- case because otherwise the cleanup has already been inserted.
3944 Set_Is_Protected_Subprogram_Body
(Sub_Body
);
3948 end Build_Protected_Subprogram_Body
;
3950 -------------------------------------
3951 -- Build_Protected_Subprogram_Call --
3952 -------------------------------------
3954 procedure Build_Protected_Subprogram_Call
3958 External
: Boolean := True)
3960 Loc
: constant Source_Ptr
:= Sloc
(N
);
3961 Sub
: constant Entity_Id
:= Entity
(Name
);
3967 New_Sub
:= New_Occurrence_Of
(External_Subprogram
(Sub
), Loc
);
3970 New_Occurrence_Of
(Protected_Body_Subprogram
(Sub
), Loc
);
3973 if Present
(Parameter_Associations
(N
)) then
3974 Params
:= New_Copy_List_Tree
(Parameter_Associations
(N
));
3979 -- If the type is an untagged derived type, convert to the root type,
3980 -- which is the one on which the operations are defined.
3982 if Nkind
(Rec
) = N_Unchecked_Type_Conversion
3983 and then not Is_Tagged_Type
(Etype
(Rec
))
3984 and then Is_Derived_Type
(Etype
(Rec
))
3986 Set_Etype
(Rec
, Root_Type
(Etype
(Rec
)));
3987 Set_Subtype_Mark
(Rec
,
3988 New_Occurrence_Of
(Root_Type
(Etype
(Rec
)), Sloc
(N
)));
3991 Prepend
(Rec
, Params
);
3993 if Ekind
(Sub
) = E_Procedure
then
3995 Make_Procedure_Call_Statement
(Loc
,
3997 Parameter_Associations
=> Params
));
4000 pragma Assert
(Ekind
(Sub
) = E_Function
);
4002 Make_Function_Call
(Loc
,
4004 Parameter_Associations
=> Params
));
4006 -- Preserve type of call for subsequent processing (required for
4007 -- call to Wrap_Transient_Expression in the case of a shared passive
4010 Set_Etype
(N
, Etype
(New_Sub
));
4014 and then Nkind
(Rec
) = N_Unchecked_Type_Conversion
4015 and then Is_Entity_Name
(Expression
(Rec
))
4016 and then Is_Shared_Passive
(Entity
(Expression
(Rec
)))
4018 Add_Shared_Var_Lock_Procs
(N
);
4020 end Build_Protected_Subprogram_Call
;
4022 ---------------------------------------------
4023 -- Build_Protected_Subprogram_Call_Cleanup --
4024 ---------------------------------------------
4026 procedure Build_Protected_Subprogram_Call_Cleanup
4035 -- If the associated protected object has entries, a protected
4036 -- procedure has to service entry queues. In this case generate:
4038 -- Service_Entries (_object._object'Access);
4040 if Nkind
(Op_Spec
) = N_Procedure_Specification
4041 and then Has_Entries
(Conc_Typ
)
4043 case Corresponding_Runtime_Package
(Conc_Typ
) is
4044 when System_Tasking_Protected_Objects_Entries
=>
4045 Nam
:= New_Occurrence_Of
(RTE
(RE_Service_Entries
), Loc
);
4047 when System_Tasking_Protected_Objects_Single_Entry
=>
4048 Nam
:= New_Occurrence_Of
(RTE
(RE_Service_Entry
), Loc
);
4051 raise Program_Error
;
4055 Make_Procedure_Call_Statement
(Loc
,
4057 Parameter_Associations
=> New_List
(
4058 Make_Attribute_Reference
(Loc
,
4060 Make_Selected_Component
(Loc
,
4061 Prefix
=> Make_Identifier
(Loc
, Name_uObject
),
4062 Selector_Name
=> Make_Identifier
(Loc
, Name_uObject
)),
4063 Attribute_Name
=> Name_Unchecked_Access
))));
4067 -- Unlock (_object._object'Access);
4069 case Corresponding_Runtime_Package
(Conc_Typ
) is
4070 when System_Tasking_Protected_Objects_Entries
=>
4071 Nam
:= New_Occurrence_Of
(RTE
(RE_Unlock_Entries
), Loc
);
4073 when System_Tasking_Protected_Objects_Single_Entry
=>
4074 Nam
:= New_Occurrence_Of
(RTE
(RE_Unlock_Entry
), Loc
);
4076 when System_Tasking_Protected_Objects
=>
4077 Nam
:= New_Occurrence_Of
(RTE
(RE_Unlock
), Loc
);
4080 raise Program_Error
;
4084 Make_Procedure_Call_Statement
(Loc
,
4086 Parameter_Associations
=> New_List
(
4087 Make_Attribute_Reference
(Loc
,
4089 Make_Selected_Component
(Loc
,
4090 Prefix
=> Make_Identifier
(Loc
, Name_uObject
),
4091 Selector_Name
=> Make_Identifier
(Loc
, Name_uObject
)),
4092 Attribute_Name
=> Name_Unchecked_Access
))));
4098 if Abort_Allowed
then
4099 Append_To
(Stmts
, Build_Runtime_Call
(Loc
, RE_Abort_Undefer
));
4101 end Build_Protected_Subprogram_Call_Cleanup
;
4103 -------------------------
4104 -- Build_Selected_Name --
4105 -------------------------
4107 function Build_Selected_Name
4108 (Prefix
: Entity_Id
;
4109 Selector
: Entity_Id
;
4110 Append_Char
: Character := ' ') return Name_Id
4112 Select_Buffer
: String (1 .. Hostparm
.Max_Name_Length
);
4113 Select_Len
: Natural;
4116 Get_Name_String
(Chars
(Selector
));
4117 Select_Len
:= Name_Len
;
4118 Select_Buffer
(1 .. Select_Len
) := Name_Buffer
(1 .. Name_Len
);
4119 Get_Name_String
(Chars
(Prefix
));
4121 -- If scope is anonymous type, discard suffix to recover name of
4122 -- single protected object. Otherwise use protected type name.
4124 if Name_Buffer
(Name_Len
) = 'T' then
4125 Name_Len
:= Name_Len
- 1;
4128 Add_Str_To_Name_Buffer
("__");
4129 for J
in 1 .. Select_Len
loop
4130 Add_Char_To_Name_Buffer
(Select_Buffer
(J
));
4133 -- Now add the Append_Char if specified. The encoding to follow
4134 -- depends on the type of entity. If Append_Char is either 'N' or 'P',
4135 -- then the entity is associated to a protected type subprogram.
4136 -- Otherwise, it is a protected type entry. For each case, the
4137 -- encoding to follow for the suffix is documented in exp_dbug.ads.
4139 -- It would be better to encapsulate this as a routine in Exp_Dbug ???
4141 if Append_Char
/= ' ' then
4142 if Append_Char
in 'P' |
'N' then
4143 Add_Char_To_Name_Buffer
(Append_Char
);
4146 Add_Str_To_Name_Buffer
((1 => '_', 2 => Append_Char
));
4147 return New_External_Name
(Name_Find
, ' ', -1);
4152 end Build_Selected_Name
;
4154 -----------------------------
4155 -- Build_Simple_Entry_Call --
4156 -----------------------------
4158 -- A task entry call is converted to a call to Call_Simple
4161 -- P : parms := (parm, parm, parm);
4163 -- Call_Simple (acceptor-task, entry-index, P'Address);
4169 -- Here Pnn is an aggregate of the type constructed for the entry to hold
4170 -- the parameters, and the constructed aggregate value contains either the
4171 -- parameters or, in the case of non-elementary types, references to these
4172 -- parameters. Then the address of this aggregate is passed to the runtime
4173 -- routine, along with the task id value and the task entry index value.
4174 -- Pnn is only required if parameters are present.
4176 -- The assignments after the call are present only in the case of in-out
4177 -- or out parameters for elementary types, and are used to assign back the
4178 -- resulting values of such parameters.
4180 -- Note: the reason that we insert a block here is that in the context
4181 -- of selects, conditional entry calls etc. the entry call statement
4182 -- appears on its own, not as an element of a list.
4184 -- A protected entry call is converted to a Protected_Entry_Call:
4187 -- P : E1_Params := (param, param, param);
4189 -- Bnn : Communications_Block;
4192 -- P : E1_Params := (param, param, param);
4193 -- Bnn : Communications_Block;
4196 -- Protected_Entry_Call (
4197 -- Object => po._object'Access,
4198 -- E => <entry index>;
4199 -- Uninterpreted_Data => P'Address;
4200 -- Mode => Simple_Call;
4207 procedure Build_Simple_Entry_Call
4216 -- If call has been inlined, nothing left to do
4218 if Nkind
(N
) = N_Block_Statement
then
4222 -- Convert entry call to Call_Simple call
4225 Loc
: constant Source_Ptr
:= Sloc
(N
);
4226 Parms
: constant List_Id
:= Parameter_Associations
(N
);
4227 Stats
: constant List_Id
:= New_List
;
4230 Comm_Name
: Entity_Id
;
4234 Ent_Acc
: Entity_Id
;
4236 Iface_Tag
: Entity_Id
;
4237 Iface_Typ
: Entity_Id
;
4250 -- Simple entry and entry family cases merge here
4252 Ent
:= Entity
(Ename
);
4253 Ent_Acc
:= Entry_Parameters_Type
(Ent
);
4254 Conctyp
:= Etype
(Concval
);
4256 -- Special case for protected subprogram calls
4258 if Is_Protected_Type
(Conctyp
)
4259 and then Is_Subprogram
(Entity
(Ename
))
4261 if not Is_Eliminated
(Entity
(Ename
)) then
4262 Build_Protected_Subprogram_Call
4263 (N
, Ename
, Convert_Concurrent
(Concval
, Conctyp
));
4270 -- First parameter is the Task_Id value from the task value or the
4271 -- Object from the protected object value, obtained by selecting
4272 -- the _Task_Id or _Object from the result of doing an unchecked
4273 -- conversion to convert the value to the corresponding record type.
4275 if Nkind
(Concval
) = N_Function_Call
4276 and then Is_Task_Type
(Conctyp
)
4277 and then Ada_Version
>= Ada_2005
4280 ExpR
: constant Node_Id
:= Relocate_Node
(Concval
);
4281 Obj
: constant Entity_Id
:= Make_Temporary
(Loc
, 'F', ExpR
);
4286 Make_Object_Declaration
(Loc
,
4287 Defining_Identifier
=> Obj
,
4288 Object_Definition
=> New_Occurrence_Of
(Conctyp
, Loc
),
4289 Expression
=> ExpR
);
4290 Set_Etype
(Obj
, Conctyp
);
4291 Decls
:= New_List
(Decl
);
4292 Rewrite
(Concval
, New_Occurrence_Of
(Obj
, Loc
));
4299 Parm1
:= Concurrent_Ref
(Concval
);
4301 -- Second parameter is the entry index, computed by the routine
4302 -- provided for this purpose. The value of this expression is
4303 -- assigned to an intermediate variable to assure that any entry
4304 -- family index expressions are evaluated before the entry
4307 if not Is_Protected_Type
(Conctyp
)
4309 Corresponding_Runtime_Package
(Conctyp
) =
4310 System_Tasking_Protected_Objects_Entries
4312 X
:= Make_Defining_Identifier
(Loc
, Name_uX
);
4315 Make_Object_Declaration
(Loc
,
4316 Defining_Identifier
=> X
,
4317 Object_Definition
=>
4318 New_Occurrence_Of
(RTE
(RE_Task_Entry_Index
), Loc
),
4319 Expression
=> Actual_Index_Expression
(
4320 Loc
, Entity
(Ename
), Index
, Concval
));
4322 Append_To
(Decls
, Xdecl
);
4323 Parm2
:= New_Occurrence_Of
(X
, Loc
);
4330 -- The third parameter is the packaged parameters. If there are
4331 -- none, then it is just the null address, since nothing is passed.
4334 Parm3
:= New_Occurrence_Of
(RTE
(RE_Null_Address
), Loc
);
4337 -- Case of parameters present, where third argument is the address
4338 -- of a packaged record containing the required parameter values.
4341 -- First build a list of parameter values, which are references to
4342 -- objects of the parameter types.
4346 Actual
:= First_Actual
(N
);
4347 Formal
:= First_Formal
(Ent
);
4348 while Present
(Actual
) loop
4350 -- If it is a by-copy type, copy it to a new variable. The
4351 -- packaged record has a field that points to this variable.
4353 if Is_By_Copy_Type
(Etype
(Actual
)) then
4355 Make_Object_Declaration
(Loc
,
4356 Defining_Identifier
=> Make_Temporary
(Loc
, 'J'),
4357 Aliased_Present
=> True,
4358 Object_Definition
=>
4359 New_Occurrence_Of
(Etype
(Formal
), Loc
));
4361 -- Mark the object as not needing initialization since the
4362 -- initialization is performed separately, avoiding errors
4363 -- on cases such as formals of null-excluding access types.
4365 Set_No_Initialization
(N_Node
);
4367 -- We must make a separate assignment statement for the
4368 -- case of limited types. We cannot assign it unless the
4369 -- Assignment_OK flag is set first. An out formal of an
4370 -- access type or whose type has a Default_Value must also
4371 -- be initialized from the actual (see RM 6.4.1 (13-13.1)),
4372 -- but no constraint, predicate, or null-exclusion check is
4373 -- applied before the call.
4375 if Ekind
(Formal
) /= E_Out_Parameter
4376 or else Is_Access_Type
(Etype
(Formal
))
4378 (Is_Scalar_Type
(Etype
(Formal
))
4380 Present
(Default_Aspect_Value
(Etype
(Formal
))))
4383 New_Occurrence_Of
(Defining_Identifier
(N_Node
), Loc
);
4384 Set_Assignment_OK
(N_Var
);
4386 Make_Assignment_Statement
(Loc
,
4388 Expression
=> Relocate_Node
(Actual
)));
4390 -- Mark the object as internal, so we don't later reset
4391 -- No_Initialization flag in Default_Initialize_Object,
4392 -- which would lead to needless default initialization.
4393 -- We don't set this outside the if statement, because
4394 -- out scalar parameters without Default_Value do require
4395 -- default initialization if Initialize_Scalars applies.
4397 Set_Is_Internal
(Defining_Identifier
(N_Node
));
4399 -- If actual is an out parameter of a null-excluding
4400 -- access type, there is access check on entry, so set
4401 -- Suppress_Assignment_Checks on the generated statement
4402 -- that assigns the actual to the parameter block.
4404 Set_Suppress_Assignment_Checks
(Last
(Stats
));
4407 Append
(N_Node
, Decls
);
4410 Make_Attribute_Reference
(Loc
,
4411 Attribute_Name
=> Name_Unchecked_Access
,
4414 (Defining_Identifier
(N_Node
), Loc
)));
4417 -- Interface class-wide formal
4419 if Ada_Version
>= Ada_2005
4420 and then Ekind
(Etype
(Formal
)) = E_Class_Wide_Type
4421 and then Is_Interface
(Etype
(Formal
))
4423 Iface_Typ
:= Etype
(Etype
(Formal
));
4426 -- formal_iface_type! (actual.iface_tag)'reference
4429 Find_Interface_Tag
(Etype
(Actual
), Iface_Typ
);
4430 pragma Assert
(Present
(Iface_Tag
));
4433 Make_Reference
(Loc
,
4434 Unchecked_Convert_To
(Iface_Typ
,
4435 Make_Selected_Component
(Loc
,
4437 Relocate_Node
(Actual
),
4439 New_Occurrence_Of
(Iface_Tag
, Loc
)))));
4445 Make_Reference
(Loc
, Relocate_Node
(Actual
)));
4449 Next_Actual
(Actual
);
4450 Next_Formal_With_Extras
(Formal
);
4453 -- Now build the declaration of parameters initialized with the
4454 -- aggregate containing this constructed parameter list.
4456 P
:= Make_Defining_Identifier
(Loc
, Name_uP
);
4459 Make_Object_Declaration
(Loc
,
4460 Defining_Identifier
=> P
,
4461 Object_Definition
=>
4462 New_Occurrence_Of
(Designated_Type
(Ent_Acc
), Loc
),
4464 Make_Aggregate
(Loc
, Expressions
=> Plist
));
4467 Make_Attribute_Reference
(Loc
,
4468 Prefix
=> New_Occurrence_Of
(P
, Loc
),
4469 Attribute_Name
=> Name_Address
);
4471 Append
(Pdecl
, Decls
);
4474 -- Now we can create the call, case of protected type
4476 if Is_Protected_Type
(Conctyp
) then
4477 case Corresponding_Runtime_Package
(Conctyp
) is
4478 when System_Tasking_Protected_Objects_Entries
=>
4480 -- Change the type of the index declaration
4482 Set_Object_Definition
(Xdecl
,
4483 New_Occurrence_Of
(RTE
(RE_Protected_Entry_Index
), Loc
));
4485 -- Some additional declarations for protected entry calls
4491 -- Bnn : Communications_Block;
4493 Comm_Name
:= Make_Temporary
(Loc
, 'B');
4496 Make_Object_Declaration
(Loc
,
4497 Defining_Identifier
=> Comm_Name
,
4498 Object_Definition
=>
4500 (RTE
(RE_Communication_Block
), Loc
)));
4502 -- Some additional statements for protected entry calls
4504 -- Protected_Entry_Call
4505 -- (Object => po._object'Access,
4506 -- E => <entry index>;
4507 -- Uninterpreted_Data => P'Address;
4508 -- Mode => Simple_Call;
4512 Make_Procedure_Call_Statement
(Loc
,
4514 New_Occurrence_Of
(RTE
(RE_Protected_Entry_Call
), Loc
),
4516 Parameter_Associations
=> New_List
(
4517 Make_Attribute_Reference
(Loc
,
4518 Attribute_Name
=> Name_Unchecked_Access
,
4522 New_Occurrence_Of
(RTE
(RE_Simple_Call
), Loc
),
4523 New_Occurrence_Of
(Comm_Name
, Loc
)));
4525 when System_Tasking_Protected_Objects_Single_Entry
=>
4527 -- Protected_Single_Entry_Call
4528 -- (Object => po._object'Access,
4529 -- Uninterpreted_Data => P'Address);
4532 Make_Procedure_Call_Statement
(Loc
,
4535 (RTE
(RE_Protected_Single_Entry_Call
), Loc
),
4537 Parameter_Associations
=> New_List
(
4538 Make_Attribute_Reference
(Loc
,
4539 Attribute_Name
=> Name_Unchecked_Access
,
4544 raise Program_Error
;
4547 -- Case of task type
4551 Make_Procedure_Call_Statement
(Loc
,
4553 New_Occurrence_Of
(RTE
(RE_Call_Simple
), Loc
),
4554 Parameter_Associations
=> New_List
(Parm1
, Parm2
, Parm3
));
4558 Append_To
(Stats
, Call
);
4560 -- If there are out or in/out parameters by copy add assignment
4561 -- statements for the result values.
4563 if Present
(Parms
) then
4564 Actual
:= First_Actual
(N
);
4565 Formal
:= First_Formal
(Ent
);
4567 Set_Assignment_OK
(Actual
);
4568 while Present
(Actual
) loop
4569 if Is_By_Copy_Type
(Etype
(Actual
))
4570 and then Ekind
(Formal
) /= E_In_Parameter
4573 Make_Assignment_Statement
(Loc
,
4574 Name
=> New_Copy
(Actual
),
4576 Make_Explicit_Dereference
(Loc
,
4577 Make_Selected_Component
(Loc
,
4578 Prefix
=> New_Occurrence_Of
(P
, Loc
),
4580 Make_Identifier
(Loc
, Chars
(Formal
)))));
4582 -- In all cases (including limited private types) we want
4583 -- the assignment to be valid.
4585 Set_Assignment_OK
(Name
(N_Node
));
4587 -- If the call is the triggering alternative in an
4588 -- asynchronous select, or the entry_call alternative of a
4589 -- conditional entry call, the assignments for in-out
4590 -- parameters are incorporated into the statement list that
4591 -- follows, so that there are executed only if the entry
4594 if (Nkind
(Parent
(N
)) = N_Triggering_Alternative
4595 and then N
= Triggering_Statement
(Parent
(N
)))
4597 (Nkind
(Parent
(N
)) = N_Entry_Call_Alternative
4598 and then N
= Entry_Call_Statement
(Parent
(N
)))
4600 if No
(Statements
(Parent
(N
))) then
4601 Set_Statements
(Parent
(N
), New_List
);
4604 Prepend
(N_Node
, Statements
(Parent
(N
)));
4607 Insert_After
(Call
, N_Node
);
4611 Next_Actual
(Actual
);
4612 Next_Formal_With_Extras
(Formal
);
4616 -- Finally, create block and analyze it
4619 Make_Block_Statement
(Loc
,
4620 Declarations
=> Decls
,
4621 Handled_Statement_Sequence
=>
4622 Make_Handled_Sequence_Of_Statements
(Loc
,
4623 Statements
=> Stats
)));
4627 end Build_Simple_Entry_Call
;
4629 --------------------------------
4630 -- Build_Task_Activation_Call --
4631 --------------------------------
4633 procedure Build_Task_Activation_Call
(N
: Node_Id
) is
4634 function Activation_Call_Loc
return Source_Ptr
;
4635 -- Find a suitable source location for the activation call
4637 -------------------------
4638 -- Activation_Call_Loc --
4639 -------------------------
4641 function Activation_Call_Loc
return Source_Ptr
is
4643 -- The activation call must carry the location of the "end" keyword
4644 -- when the context is a package declaration.
4646 if Nkind
(N
) = N_Package_Declaration
then
4647 return End_Keyword_Location
(N
);
4649 -- Otherwise the activation call must carry the location of the
4653 return Begin_Keyword_Location
(N
);
4655 end Activation_Call_Loc
;
4666 -- Start of processing for Build_Task_Activation_Call
4669 -- For sequential elaboration policy, all the tasks will be activated at
4670 -- the end of the elaboration.
4672 if Partition_Elaboration_Policy
= 'S' then
4675 -- Do not create an activation call for a package spec if the package
4676 -- has a completing body. The activation call will be inserted after
4677 -- the "begin" of the body.
4679 elsif Nkind
(N
) = N_Package_Declaration
4680 and then Present
(Corresponding_Body
(N
))
4685 -- Obtain the activation chain entity. Block statements, entry bodies,
4686 -- subprogram bodies, and task bodies keep the entity in their nodes.
4687 -- Package bodies on the other hand store it in the declaration of the
4688 -- corresponding package spec.
4692 if Nkind
(Owner
) = N_Package_Body
then
4693 Owner
:= Unit_Declaration_Node
(Corresponding_Spec
(Owner
));
4696 Chain
:= Activation_Chain_Entity
(Owner
);
4698 -- Nothing to do when there are no tasks to activate. This is indicated
4699 -- by a missing activation chain entity; also skip generating it when
4700 -- it is a ghost entity.
4702 if No
(Chain
) or else Is_Ignored_Ghost_Entity
(Chain
) then
4705 -- The availability of the activation chain entity does not ensure
4706 -- that we have tasks to activate because it may have been declared
4707 -- by the frontend to pass a required extra formal to a build-in-place
4708 -- subprogram call. If we are within the scope of a protected type and
4709 -- pragma Detect_Blocking is active we can assume that no tasks will be
4710 -- activated; if tasks are created in a protected object and this pragma
4711 -- is active then the frontend emits a warning and Program_Error is
4712 -- raised at runtime.
4714 elsif Detect_Blocking
and then Within_Protected_Type
(Current_Scope
) then
4718 -- The location of the activation call must be as close as possible to
4719 -- the intended semantic location of the activation because the ABE
4720 -- mechanism relies heavily on accurate locations.
4722 Loc
:= Activation_Call_Loc
;
4724 if Restricted_Profile
then
4725 Name
:= New_Occurrence_Of
(RTE
(RE_Activate_Restricted_Tasks
), Loc
);
4727 Name
:= New_Occurrence_Of
(RTE
(RE_Activate_Tasks
), Loc
);
4731 Make_Procedure_Call_Statement
(Loc
,
4733 Parameter_Associations
=>
4734 New_List
(Make_Attribute_Reference
(Loc
,
4735 Prefix
=> New_Occurrence_Of
(Chain
, Loc
),
4736 Attribute_Name
=> Name_Unchecked_Access
)));
4738 if Nkind
(N
) = N_Package_Declaration
then
4739 if Present
(Private_Declarations
(Specification
(N
))) then
4740 Append
(Call
, Private_Declarations
(Specification
(N
)));
4742 Append
(Call
, Visible_Declarations
(Specification
(N
)));
4746 -- The call goes at the start of the statement sequence after the
4747 -- start of exception range label if one is present.
4749 if Present
(Handled_Statement_Sequence
(N
)) then
4750 Stmt
:= First
(Statements
(Handled_Statement_Sequence
(N
)));
4752 -- A special case, skip exception range label if one is present
4753 -- (from front end zcx processing).
4755 if Nkind
(Stmt
) = N_Label
and then Exception_Junk
(Stmt
) then
4759 -- Another special case, if the first statement is a block from
4760 -- optimization of a local raise to a goto, then the call goes
4761 -- inside this block.
4763 if Nkind
(Stmt
) = N_Block_Statement
4764 and then Exception_Junk
(Stmt
)
4766 Stmt
:= First
(Statements
(Handled_Statement_Sequence
(Stmt
)));
4769 -- Insertion point is after any exception label pushes, since we
4770 -- want it covered by any local handlers.
4772 while Nkind
(Stmt
) in N_Push_xxx_Label
loop
4776 -- Now we have the proper insertion point
4778 Insert_Before
(Stmt
, Call
);
4781 Set_Handled_Statement_Sequence
(N
,
4782 Make_Handled_Sequence_Of_Statements
(Loc
,
4783 Statements
=> New_List
(Call
)));
4789 if Legacy_Elaboration_Checks
then
4790 Check_Task_Activation
(N
);
4792 end Build_Task_Activation_Call
;
4794 -------------------------------
4795 -- Build_Task_Allocate_Block --
4796 -------------------------------
4798 procedure Build_Task_Allocate_Block
4803 T
: constant Entity_Id
:= Entity
(Expression
(N
));
4804 Init
: constant Entity_Id
:= Base_Init_Proc
(T
);
4805 Loc
: constant Source_Ptr
:= Sloc
(N
);
4806 Chain
: constant Entity_Id
:=
4807 Make_Defining_Identifier
(Loc
, Name_uChain
);
4808 Blkent
: constant Entity_Id
:= Make_Temporary
(Loc
, 'A');
4813 Make_Block_Statement
(Loc
,
4814 Identifier
=> New_Occurrence_Of
(Blkent
, Loc
),
4815 Declarations
=> New_List
(
4817 -- _Chain : Activation_Chain;
4819 Make_Object_Declaration
(Loc
,
4820 Defining_Identifier
=> Chain
,
4821 Aliased_Present
=> True,
4822 Object_Definition
=>
4823 New_Occurrence_Of
(RTE
(RE_Activation_Chain
), Loc
))),
4825 Handled_Statement_Sequence
=>
4826 Make_Handled_Sequence_Of_Statements
(Loc
,
4828 Statements
=> New_List
(
4832 Make_Procedure_Call_Statement
(Loc
,
4833 Name
=> New_Occurrence_Of
(Init
, Loc
),
4834 Parameter_Associations
=> Args
),
4836 -- Activate_Tasks (_Chain);
4838 Make_Procedure_Call_Statement
(Loc
,
4839 Name
=> New_Occurrence_Of
(RTE
(RE_Activate_Tasks
), Loc
),
4840 Parameter_Associations
=> New_List
(
4841 Make_Attribute_Reference
(Loc
,
4842 Prefix
=> New_Occurrence_Of
(Chain
, Loc
),
4843 Attribute_Name
=> Name_Unchecked_Access
))))),
4845 Has_Created_Identifier
=> True,
4846 Is_Task_Allocation_Block
=> True);
4849 Make_Implicit_Label_Declaration
(Loc
,
4850 Defining_Identifier
=> Blkent
,
4851 Label_Construct
=> Block
));
4853 Append_To
(Actions
, Block
);
4855 Set_Activation_Chain_Entity
(Block
, Chain
);
4856 end Build_Task_Allocate_Block
;
4858 -----------------------------------------------
4859 -- Build_Task_Allocate_Block_With_Init_Stmts --
4860 -----------------------------------------------
4862 procedure Build_Task_Allocate_Block_With_Init_Stmts
4865 Init_Stmts
: List_Id
)
4867 Loc
: constant Source_Ptr
:= Sloc
(N
);
4868 Chain
: constant Entity_Id
:=
4869 Make_Defining_Identifier
(Loc
, Name_uChain
);
4870 Blkent
: constant Entity_Id
:= Make_Temporary
(Loc
, 'A');
4874 Append_To
(Init_Stmts
,
4875 Make_Procedure_Call_Statement
(Loc
,
4876 Name
=> New_Occurrence_Of
(RTE
(RE_Activate_Tasks
), Loc
),
4877 Parameter_Associations
=> New_List
(
4878 Make_Attribute_Reference
(Loc
,
4879 Prefix
=> New_Occurrence_Of
(Chain
, Loc
),
4880 Attribute_Name
=> Name_Unchecked_Access
))));
4883 Make_Block_Statement
(Loc
,
4884 Identifier
=> New_Occurrence_Of
(Blkent
, Loc
),
4885 Declarations
=> New_List
(
4887 -- _Chain : Activation_Chain;
4889 Make_Object_Declaration
(Loc
,
4890 Defining_Identifier
=> Chain
,
4891 Aliased_Present
=> True,
4892 Object_Definition
=>
4893 New_Occurrence_Of
(RTE
(RE_Activation_Chain
), Loc
))),
4895 Handled_Statement_Sequence
=>
4896 Make_Handled_Sequence_Of_Statements
(Loc
, Init_Stmts
),
4898 Has_Created_Identifier
=> True,
4899 Is_Task_Allocation_Block
=> True);
4902 Make_Implicit_Label_Declaration
(Loc
,
4903 Defining_Identifier
=> Blkent
,
4904 Label_Construct
=> Block
));
4906 Append_To
(Actions
, Block
);
4908 Set_Activation_Chain_Entity
(Block
, Chain
);
4909 end Build_Task_Allocate_Block_With_Init_Stmts
;
4911 -----------------------------------
4912 -- Build_Task_Proc_Specification --
4913 -----------------------------------
4915 function Build_Task_Proc_Specification
(T
: Entity_Id
) return Node_Id
is
4916 Loc
: constant Source_Ptr
:= Sloc
(T
);
4917 Spec_Id
: Entity_Id
;
4920 -- Case of explicit task type, suffix TB
4922 if Comes_From_Source
(T
) then
4924 Make_Defining_Identifier
(Loc
, New_External_Name
(Chars
(T
), "TB"));
4926 -- Case of anonymous task type, suffix B
4930 Make_Defining_Identifier
(Loc
, New_External_Name
(Chars
(T
), 'B'));
4933 Set_Is_Internal
(Spec_Id
);
4935 -- Associate the procedure with the task, if this is the declaration
4936 -- (and not the body) of the procedure.
4938 if No
(Task_Body_Procedure
(T
)) then
4939 Set_Task_Body_Procedure
(T
, Spec_Id
);
4943 Make_Procedure_Specification
(Loc
,
4944 Defining_Unit_Name
=> Spec_Id
,
4945 Parameter_Specifications
=> New_List
(
4946 Make_Parameter_Specification
(Loc
,
4947 Defining_Identifier
=>
4948 Make_Defining_Identifier
(Loc
, Name_uTask
),
4950 Make_Access_Definition
(Loc
,
4952 New_Occurrence_Of
(Corresponding_Record_Type
(T
), Loc
)))));
4953 end Build_Task_Proc_Specification
;
4955 ---------------------------------------
4956 -- Build_Unprotected_Subprogram_Body --
4957 ---------------------------------------
4959 function Build_Unprotected_Subprogram_Body
4961 Pid
: Node_Id
) return Node_Id
4963 Decls
: constant List_Id
:= Declarations
(N
);
4966 -- Add renamings for the Protection object, discriminals, privals, and
4967 -- the entry index constant for use by debugger.
4969 Debug_Private_Data_Declarations
(Decls
);
4971 -- Make an unprotected version of the subprogram for use within the same
4972 -- object, with a new name and an additional parameter representing the
4976 Make_Subprogram_Body
(Sloc
(N
),
4978 Build_Protected_Sub_Specification
(N
, Pid
, Unprotected_Mode
),
4979 Declarations
=> Decls
,
4980 Handled_Statement_Sequence
=> Handled_Statement_Sequence
(N
),
4981 At_End_Proc
=> At_End_Proc
(N
));
4982 end Build_Unprotected_Subprogram_Body
;
4984 ----------------------------
4985 -- Collect_Entry_Families --
4986 ----------------------------
4988 procedure Collect_Entry_Families
4991 Current_Node
: in out Node_Id
;
4992 Conctyp
: Entity_Id
)
4995 Efam_Decl
: Node_Id
;
4996 Efam_Type
: Entity_Id
;
4999 Efam
:= First_Entity
(Conctyp
);
5000 while Present
(Efam
) loop
5001 if Ekind
(Efam
) = E_Entry_Family
then
5002 Efam_Type
:= Make_Temporary
(Loc
, 'F');
5005 Eityp
: constant Entity_Id
:= Entry_Index_Type
(Efam
);
5006 Lo
: constant Node_Id
:= Type_Low_Bound
(Eityp
);
5007 Hi
: constant Node_Id
:= Type_High_Bound
(Eityp
);
5012 Bityp
:= Base_Type
(Eityp
);
5014 if Is_Potentially_Large_Family
(Bityp
, Conctyp
, Lo
, Hi
) then
5015 Bityp
:= Make_Temporary
(Loc
, 'B');
5018 Make_Subtype_Declaration
(Loc
,
5019 Defining_Identifier
=> Bityp
,
5020 Subtype_Indication
=>
5021 Make_Subtype_Indication
(Loc
,
5023 New_Occurrence_Of
(Standard_Integer
, Loc
),
5025 Make_Range_Constraint
(Loc
,
5026 Range_Expression
=> Make_Range
(Loc
,
5027 Make_Integer_Literal
5028 (Loc
, -Entry_Family_Bound
),
5029 Make_Integer_Literal
5030 (Loc
, Entry_Family_Bound
- 1)))));
5032 Insert_After
(Current_Node
, Bdecl
);
5033 Current_Node
:= Bdecl
;
5038 Make_Full_Type_Declaration
(Loc
,
5039 Defining_Identifier
=> Efam_Type
,
5041 Make_Unconstrained_Array_Definition
(Loc
,
5043 (New_List
(New_Occurrence_Of
(Bityp
, Loc
))),
5045 Component_Definition
=>
5046 Make_Component_Definition
(Loc
,
5047 Aliased_Present
=> False,
5048 Subtype_Indication
=>
5049 New_Occurrence_Of
(Standard_Character
, Loc
))));
5052 Insert_After
(Current_Node
, Efam_Decl
);
5053 Current_Node
:= Efam_Decl
;
5054 Analyze
(Efam_Decl
);
5057 Make_Component_Declaration
(Loc
,
5058 Defining_Identifier
=>
5059 Make_Defining_Identifier
(Loc
, Chars
(Efam
)),
5061 Component_Definition
=>
5062 Make_Component_Definition
(Loc
,
5063 Aliased_Present
=> False,
5064 Subtype_Indication
=>
5065 Make_Subtype_Indication
(Loc
,
5067 New_Occurrence_Of
(Efam_Type
, Loc
),
5070 Make_Index_Or_Discriminant_Constraint
(Loc
,
5071 Constraints
=> New_List
(
5072 New_Occurrence_Of
(Entry_Index_Type
(Efam
),
5078 end Collect_Entry_Families
;
5080 -----------------------
5081 -- Concurrent_Object --
5082 -----------------------
5084 function Concurrent_Object
5085 (Spec_Id
: Entity_Id
;
5086 Conc_Typ
: Entity_Id
) return Entity_Id
5089 -- Parameter _O or _object
5091 if Is_Protected_Type
(Conc_Typ
) then
5092 return First_Formal
(Protected_Body_Subprogram
(Spec_Id
));
5097 pragma Assert
(Is_Task_Type
(Conc_Typ
));
5098 return First_Formal
(Task_Body_Procedure
(Conc_Typ
));
5100 end Concurrent_Object
;
5102 ----------------------
5103 -- Copy_Result_Type --
5104 ----------------------
5106 function Copy_Result_Type
(Res
: Node_Id
) return Node_Id
is
5107 New_Res
: constant Node_Id
:= New_Copy_Tree
(Res
);
5112 -- If the result type is an access_to_subprogram, we must create new
5113 -- entities for its spec.
5115 if Nkind
(New_Res
) = N_Access_Definition
5116 and then Present
(Access_To_Subprogram_Definition
(New_Res
))
5118 -- Provide new entities for the formals
5120 Par_Spec
:= First
(Parameter_Specifications
5121 (Access_To_Subprogram_Definition
(New_Res
)));
5122 while Present
(Par_Spec
) loop
5123 Formal
:= Defining_Identifier
(Par_Spec
);
5124 Set_Defining_Identifier
(Par_Spec
,
5125 Make_Defining_Identifier
(Sloc
(Formal
), Chars
(Formal
)));
5131 end Copy_Result_Type
;
5133 --------------------
5134 -- Concurrent_Ref --
5135 --------------------
5137 -- The expression returned for a reference to a concurrent object has the
5140 -- taskV!(name)._Task_Id
5144 -- objectV!(name)._Object
5146 -- for a protected object. For the case of an access to a concurrent
5147 -- object, there is an extra explicit dereference:
5149 -- taskV!(name.all)._Task_Id
5150 -- objectV!(name.all)._Object
5152 -- here taskV and objectV are the types for the associated records, which
5153 -- contain the required _Task_Id and _Object fields for tasks and protected
5154 -- objects, respectively.
5156 -- For the case of a task type name, the expression is
5160 -- i.e. a call to the Self function which returns precisely this Task_Id
5162 -- For the case of a protected type name, the expression is
5166 -- which is a renaming of the _object field of the current object
5167 -- record, passed into protected operations as a parameter.
5169 function Concurrent_Ref
(N
: Node_Id
) return Node_Id
is
5170 Loc
: constant Source_Ptr
:= Sloc
(N
);
5171 Ntyp
: constant Entity_Id
:= Etype
(N
);
5175 function Is_Current_Task
(T
: Entity_Id
) return Boolean;
5176 -- Check whether the reference is to the immediately enclosing task
5177 -- type, or to an outer one (rare but legal).
5179 ---------------------
5180 -- Is_Current_Task --
5181 ---------------------
5183 function Is_Current_Task
(T
: Entity_Id
) return Boolean is
5187 Scop
:= Current_Scope
;
5188 while Present
(Scop
) and then Scop
/= Standard_Standard
loop
5192 elsif Is_Task_Type
(Scop
) then
5195 -- If this is a procedure nested within the task type, we must
5196 -- assume that it can be called from an inner task, and therefore
5197 -- cannot treat it as a local reference.
5199 elsif Is_Overloadable
(Scop
) and then In_Open_Scopes
(T
) then
5203 Scop
:= Scope
(Scop
);
5207 -- We know that we are within the task body, so should have found it
5210 raise Program_Error
;
5211 end Is_Current_Task
;
5213 -- Start of processing for Concurrent_Ref
5216 if Is_Access_Type
(Ntyp
) then
5217 Dtyp
:= Designated_Type
(Ntyp
);
5219 if Is_Protected_Type
(Dtyp
) then
5220 Sel
:= Name_uObject
;
5222 Sel
:= Name_uTask_Id
;
5226 Make_Selected_Component
(Loc
,
5228 Unchecked_Convert_To
(Corresponding_Record_Type
(Dtyp
),
5229 Make_Explicit_Dereference
(Loc
, N
)),
5230 Selector_Name
=> Make_Identifier
(Loc
, Sel
));
5232 elsif Is_Entity_Name
(N
) and then Is_Concurrent_Type
(Entity
(N
)) then
5233 if Is_Task_Type
(Entity
(N
)) then
5235 if Is_Current_Task
(Entity
(N
)) then
5237 Make_Function_Call
(Loc
,
5238 Name
=> New_Occurrence_Of
(RTE
(RE_Self
), Loc
));
5243 T_Self
: constant Entity_Id
:= Make_Temporary
(Loc
, 'T');
5244 T_Body
: constant Node_Id
:=
5245 Parent
(Corresponding_Body
(Parent
(Entity
(N
))));
5249 Make_Object_Declaration
(Loc
,
5250 Defining_Identifier
=> T_Self
,
5251 Object_Definition
=>
5252 New_Occurrence_Of
(RTE
(RO_ST_Task_Id
), Loc
),
5254 Make_Function_Call
(Loc
,
5255 Name
=> New_Occurrence_Of
(RTE
(RE_Self
), Loc
)));
5256 Prepend
(Decl
, Declarations
(T_Body
));
5258 Set_Scope
(T_Self
, Entity
(N
));
5259 return New_Occurrence_Of
(T_Self
, Loc
);
5264 pragma Assert
(Is_Protected_Type
(Entity
(N
)));
5267 New_Occurrence_Of
(Find_Protection_Object
(Current_Scope
), Loc
);
5271 if Is_Protected_Type
(Ntyp
) then
5272 Sel
:= Name_uObject
;
5273 elsif Is_Task_Type
(Ntyp
) then
5274 Sel
:= Name_uTask_Id
;
5276 raise Program_Error
;
5280 Make_Selected_Component
(Loc
,
5282 Unchecked_Convert_To
(Corresponding_Record_Type
(Ntyp
),
5284 Selector_Name
=> Make_Identifier
(Loc
, Sel
));
5288 ------------------------
5289 -- Convert_Concurrent --
5290 ------------------------
5292 function Convert_Concurrent
5294 Typ
: Entity_Id
) return Node_Id
5297 if not Is_Concurrent_Type
(Typ
) then
5301 Unchecked_Convert_To
5302 (Corresponding_Record_Type
(Typ
), New_Copy_Tree
(N
));
5304 end Convert_Concurrent
;
5306 -------------------------------------
5307 -- Create_Secondary_Stack_For_Task --
5308 -------------------------------------
5310 function Create_Secondary_Stack_For_Task
(T
: Node_Id
) return Boolean is
5313 (Restriction_Active
(No_Implicit_Heap_Allocations
)
5314 or else Restriction_Active
(No_Implicit_Task_Allocations
))
5315 and then not Restriction_Active
(No_Secondary_Stack
)
5316 and then Has_Rep_Pragma
5317 (T
, Name_Secondary_Stack_Size
, Check_Parents
=> False);
5318 end Create_Secondary_Stack_For_Task
;
5320 -------------------------------------
5321 -- Debug_Private_Data_Declarations --
5322 -------------------------------------
5324 procedure Debug_Private_Data_Declarations
(Decls
: List_Id
) is
5325 Debug_Nod
: Node_Id
;
5329 Decl
:= First
(Decls
);
5330 while Present
(Decl
) and then not Comes_From_Source
(Decl
) loop
5332 -- Declaration for concurrent entity _object and its access type,
5333 -- along with the entry index subtype:
5334 -- type prot_typVP is access prot_typV;
5335 -- _object : prot_typVP := prot_typV (_O);
5336 -- subtype Jnn is <Type of Index> range Low .. High;
5338 if Nkind
(Decl
) in N_Full_Type_Declaration | N_Object_Declaration
then
5339 Set_Debug_Info_Needed
(Defining_Identifier
(Decl
));
5341 -- Declaration for the Protection object, discriminals, privals, and
5342 -- entry index constant:
5343 -- conc_typR : protection_typ renames _object._object;
5344 -- discr_nameD : discr_typ renames _object.discr_name;
5345 -- discr_nameD : discr_typ renames _task.discr_name;
5346 -- prival_name : comp_typ renames _object.comp_name;
5347 -- J : constant Jnn :=
5348 -- Jnn'Val (_E - <Index expression> + Jnn'Pos (Jnn'First));
5350 elsif Nkind
(Decl
) = N_Object_Renaming_Declaration
then
5351 Set_Debug_Info_Needed
(Defining_Identifier
(Decl
));
5352 Debug_Nod
:= Debug_Renaming_Declaration
(Decl
);
5354 if Present
(Debug_Nod
) then
5355 Insert_After
(Decl
, Debug_Nod
);
5361 end Debug_Private_Data_Declarations
;
5363 ------------------------------
5364 -- Ensure_Statement_Present --
5365 ------------------------------
5367 procedure Ensure_Statement_Present
(Loc
: Source_Ptr
; Alt
: Node_Id
) is
5371 if Opt
.Suppress_Control_Flow_Optimizations
5372 and then Is_Empty_List
(Statements
(Alt
))
5374 Stmt
:= Make_Null_Statement
(Loc
);
5376 -- Mark NULL statement as coming from source so that it is not
5377 -- eliminated by GIGI.
5379 -- Another covert channel. If this is a requirement, it must be
5380 -- documented in sinfo/einfo ???
5382 Set_Comes_From_Source
(Stmt
, True);
5384 Set_Statements
(Alt
, New_List
(Stmt
));
5386 end Ensure_Statement_Present
;
5388 ----------------------------
5389 -- Entry_Index_Expression --
5390 ----------------------------
5392 function Entry_Index_Expression
5396 Ttyp
: Entity_Id
) return Node_Id
5406 -- The queues of entries and entry families appear in textual order in
5407 -- the associated record. The entry index is computed as the sum of the
5408 -- number of queues for all entries that precede the designated one, to
5409 -- which is added the index expression, if this expression denotes a
5410 -- member of a family.
5412 -- The following is a place holder for the count of simple entries
5414 Num
:= Make_Integer_Literal
(Sloc
, 1);
5416 -- We construct an expression which is a series of addition operations.
5417 -- The first operand is the number of single entries that precede this
5418 -- one, the second operand is the index value relative to the start of
5419 -- the referenced family, and the remaining operands are the lengths of
5420 -- the entry families that precede this entry, i.e. the constructed
5423 -- number_simple_entries +
5424 -- (s'pos (index-value) - s'pos (family'first)) + 1 +
5425 -- family'length + ...
5427 -- where index-value is the given index value, and s is the index
5428 -- subtype (we have to use pos because the subtype might be an
5429 -- enumeration type preventing direct subtraction). Note that the task
5430 -- entry array is one-indexed.
5432 -- The upper bound of the entry family may be a discriminant, so we
5433 -- retrieve the lower bound explicitly to compute offset, rather than
5434 -- using the index subtype which may mention a discriminant.
5436 if Present
(Index
) then
5437 S
:= Entry_Index_Type
(Ent
);
5439 -- First make sure the index is in range if requested. The index type
5440 -- is the pristine Entry_Index_Type of the entry.
5442 if Do_Range_Check
(Index
) then
5443 Generate_Range_Check
(Index
, S
, CE_Range_Check_Failed
);
5452 Make_Attribute_Reference
(Sloc
,
5453 Attribute_Name
=> Name_Pos
,
5454 Prefix
=> New_Occurrence_Of
(Base_Type
(S
), Sloc
),
5455 Expressions
=> New_List
(Relocate_Node
(Index
))),
5463 -- Now add lengths of preceding entries and entry families
5465 Prev
:= First_Entity
(Ttyp
);
5466 while Chars
(Prev
) /= Chars
(Ent
)
5467 or else Ekind
(Prev
) /= Ekind
(Ent
)
5468 or else not Sem_Ch6
.Type_Conformant
(Ent
, Prev
)
5470 if Ekind
(Prev
) = E_Entry
then
5471 Set_Intval
(Num
, Intval
(Num
) + 1);
5473 elsif Ekind
(Prev
) = E_Entry_Family
then
5474 S
:= Entry_Index_Type
(Prev
);
5475 Lo
:= Type_Low_Bound
(S
);
5476 Hi
:= Type_High_Bound
(S
);
5481 Right_Opnd
=> Family_Size
(Sloc
, Hi
, Lo
, Ttyp
, False));
5483 -- Other components are anonymous types to be ignored
5493 end Entry_Index_Expression
;
5495 ---------------------------
5496 -- Establish_Task_Master --
5497 ---------------------------
5499 procedure Establish_Task_Master
(N
: Node_Id
) is
5503 if Restriction_Active
(No_Task_Hierarchy
) = False then
5504 Call
:= Build_Runtime_Call
(Sloc
(N
), RE_Enter_Master
);
5506 -- The block may have no declarations (and nevertheless be a task
5507 -- master) if it contains a call that may return an object that
5510 if No
(Declarations
(N
)) then
5511 Set_Declarations
(N
, New_List
(Call
));
5513 Prepend_To
(Declarations
(N
), Call
);
5518 end Establish_Task_Master
;
5520 --------------------------------
5521 -- Expand_Accept_Declarations --
5522 --------------------------------
5524 -- Part of the expansion of an accept statement involves the creation of
5525 -- a declaration that can be referenced from the statement sequence of
5530 -- This declaration is inserted immediately before the accept statement
5531 -- and it is important that it be inserted before the statements of the
5532 -- statement sequence are analyzed. Thus it would be too late to create
5533 -- this declaration in the Expand_N_Accept_Statement routine, which is
5534 -- why there is a separate procedure to be called directly from Sem_Ch9.
5536 -- Ann is used to hold the address of the record containing the parameters
5537 -- (see Expand_N_Entry_Call for more details on how this record is built).
5538 -- References to the parameters do an unchecked conversion of this address
5539 -- to a pointer to the required record type, and then access the field that
5540 -- holds the value of the required parameter. The entity for the address
5541 -- variable is held as the top stack element (i.e. the last element) of the
5542 -- Accept_Address stack in the corresponding entry entity, and this element
5543 -- must be set in place before the statements are processed.
5545 -- The above description applies to the case of a stand alone accept
5546 -- statement, i.e. one not appearing as part of a select alternative.
5548 -- For the case of an accept that appears as part of a select alternative
5549 -- of a selective accept, we must still create the declaration right away,
5550 -- since Ann is needed immediately, but there is an important difference:
5552 -- The declaration is inserted before the selective accept, not before
5553 -- the accept statement (which is not part of a list anyway, and so would
5554 -- not accommodate inserted declarations)
5556 -- We only need one address variable for the entire selective accept. So
5557 -- the Ann declaration is created only for the first accept alternative,
5558 -- and subsequent accept alternatives reference the same Ann variable.
5560 -- We can distinguish the two cases by seeing whether the accept statement
5561 -- is part of a list. If not, then it must be in an accept alternative.
5563 -- To expand the requeue statement, a label is provided at the end of the
5564 -- accept statement or alternative of which it is a part, so that the
5565 -- statement can be skipped after the requeue is complete. This label is
5566 -- created here rather than during the expansion of the accept statement,
5567 -- because it will be needed by any requeue statements within the accept,
5568 -- which are expanded before the accept.
5570 procedure Expand_Accept_Declarations
(N
: Node_Id
; Ent
: Entity_Id
) is
5571 Loc
: constant Source_Ptr
:= Sloc
(N
);
5572 Stats
: constant Node_Id
:= Handled_Statement_Sequence
(N
);
5573 Ann
: Entity_Id
:= Empty
;
5580 if Expander_Active
then
5582 -- If we have no handled statement sequence, we may need to build
5583 -- a dummy sequence consisting of a null statement. This can be
5584 -- skipped if the trivial accept optimization is permitted.
5586 if not Trivial_Accept_OK
5587 and then (No
(Stats
) or else Null_Statements
(Statements
(Stats
)))
5589 Set_Handled_Statement_Sequence
(N
,
5590 Make_Handled_Sequence_Of_Statements
(Loc
,
5591 Statements
=> New_List
(Make_Null_Statement
(Loc
))));
5594 -- Create and declare two labels to be placed at the end of the
5595 -- accept statement. The first label is used to allow requeues to
5596 -- skip the remainder of entry processing. The second label is used
5597 -- to skip the remainder of entry processing if the rendezvous
5598 -- completes in the middle of the accept body.
5600 if Present
(Handled_Statement_Sequence
(N
)) then
5605 Ent
:= Make_Temporary
(Loc
, 'L');
5606 Lab
:= Make_Label
(Loc
, New_Occurrence_Of
(Ent
, Loc
));
5608 Make_Implicit_Label_Declaration
(Loc
,
5609 Defining_Identifier
=> Ent
,
5610 Label_Construct
=> Lab
);
5611 Append
(Lab
, Statements
(Handled_Statement_Sequence
(N
)));
5613 Ent
:= Make_Temporary
(Loc
, 'L');
5614 Lab
:= Make_Label
(Loc
, New_Occurrence_Of
(Ent
, Loc
));
5616 Make_Implicit_Label_Declaration
(Loc
,
5617 Defining_Identifier
=> Ent
,
5618 Label_Construct
=> Lab
);
5619 Append
(Lab
, Statements
(Handled_Statement_Sequence
(N
)));
5627 -- Case of stand alone accept statement
5629 if Is_List_Member
(N
) then
5631 if Present
(Handled_Statement_Sequence
(N
)) then
5632 Ann
:= Make_Temporary
(Loc
, 'A');
5635 Make_Object_Declaration
(Loc
,
5636 Defining_Identifier
=> Ann
,
5637 Object_Definition
=>
5638 New_Occurrence_Of
(RTE
(RE_Address
), Loc
));
5640 Insert_Before_And_Analyze
(N
, Adecl
);
5641 Insert_Before_And_Analyze
(N
, Ldecl
);
5642 Insert_Before_And_Analyze
(N
, Ldecl2
);
5645 -- Case of accept statement which is in an accept alternative
5649 Acc_Alt
: constant Node_Id
:= Parent
(N
);
5650 Sel_Acc
: constant Node_Id
:= Parent
(Acc_Alt
);
5654 pragma Assert
(Nkind
(Acc_Alt
) = N_Accept_Alternative
);
5655 pragma Assert
(Nkind
(Sel_Acc
) = N_Selective_Accept
);
5657 -- ??? Consider a single label for select statements
5659 if Present
(Handled_Statement_Sequence
(N
)) then
5661 Statements
(Handled_Statement_Sequence
(N
)));
5665 Statements
(Handled_Statement_Sequence
(N
)));
5669 -- Find first accept alternative of the selective accept. A
5670 -- valid selective accept must have at least one accept in it.
5672 Alt
:= First
(Select_Alternatives
(Sel_Acc
));
5674 while Nkind
(Alt
) /= N_Accept_Alternative
loop
5678 -- If this is the first accept statement, then we have to
5679 -- create the Ann variable, as for the stand alone case, except
5680 -- that it is inserted before the selective accept. Similarly,
5681 -- a label for requeue expansion must be declared.
5683 if N
= Accept_Statement
(Alt
) then
5684 Ann
:= Make_Temporary
(Loc
, 'A');
5686 Make_Object_Declaration
(Loc
,
5687 Defining_Identifier
=> Ann
,
5688 Object_Definition
=>
5689 New_Occurrence_Of
(RTE
(RE_Address
), Loc
));
5691 Insert_Before_And_Analyze
(Sel_Acc
, Adecl
);
5693 -- If this is not the first accept statement, then find the Ann
5694 -- variable allocated by the first accept and use it.
5698 Node
(Last_Elmt
(Accept_Address
5699 (Entity
(Entry_Direct_Name
(Accept_Statement
(Alt
))))));
5704 -- Merge here with Ann either created or referenced, and Adecl
5705 -- pointing to the corresponding declaration. Remaining processing
5706 -- is the same for the two cases.
5708 if Present
(Ann
) then
5709 Append_Elmt
(Ann
, Accept_Address
(Ent
));
5710 Set_Debug_Info_Needed
(Ann
);
5713 -- Create renaming declarations for the entry formals. Each reference
5714 -- to a formal becomes a dereference of a component of the parameter
5715 -- block, whose address is held in Ann. These declarations are
5716 -- eventually inserted into the accept block, and analyzed there so
5717 -- that they have the proper scope for gdb and do not conflict with
5718 -- other declarations.
5720 if Present
(Parameter_Specifications
(N
))
5721 and then Present
(Handled_Statement_Sequence
(N
))
5728 Renamed_Formal
: Node_Id
;
5732 Formal
:= First_Formal
(Ent
);
5734 while Present
(Formal
) loop
5735 Comp
:= Entry_Component
(Formal
);
5736 New_F
:= Make_Defining_Identifier
(Loc
, Chars
(Formal
));
5738 Set_Etype
(New_F
, Etype
(Formal
));
5739 Set_Scope
(New_F
, Ent
);
5741 -- Now we set debug info needed on New_F even though it does
5742 -- not come from source, so that the debugger will get the
5743 -- right information for these generated names.
5745 Set_Debug_Info_Needed
(New_F
);
5747 if Ekind
(Formal
) = E_In_Parameter
then
5748 Mutate_Ekind
(New_F
, E_Constant
);
5750 Mutate_Ekind
(New_F
, E_Variable
);
5751 Set_Extra_Constrained
(New_F
, Extra_Constrained
(Formal
));
5754 Set_Actual_Subtype
(New_F
, Actual_Subtype
(Formal
));
5757 Make_Selected_Component
(Loc
,
5759 Make_Explicit_Dereference
(Loc
,
5760 Unchecked_Convert_To
(
5761 Entry_Parameters_Type
(Ent
),
5762 New_Occurrence_Of
(Ann
, Loc
))),
5764 New_Occurrence_Of
(Comp
, Loc
));
5767 Build_Renamed_Formal_Declaration
5768 (New_F
, Formal
, Comp
, Renamed_Formal
);
5770 if No
(Declarations
(N
)) then
5771 Set_Declarations
(N
, New_List
);
5774 Append
(Decl
, Declarations
(N
));
5775 Set_Renamed_Object
(Formal
, New_F
);
5776 Next_Formal
(Formal
);
5783 end Expand_Accept_Declarations
;
5785 ---------------------------------------------
5786 -- Expand_Access_Protected_Subprogram_Type --
5787 ---------------------------------------------
5789 procedure Expand_Access_Protected_Subprogram_Type
(N
: Node_Id
) is
5790 Loc
: constant Source_Ptr
:= Sloc
(N
);
5791 T
: constant Entity_Id
:= Defining_Identifier
(N
);
5792 D_T
: constant Entity_Id
:= Designated_Type
(T
);
5793 D_T2
: constant Entity_Id
:= Make_Temporary
(Loc
, 'D');
5794 E_T
: constant Entity_Id
:= Make_Temporary
(Loc
, 'E');
5795 P_List
: constant List_Id
:=
5796 Build_Protected_Spec
(N
, RTE
(RE_Address
), D_T
, False);
5804 -- Create access to subprogram with full signature
5806 if Etype
(D_T
) /= Standard_Void_Type
then
5808 Make_Access_Function_Definition
(Loc
,
5809 Parameter_Specifications
=> P_List
,
5810 Result_Definition
=>
5811 Copy_Result_Type
(Result_Definition
(Type_Definition
(N
))));
5815 Make_Access_Procedure_Definition
(Loc
,
5816 Parameter_Specifications
=> P_List
);
5820 Make_Full_Type_Declaration
(Loc
,
5821 Defining_Identifier
=> D_T2
,
5822 Type_Definition
=> Def1
);
5824 -- Declare the new types before the original one since the latter will
5825 -- refer to them through the Equivalent_Type slot.
5827 Insert_Before_And_Analyze
(N
, Decl1
);
5829 -- Associate the access to subprogram with its original access to
5830 -- protected subprogram type. Needed by the backend to know that this
5831 -- type corresponds with an access to protected subprogram type.
5833 Set_Original_Access_Type
(D_T2
, T
);
5835 -- Create Equivalent_Type, a record with two components for an access to
5836 -- object and an access to subprogram.
5839 Make_Component_Declaration
(Loc
,
5840 Defining_Identifier
=> Make_Temporary
(Loc
, 'P'),
5841 Component_Definition
=>
5842 Make_Component_Definition
(Loc
,
5843 Aliased_Present
=> False,
5844 Subtype_Indication
=>
5845 New_Occurrence_Of
(RTE
(RE_Address
), Loc
))),
5847 Make_Component_Declaration
(Loc
,
5848 Defining_Identifier
=> Make_Temporary
(Loc
, 'S'),
5849 Component_Definition
=>
5850 Make_Component_Definition
(Loc
,
5851 Aliased_Present
=> False,
5852 Subtype_Indication
=> New_Occurrence_Of
(D_T2
, Loc
))));
5855 Make_Full_Type_Declaration
(Loc
,
5856 Defining_Identifier
=> E_T
,
5858 Make_Record_Definition
(Loc
,
5860 Make_Component_List
(Loc
, Component_Items
=> Comps
)));
5862 Insert_Before_And_Analyze
(N
, Decl2
);
5863 Set_Equivalent_Type
(T
, E_T
);
5864 end Expand_Access_Protected_Subprogram_Type
;
5866 --------------------------
5867 -- Expand_Entry_Barrier --
5868 --------------------------
5870 procedure Expand_Entry_Barrier
(N
: Node_Id
; Ent
: Entity_Id
) is
5871 Cond
: constant Node_Id
:= Condition
(Entry_Body_Formal_Part
(N
));
5872 Prot
: constant Entity_Id
:= Scope
(Ent
);
5873 Spec_Decl
: constant Node_Id
:= Parent
(Prot
);
5875 Func_Id
: Entity_Id
:= Empty
;
5876 -- The entity of the barrier function
5878 function Is_Global_Entity
(N
: Node_Id
) return Traverse_Result
;
5879 -- Check whether entity in Barrier is external to protected type.
5880 -- If so, barrier may not be properly synchronized.
5882 function Is_Pure_Barrier
(N
: Node_Id
) return Traverse_Result
;
5883 -- Check whether N meets the Pure_Barriers restriction. Return OK if
5886 function Is_Simple_Barrier
(N
: Node_Id
) return Boolean;
5887 -- Check whether N meets the Simple_Barriers restriction. Return OK if
5890 ----------------------
5891 -- Is_Global_Entity --
5892 ----------------------
5894 function Is_Global_Entity
(N
: Node_Id
) return Traverse_Result
is
5899 if Is_Entity_Name
(N
) and then Present
(Entity
(N
)) then
5903 if Ekind
(E
) = E_Variable
then
5905 -- If the variable is local to the barrier function generated
5906 -- during expansion, it is ok. If expansion is not performed,
5907 -- then Func is Empty so this test cannot succeed.
5909 if Scope
(E
) = Func_Id
then
5912 -- A protected call from a barrier to another object is ok
5914 elsif Ekind
(Etype
(E
)) = E_Protected_Type
then
5917 -- If the variable is within the package body we consider
5918 -- this safe. This is a common (if dubious) idiom.
5920 elsif S
= Scope
(Prot
)
5921 and then Is_Package_Or_Generic_Package
(S
)
5922 and then Nkind
(Parent
(E
)) = N_Object_Declaration
5923 and then Nkind
(Parent
(Parent
(E
))) = N_Package_Body
5928 Error_Msg_N
("potentially unsynchronized barrier??", N
);
5929 Error_Msg_N
("\& should be private component of type??", N
);
5935 end Is_Global_Entity
;
5937 procedure Check_Unprotected_Barrier
is
5938 new Traverse_Proc
(Is_Global_Entity
);
5940 -----------------------
5941 -- Is_Simple_Barrier --
5942 -----------------------
5944 function Is_Simple_Barrier
(N
: Node_Id
) return Boolean is
5948 if Is_Static_Expression
(N
) then
5950 elsif Ada_Version
>= Ada_2022
5951 and then Nkind
(N
) in N_Selected_Component | N_Indexed_Component
5952 and then Statically_Names_Object
(N
)
5954 -- Restriction relaxed in Ada 2022 to allow statically named
5956 return Is_Simple_Barrier
(Prefix
(N
));
5959 -- Check if the name is a component of the protected object. If
5960 -- the expander is active, the component has been transformed into a
5961 -- renaming of _object.all.component. Original_Node is needed in case
5962 -- validity checking is enabled, in which case the simple object
5963 -- reference will have been rewritten.
5965 if Expander_Active
then
5967 -- The expanded name may have been constant folded in which case
5968 -- the original node is not necessarily an entity name (e.g. an
5969 -- indexed component).
5971 if not Is_Entity_Name
(Original_Node
(N
)) then
5975 Renamed
:= Renamed_Object
(Entity
(Original_Node
(N
)));
5979 and then Nkind
(Renamed
) = N_Selected_Component
5980 and then Chars
(Prefix
(Prefix
(Renamed
))) = Name_uObject
;
5981 elsif not Is_Entity_Name
(N
) then
5984 return Is_Protected_Component
(Entity
(N
));
5986 end Is_Simple_Barrier
;
5988 ---------------------
5989 -- Is_Pure_Barrier --
5990 ---------------------
5992 function Is_Pure_Barrier
(N
: Node_Id
) return Traverse_Result
is
5995 when N_Expanded_Name
5999 -- Because of N_Expanded_Name case, return Skip instead of OK.
6001 if No
(Entity
(N
)) then
6004 elsif Is_Numeric_Type
(Entity
(N
)) then
6008 case Ekind
(Entity
(N
)) is
6014 when E_Enumeration_Literal
6018 if not Is_OK_Static_Expression
(N
) then
6027 if Is_Simple_Barrier
(N
) then
6033 -- The count attribute has been transformed into run-time
6036 if Is_RTE
(Entity
(N
), RE_Protected_Count
)
6037 or else Is_RTE
(Entity
(N
), RE_Protected_Count_Entry
)
6046 when N_Function_Call
=>
6048 -- Function call checks are carried out as part of the analysis
6049 -- of the function call name.
6053 when N_Character_Literal
6062 if Ekind
(Entity
(N
)) = E_Operator
then
6066 when N_Short_Circuit
6072 when N_Indexed_Component | N_Selected_Component
=>
6073 if Statically_Names_Object
(N
) then
6074 return Is_Pure_Barrier
(Prefix
(N
));
6079 when N_Case_Expression_Alternative
=>
6080 -- do not traverse Discrete_Choices subtree
6081 if Is_Pure_Barrier
(Expression
(N
)) /= Abandon
then
6085 when N_Expression_With_Actions
=>
6086 -- this may occur in the case of a Count attribute reference
6087 if Is_Rewrite_Substitution
(N
)
6088 and then Is_Pure_Barrier
(Original_Node
(N
)) /= Abandon
6093 when N_Membership_Test
=>
6094 if Is_Pure_Barrier
(Left_Opnd
(N
)) /= Abandon
6095 and then All_Membership_Choices_Static
(N
)
6100 when N_Type_Conversion
=>
6102 -- Conversions to Universal_Integer do not raise constraint
6103 -- errors. Likewise if the expression's type is statically
6104 -- compatible with the target's type.
6106 if Etype
(N
) = Universal_Integer
6107 or else Subtypes_Statically_Compatible
6108 (Etype
(Expression
(N
)), Etype
(N
))
6113 when N_Unchecked_Type_Conversion
=>
6121 end Is_Pure_Barrier
;
6123 function Check_Pure_Barriers
is new Traverse_Func
(Is_Pure_Barrier
);
6127 Entry_Body
: Node_Id
;
6128 Func_Body
: Node_Id
:= Empty
;
6130 -- Start of processing for Expand_Entry_Barrier
6133 if No_Run_Time_Mode
then
6134 Error_Msg_CRT
("entry barrier", N
);
6138 -- Prevent cascaded errors
6140 if Nkind
(Cond
) = N_Error
then
6144 -- The body of the entry barrier must be analyzed in the context of the
6145 -- protected object, but its scope is external to it, just as any other
6146 -- unprotected version of a protected operation. The specification has
6147 -- been produced when the protected type declaration was elaborated. We
6148 -- build the body, insert it in the enclosing scope, but analyze it in
6149 -- the current context. A more uniform approach would be to treat the
6150 -- barrier just as a protected function, and discard the protected
6151 -- version of it because it is never called.
6153 if Expander_Active
then
6154 Func_Body
:= Build_Barrier_Function
(N
, Ent
, Prot
);
6155 Func_Id
:= Barrier_Function
(Ent
);
6156 Set_Corresponding_Spec
(Func_Body
, Func_Id
);
6158 Entry_Body
:= Parent
(Corresponding_Body
(Spec_Decl
));
6160 if Nkind
(Parent
(Entry_Body
)) = N_Subunit
then
6161 Entry_Body
:= Corresponding_Stub
(Parent
(Entry_Body
));
6164 Insert_Before_And_Analyze
(Entry_Body
, Func_Body
);
6166 Set_Discriminals
(Spec_Decl
);
6167 Set_Scope
(Func_Id
, Scope
(Prot
));
6170 Analyze_And_Resolve
(Cond
, Any_Boolean
);
6173 -- Check Simple_Barriers and Pure_Barriers restrictions.
6174 -- Note that it is safe to be calling Check_Restriction from here, even
6175 -- though this is part of the expander, since Expand_Entry_Barrier is
6176 -- called from Sem_Ch9 even in -gnatc mode.
6178 if not Is_Simple_Barrier
(Cond
) then
6179 -- flag restriction violation
6180 Check_Restriction
(Simple_Barriers
, Cond
);
6183 if Check_Pure_Barriers
(Cond
) = Abandon
then
6184 -- flag restriction violation
6185 Check_Restriction
(Pure_Barriers
, Cond
);
6187 -- Emit warning if barrier contains global entities and is thus
6188 -- potentially unsynchronized (if Pure_Barriers restrictions
6189 -- are met then no need to check for this).
6190 Check_Unprotected_Barrier
(Cond
);
6193 -- Perform a small optimization of simple barrier functions. If the
6194 -- scope of the condition's entity is not the barrier function, then
6195 -- the condition does not depend on any of the generated renamings.
6196 -- If this is the case, eliminate the renamings as they are useless.
6197 -- This optimization is not performed when the condition was folded
6198 -- and validity checks are in effect because the original condition
6199 -- may have produced at least one check that depends on the generated
6203 and then Is_Entity_Name
(Cond
)
6204 and then Scope
(Entity
(Cond
)) /= Func_Id
6205 and then not Validity_Check_Operands
6207 Set_Declarations
(Func_Body
, Empty_List
);
6209 end Expand_Entry_Barrier
;
6211 ------------------------------
6212 -- Expand_N_Abort_Statement --
6213 ------------------------------
6215 -- Expand abort T1, T2, .. Tn; into:
6216 -- Abort_Tasks (Task_List'(1 => T1.Task_Id, 2 => T2.Task_Id ...))
6218 procedure Expand_N_Abort_Statement
(N
: Node_Id
) is
6219 Loc
: constant Source_Ptr
:= Sloc
(N
);
6220 Tlist
: constant List_Id
:= Names
(N
);
6226 Aggr
:= Make_Aggregate
(Loc
, Component_Associations
=> New_List
);
6229 Tasknm
:= First
(Tlist
);
6231 while Present
(Tasknm
) loop
6234 -- A task interface class-wide type object is being aborted. Retrieve
6235 -- its _task_id by calling a dispatching routine.
6237 if Ada_Version
>= Ada_2005
6238 and then Ekind
(Etype
(Tasknm
)) = E_Class_Wide_Type
6239 and then Is_Interface
(Etype
(Tasknm
))
6240 and then Is_Task_Interface
(Etype
(Tasknm
))
6242 Append_To
(Component_Associations
(Aggr
),
6243 Make_Component_Association
(Loc
,
6244 Choices
=> New_List
(Make_Integer_Literal
(Loc
, Count
)),
6247 -- Task_Id (Tasknm._disp_get_task_id)
6249 Unchecked_Convert_To
6250 (RTE
(RO_ST_Task_Id
),
6251 Make_Selected_Component
(Loc
,
6252 Prefix
=> New_Copy_Tree
(Tasknm
),
6254 Make_Identifier
(Loc
, Name_uDisp_Get_Task_Id
)))));
6257 Append_To
(Component_Associations
(Aggr
),
6258 Make_Component_Association
(Loc
,
6259 Choices
=> New_List
(Make_Integer_Literal
(Loc
, Count
)),
6260 Expression
=> Concurrent_Ref
(Tasknm
)));
6267 Make_Procedure_Call_Statement
(Loc
,
6268 Name
=> New_Occurrence_Of
(RTE
(RE_Abort_Tasks
), Loc
),
6269 Parameter_Associations
=> New_List
(
6270 Make_Qualified_Expression
(Loc
,
6271 Subtype_Mark
=> New_Occurrence_Of
(RTE
(RE_Task_List
), Loc
),
6272 Expression
=> Aggr
))));
6275 end Expand_N_Abort_Statement
;
6277 -------------------------------
6278 -- Expand_N_Accept_Statement --
6279 -------------------------------
6281 -- This procedure handles expansion of accept statements that stand alone,
6282 -- i.e. they are not part of an accept alternative. The expansion of
6283 -- accept statement in accept alternatives is handled by the routines
6284 -- Expand_N_Accept_Alternative and Expand_N_Selective_Accept. The
6285 -- following description applies only to stand alone accept statements.
6287 -- If there is no handled statement sequence, or only null statements, then
6288 -- this is called a trivial accept, and the expansion is:
6290 -- Accept_Trivial (entry-index)
6292 -- If there is a handled statement sequence, then the expansion is:
6299 -- Accept_Call (entry-index, Ann);
6300 -- Renaming_Declarations for formals
6301 -- <statement sequence from N_Accept_Statement node>
6302 -- Complete_Rendezvous;
6307 -- <exception handler from N_Accept_Statement node>
6308 -- Complete_Rendezvous;
6310 -- <exception handler from N_Accept_Statement node>
6311 -- Complete_Rendezvous;
6316 -- when all others =>
6317 -- Exceptional_Complete_Rendezvous (Get_GNAT_Exception);
6320 -- The first three declarations were already inserted ahead of the accept
6321 -- statement by the Expand_Accept_Declarations procedure, which was called
6322 -- directly from the semantics during analysis of the accept statement,
6323 -- before analyzing its contained statements.
6325 -- The declarations from the N_Accept_Statement, as noted in Sinfo, come
6326 -- from possible expansion activity (the original source of course does
6327 -- not have any declarations associated with the accept statement, since
6328 -- an accept statement has no declarative part). In particular, if the
6329 -- expander is active, the first such declaration is the declaration of
6330 -- the Accept_Params_Ptr entity (see Sem_Ch9.Analyze_Accept_Statement).
6332 -- The two blocks are merged into a single block if the inner block has
6333 -- no exception handlers, but otherwise two blocks are required, since
6334 -- exceptions might be raised in the exception handlers of the inner
6335 -- block, and Exceptional_Complete_Rendezvous must be called.
6337 procedure Expand_N_Accept_Statement
(N
: Node_Id
) is
6338 Loc
: constant Source_Ptr
:= Sloc
(N
);
6339 Stats
: constant Node_Id
:= Handled_Statement_Sequence
(N
);
6340 Ename
: constant Node_Id
:= Entry_Direct_Name
(N
);
6341 Eindx
: constant Node_Id
:= Entry_Index
(N
);
6342 Eent
: constant Entity_Id
:= Entity
(Ename
);
6343 Acstack
: constant Elist_Id
:= Accept_Address
(Eent
);
6344 Ann
: constant Entity_Id
:= Node
(Last_Elmt
(Acstack
));
6345 Ttyp
: constant Entity_Id
:= Etype
(Scope
(Eent
));
6351 -- If the accept statement is not part of a list, then its parent must
6352 -- be an accept alternative, and, as described above, we do not do any
6353 -- expansion for such accept statements at this level.
6355 if not Is_List_Member
(N
) then
6356 pragma Assert
(Nkind
(Parent
(N
)) = N_Accept_Alternative
);
6359 -- Trivial accept case (no statement sequence, or null statements).
6360 -- If the accept statement has declarations, then just insert them
6361 -- before the procedure call.
6363 elsif Trivial_Accept_OK
6364 and then (No
(Stats
) or else Null_Statements
(Statements
(Stats
)))
6366 -- Remove declarations for renamings, because the parameter block
6367 -- will not be assigned.
6374 D
:= First
(Declarations
(N
));
6375 while Present
(D
) loop
6377 if Nkind
(D
) = N_Object_Renaming_Declaration
then
6385 if Present
(Declarations
(N
)) then
6386 Insert_Actions
(N
, Declarations
(N
));
6390 Make_Procedure_Call_Statement
(Loc
,
6391 Name
=> New_Occurrence_Of
(RTE
(RE_Accept_Trivial
), Loc
),
6392 Parameter_Associations
=> New_List
(
6393 Entry_Index_Expression
(Loc
, Entity
(Ename
), Eindx
, Ttyp
))));
6397 -- Ada 2022 (AI12-0279)
6399 if Has_Yield_Aspect
(Eent
)
6400 and then RTE_Available
(RE_Yield
)
6402 Insert_Action_After
(N
,
6403 Make_Procedure_Call_Statement
(Loc
,
6404 New_Occurrence_Of
(RTE
(RE_Yield
), Loc
)));
6407 -- Discard Entry_Address that was created for it, so it will not be
6408 -- emitted if this accept statement is in the statement part of a
6409 -- delay alternative.
6411 if Present
(Stats
) then
6412 Remove_Last_Elmt
(Acstack
);
6415 -- Case of statement sequence present
6418 -- Construct the block, using the declarations from the accept
6419 -- statement if any to initialize the declarations of the block.
6421 Blkent
:= Make_Temporary
(Loc
, 'A');
6422 Mutate_Ekind
(Blkent
, E_Block
);
6423 Set_Etype
(Blkent
, Standard_Void_Type
);
6424 Set_Scope
(Blkent
, Current_Scope
);
6427 Make_Block_Statement
(Loc
,
6428 Identifier
=> New_Occurrence_Of
(Blkent
, Loc
),
6429 Declarations
=> Declarations
(N
),
6430 Handled_Statement_Sequence
=> Build_Accept_Body
(N
));
6432 -- Reset the Scope of local entities associated with the accept
6433 -- statement (that currently reference the entry scope) to the
6434 -- block scope, to avoid having references to the locals treated
6435 -- as up-level references.
6437 Reset_Scopes_To
(Block
, Blkent
);
6439 -- For the analysis of the generated declarations, the parent node
6440 -- must be properly set.
6442 Set_Parent
(Block
, Parent
(N
));
6443 Set_Parent
(Blkent
, Block
);
6445 -- Prepend call to Accept_Call to main statement sequence If the
6446 -- accept has exception handlers, the statement sequence is wrapped
6447 -- in a block. Insert call and renaming declarations in the
6448 -- declarations of the block, so they are elaborated before the
6452 Make_Procedure_Call_Statement
(Loc
,
6453 Name
=> New_Occurrence_Of
(RTE
(RE_Accept_Call
), Loc
),
6454 Parameter_Associations
=> New_List
(
6455 Entry_Index_Expression
(Loc
, Entity
(Ename
), Eindx
, Ttyp
),
6456 New_Occurrence_Of
(Ann
, Loc
)));
6458 if Parent
(Stats
) = N
then
6459 Prepend
(Call
, Statements
(Stats
));
6461 Set_Declarations
(Parent
(Stats
), New_List
(Call
));
6466 Push_Scope
(Blkent
);
6474 D
:= First
(Declarations
(N
));
6475 while Present
(D
) loop
6478 if Nkind
(D
) = N_Object_Renaming_Declaration
then
6480 -- The renaming declarations for the formals were created
6481 -- during analysis of the accept statement, and attached to
6482 -- the list of declarations. Place them now in the context
6483 -- of the accept block or subprogram.
6486 Typ
:= Entity
(Subtype_Mark
(D
));
6487 Insert_After
(Call
, D
);
6490 -- If the formal is class_wide, it does not have an actual
6491 -- subtype. The analysis of the renaming declaration creates
6492 -- one, but we need to retain the class-wide nature of the
6495 if Is_Class_Wide_Type
(Typ
) then
6496 Set_Etype
(Defining_Identifier
(D
), Typ
);
6507 -- Replace the accept statement by the new block
6512 -- Last step is to unstack the Accept_Address value
6514 Remove_Last_Elmt
(Acstack
);
6516 end Expand_N_Accept_Statement
;
6518 ----------------------------------
6519 -- Expand_N_Asynchronous_Select --
6520 ----------------------------------
6522 -- This procedure assumes that the trigger statement is an entry call or
6523 -- a dispatching procedure call. A delay alternative should already have
6524 -- been expanded into an entry call to the appropriate delay object Wait
6527 -- If the trigger is a task entry call, the select is implemented with
6528 -- a Task_Entry_Call:
6533 -- P : parms := (parm, parm, parm);
6535 -- -- Clean is added by Exp_Ch7.Expand_Cleanup_Actions
6537 -- procedure _clean is
6540 -- Cancel_Task_Entry_Call (C);
6547 -- (<acceptor-task>, -- Acceptor
6548 -- <entry-index>, -- E
6549 -- P'Address, -- Uninterpreted_Data
6550 -- Asynchronous_Call, -- Mode
6551 -- B); -- Rendezvous_Successful
6558 -- _clean; -- Added by Exp_Ch7.Expand_Cleanup_Actions
6561 -- when Abort_Signal => Abort_Undefer;
6568 -- <triggered-statements>
6572 -- Note that Build_Simple_Entry_Call is used to expand the entry of the
6573 -- asynchronous entry call (by Expand_N_Entry_Call_Statement procedure)
6577 -- P : parms := (parm, parm, parm);
6579 -- Call_Simple (acceptor-task, entry-index, P'Address);
6585 -- so the task at hand is to convert the latter expansion into the former
6587 -- If the trigger is a protected entry call, the select is implemented
6588 -- with Protected_Entry_Call:
6591 -- P : E1_Params := (param, param, param);
6592 -- Bnn : Communications_Block;
6597 -- -- Clean is added by Exp_Ch7.Expand_Cleanup_Actions
6599 -- procedure _clean is
6602 -- if Enqueued (Bnn) then
6603 -- Cancel_Protected_Entry_Call (Bnn);
6610 -- Protected_Entry_Call
6611 -- (po._object'Access, -- Object
6612 -- <entry index>, -- E
6613 -- P'Address, -- Uninterpreted_Data
6614 -- Asynchronous_Call, -- Mode
6617 -- if Enqueued (Bnn) then
6621 -- _clean; -- Added by Exp_Ch7.Expand_Cleanup_Actions
6624 -- when Abort_Signal => Abort_Undefer;
6627 -- if not Cancelled (Bnn) then
6628 -- <triggered-statements>
6632 -- Build_Simple_Entry_Call is used to expand the all to a simple protected
6636 -- P : E1_Params := (param, param, param);
6637 -- Bnn : Communications_Block;
6640 -- Protected_Entry_Call
6641 -- (po._object'Access, -- Object
6642 -- <entry index>, -- E
6643 -- P'Address, -- Uninterpreted_Data
6644 -- Simple_Call, -- Mode
6651 -- Ada 2005 (AI-345): If the trigger is a dispatching call, the select is
6655 -- B : Boolean := False;
6656 -- Bnn : Communication_Block;
6657 -- C : Ada.Tags.Prim_Op_Kind;
6658 -- D : System.Storage_Elements.Dummy_Communication_Block;
6659 -- K : Ada.Tags.Tagged_Kind :=
6660 -- Ada.Tags.Get_Tagged_Kind (Ada.Tags.Tag (<object>));
6661 -- P : Parameters := (Param1 .. ParamN);
6666 -- if K = Ada.Tags.TK_Limited_Tagged
6667 -- or else K = Ada.Tags.TK_Tagged
6669 -- <dispatching-call>;
6670 -- <triggering-statements>;
6674 -- Ada.Tags.Get_Offset_Index
6675 -- (Ada.Tags.Tag (<object>), DT_Position (<dispatching-call>));
6677 -- _Disp_Get_Prim_Op_Kind (<object>, S, C);
6679 -- if C = POK_Protected_Entry then
6681 -- procedure _clean is
6683 -- if Enqueued (Bnn) then
6684 -- Cancel_Protected_Entry_Call (Bnn);
6690 -- _Disp_Asynchronous_Select
6691 -- (<object>, S, P'Address, D, B);
6692 -- Bnn := Communication_Block (D);
6694 -- Param1 := P.Param1;
6696 -- ParamN := P.ParamN;
6698 -- if Enqueued (Bnn) then
6699 -- <abortable-statements>
6702 -- _clean; -- Added by Exp_Ch7.Expand_Cleanup_Actions
6705 -- when Abort_Signal => Abort_Undefer;
6708 -- if not Cancelled (Bnn) then
6709 -- <triggering-statements>
6712 -- elsif C = POK_Task_Entry then
6714 -- procedure _clean is
6716 -- Cancel_Task_Entry_Call (U);
6722 -- _Disp_Asynchronous_Select
6723 -- (<object>, S, P'Address, D, B);
6724 -- Bnn := Communication_Bloc (D);
6726 -- Param1 := P.Param1;
6728 -- ParamN := P.ParamN;
6733 -- <abortable-statements>
6735 -- _clean; -- Added by Exp_Ch7.Expand_Cleanup_Actions
6738 -- when Abort_Signal => Abort_Undefer;
6742 -- <triggering-statements>
6747 -- <dispatching-call>;
6748 -- <triggering-statements>
6753 -- The job is to convert this to the asynchronous form
6755 -- If the trigger is a delay statement, it will have been expanded into
6756 -- a call to one of the GNARL delay procedures. This routine will convert
6757 -- this into a protected entry call on a delay object and then continue
6758 -- processing as for a protected entry call trigger. This requires
6759 -- declaring a Delay_Block object and adding a pointer to this object to
6760 -- the parameter list of the delay procedure to form the parameter list of
6761 -- the entry call. This object is used by the runtime to queue the delay
6764 -- For a description of the use of P and the assignments after the call,
6765 -- see Expand_N_Entry_Call_Statement.
6767 procedure Expand_N_Asynchronous_Select
(N
: Node_Id
) is
6768 Loc
: constant Source_Ptr
:= Sloc
(N
);
6769 Abrt
: constant Node_Id
:= Abortable_Part
(N
);
6770 Trig
: constant Node_Id
:= Triggering_Alternative
(N
);
6772 Abort_Block_Ent
: Entity_Id
;
6773 Abortable_Block
: Node_Id
;
6776 Blk_Ent
: constant Entity_Id
:= Make_Temporary
(Loc
, 'A');
6777 Blk_Typ
: Entity_Id
;
6779 Call_Ent
: Entity_Id
;
6780 Cancel_Param
: Entity_Id
;
6781 Cleanup_Block
: Node_Id
;
6782 Cleanup_Block_Ent
: Entity_Id
;
6783 Cleanup_Stmts
: List_Id
;
6784 Conc_Typ_Stmts
: List_Id
;
6786 Dblock_Ent
: Entity_Id
;
6791 Enqueue_Call
: Node_Id
;
6795 Lim_Typ_Stmts
: List_Id
;
6801 ProtE_Stmts
: List_Id
;
6802 ProtP_Stmts
: List_Id
;
6805 TaskE_Stmts
: List_Id
;
6808 B
: Entity_Id
; -- Call status flag
6809 Bnn
: Entity_Id
; -- Communication block
6810 C
: Entity_Id
; -- Call kind
6811 K
: Entity_Id
; -- Tagged kind
6812 P
: Entity_Id
; -- Parameter block
6813 S
: Entity_Id
; -- Primitive operation slot
6814 T
: Entity_Id
; -- Additional status flag
6816 procedure Rewrite_Abortable_Part
;
6817 -- If the trigger is a dispatching call, the expansion inserts multiple
6818 -- copies of the abortable part. This is both inefficient, and may lead
6819 -- to duplicate definitions that the back-end will reject, when the
6820 -- abortable part includes loops. This procedure rewrites the abortable
6821 -- part into a call to a generated procedure.
6823 ----------------------------
6824 -- Rewrite_Abortable_Part --
6825 ----------------------------
6827 procedure Rewrite_Abortable_Part
is
6828 Proc
: constant Entity_Id
:= Make_Defining_Identifier
(Loc
, Name_uA
);
6833 Make_Subprogram_Body
(Loc
,
6835 Make_Procedure_Specification
(Loc
, Defining_Unit_Name
=> Proc
),
6836 Declarations
=> New_List
,
6837 Handled_Statement_Sequence
=>
6838 Make_Handled_Sequence_Of_Statements
(Loc
, Astats
));
6839 Insert_Before
(N
, Decl
);
6842 -- Rewrite abortable part into a call to this procedure
6846 Make_Procedure_Call_Statement
(Loc
,
6847 Name
=> New_Occurrence_Of
(Proc
, Loc
)));
6848 end Rewrite_Abortable_Part
;
6850 -- Start of processing for Expand_N_Asynchronous_Select
6853 -- Asynchronous select is not supported on restricted runtimes. Don't
6856 if Restricted_Profile
then
6860 Process_Statements_For_Controlled_Objects
(Trig
);
6861 Process_Statements_For_Controlled_Objects
(Abrt
);
6863 Ecall
:= Triggering_Statement
(Trig
);
6865 Ensure_Statement_Present
(Sloc
(Ecall
), Trig
);
6867 -- Retrieve Astats and Tstats now because the finalization machinery may
6868 -- wrap them in blocks.
6870 Astats
:= Statements
(Abrt
);
6871 Tstats
:= Statements
(Trig
);
6873 -- The arguments in the call may require dynamic allocation, and the
6874 -- call statement may have been transformed into a block. The block
6875 -- may contain additional declarations for internal entities, and the
6876 -- original call is found by sequential search.
6878 if Nkind
(Ecall
) = N_Block_Statement
then
6879 Ecall
:= First
(Statements
(Handled_Statement_Sequence
(Ecall
)));
6880 while Nkind
(Ecall
) not in
6881 N_Procedure_Call_Statement | N_Entry_Call_Statement
6887 -- This is either a dispatching call or a delay statement used as a
6888 -- trigger which was expanded into a procedure call.
6890 if Nkind
(Ecall
) = N_Procedure_Call_Statement
then
6891 if Ada_Version
>= Ada_2005
6893 (No
(Original_Node
(Ecall
))
6894 or else Nkind
(Original_Node
(Ecall
)) not in N_Delay_Statement
)
6896 Extract_Dispatching_Call
(Ecall
, Call_Ent
, Obj
, Actuals
, Formals
);
6898 Rewrite_Abortable_Part
;
6902 -- Call status flag processing, generate:
6903 -- B : Boolean := False;
6905 B
:= Build_B
(Loc
, Decls
);
6907 -- Communication block processing, generate:
6908 -- Bnn : Communication_Block;
6910 Bnn
:= Make_Temporary
(Loc
, 'B');
6912 Make_Object_Declaration
(Loc
,
6913 Defining_Identifier
=> Bnn
,
6914 Object_Definition
=>
6915 New_Occurrence_Of
(RTE
(RE_Communication_Block
), Loc
)));
6917 -- Call kind processing, generate:
6918 -- C : Ada.Tags.Prim_Op_Kind;
6920 C
:= Build_C
(Loc
, Decls
);
6922 -- Tagged kind processing, generate:
6923 -- K : Ada.Tags.Tagged_Kind :=
6924 -- Ada.Tags.Get_Tagged_Kind (Ada.Tags.Tag (<object>));
6926 -- Dummy communication block, generate:
6927 -- D : Dummy_Communication_Block;
6930 Make_Object_Declaration
(Loc
,
6931 Defining_Identifier
=>
6932 Make_Defining_Identifier
(Loc
, Name_uD
),
6933 Object_Definition
=>
6935 (RTE
(RE_Dummy_Communication_Block
), Loc
)));
6937 K
:= Build_K
(Loc
, Decls
, Obj
);
6939 -- Parameter block processing
6941 Blk_Typ
:= Build_Parameter_Block
6942 (Loc
, Actuals
, Formals
, Decls
);
6943 P
:= Parameter_Block_Pack
6944 (Loc
, Blk_Typ
, Actuals
, Formals
, Decls
, Stmts
);
6946 -- Dispatch table slot processing, generate:
6949 S
:= Build_S
(Loc
, Decls
);
6951 -- Additional status flag processing, generate:
6954 T
:= Make_Temporary
(Loc
, 'T');
6956 Make_Object_Declaration
(Loc
,
6957 Defining_Identifier
=> T
,
6958 Object_Definition
=>
6959 New_Occurrence_Of
(Standard_Boolean
, Loc
)));
6961 ------------------------------
6962 -- Protected entry handling --
6963 ------------------------------
6966 -- Param1 := P.Param1;
6968 -- ParamN := P.ParamN;
6970 Cleanup_Stmts
:= Parameter_Block_Unpack
(Loc
, P
, Actuals
, Formals
);
6973 -- Bnn := Communication_Block (D);
6975 Prepend_To
(Cleanup_Stmts
,
6976 Make_Assignment_Statement
(Loc
,
6977 Name
=> New_Occurrence_Of
(Bnn
, Loc
),
6979 Unchecked_Convert_To
6980 (RTE
(RE_Communication_Block
),
6981 Make_Identifier
(Loc
, Name_uD
))));
6984 -- _Disp_Asynchronous_Select (<object>, S, P'Address, D, B);
6986 Prepend_To
(Cleanup_Stmts
,
6987 Make_Procedure_Call_Statement
(Loc
,
6991 (Etype
(Etype
(Obj
)), Name_uDisp_Asynchronous_Select
),
6993 Parameter_Associations
=>
6995 New_Copy_Tree
(Obj
), -- <object>
6996 New_Occurrence_Of
(S
, Loc
), -- S
6997 Make_Attribute_Reference
(Loc
, -- P'Address
6998 Prefix
=> New_Occurrence_Of
(P
, Loc
),
6999 Attribute_Name
=> Name_Address
),
7000 Make_Identifier
(Loc
, Name_uD
), -- D
7001 New_Occurrence_Of
(B
, Loc
)))); -- B
7004 -- if Enqueued (Bnn) then
7005 -- <abortable-statements>
7008 Append_To
(Cleanup_Stmts
,
7009 Make_Implicit_If_Statement
(N
,
7011 Make_Function_Call
(Loc
,
7013 New_Occurrence_Of
(RTE
(RE_Enqueued
), Loc
),
7014 Parameter_Associations
=>
7015 New_List
(New_Occurrence_Of
(Bnn
, Loc
))),
7018 New_Copy_List_Tree
(Astats
)));
7020 -- Wrap the statements in a block. Exp_Ch7.Expand_Cleanup_Actions
7021 -- will then generate a _clean for the communication block Bnn.
7025 -- procedure _clean is
7027 -- if Enqueued (Bnn) then
7028 -- Cancel_Protected_Entry_Call (Bnn);
7037 Cleanup_Block_Ent
:= Make_Temporary
(Loc
, 'C');
7039 Build_Cleanup_Block
(Loc
, Cleanup_Block_Ent
, Cleanup_Stmts
, Bnn
);
7041 -- Wrap the cleanup block in an exception handling block
7047 -- when Abort_Signal => Abort_Undefer;
7050 Abort_Block_Ent
:= Make_Temporary
(Loc
, 'A');
7053 Make_Implicit_Label_Declaration
(Loc
,
7054 Defining_Identifier
=> Abort_Block_Ent
),
7057 (Loc
, Abort_Block_Ent
, Cleanup_Block_Ent
, Cleanup_Block
));
7060 -- if not Cancelled (Bnn) then
7061 -- <triggering-statements>
7064 Append_To
(ProtE_Stmts
,
7065 Make_Implicit_If_Statement
(N
,
7069 Make_Function_Call
(Loc
,
7071 New_Occurrence_Of
(RTE
(RE_Cancelled
), Loc
),
7072 Parameter_Associations
=>
7073 New_List
(New_Occurrence_Of
(Bnn
, Loc
)))),
7076 New_Copy_List_Tree
(Tstats
)));
7078 -------------------------
7079 -- Task entry handling --
7080 -------------------------
7083 -- Param1 := P.Param1;
7085 -- ParamN := P.ParamN;
7087 TaskE_Stmts
:= Parameter_Block_Unpack
(Loc
, P
, Actuals
, Formals
);
7090 -- Bnn := Communication_Block (D);
7092 Append_To
(TaskE_Stmts
,
7093 Make_Assignment_Statement
(Loc
,
7095 New_Occurrence_Of
(Bnn
, Loc
),
7097 Unchecked_Convert_To
7098 (RTE
(RE_Communication_Block
),
7099 Make_Identifier
(Loc
, Name_uD
))));
7102 -- _Disp_Asynchronous_Select (<object>, S, P'Address, D, B);
7104 Prepend_To
(TaskE_Stmts
,
7105 Make_Procedure_Call_Statement
(Loc
,
7108 Find_Prim_Op
(Etype
(Etype
(Obj
)),
7109 Name_uDisp_Asynchronous_Select
),
7112 Parameter_Associations
=> New_List
(
7113 New_Copy_Tree
(Obj
), -- <object>
7114 New_Occurrence_Of
(S
, Loc
), -- S
7115 Make_Attribute_Reference
(Loc
, -- P'Address
7116 Prefix
=> New_Occurrence_Of
(P
, Loc
),
7117 Attribute_Name
=> Name_Address
),
7118 Make_Identifier
(Loc
, Name_uD
), -- D
7119 New_Occurrence_Of
(B
, Loc
)))); -- B
7124 Prepend_To
(TaskE_Stmts
, Build_Runtime_Call
(Loc
, RE_Abort_Defer
));
7128 -- <abortable-statements>
7130 Cleanup_Stmts
:= New_Copy_List_Tree
(Astats
);
7133 (Cleanup_Stmts
, Build_Runtime_Call
(Loc
, RE_Abort_Undefer
));
7135 -- Wrap the statements in a block. Exp_Ch7.Expand_Cleanup_Actions
7136 -- will generate a _clean for the additional status flag.
7140 -- procedure _clean is
7142 -- Cancel_Task_Entry_Call (U);
7150 Cleanup_Block_Ent
:= Make_Temporary
(Loc
, 'C');
7152 Build_Cleanup_Block
(Loc
, Cleanup_Block_Ent
, Cleanup_Stmts
, T
);
7154 -- Wrap the cleanup block in an exception handling block
7160 -- when Abort_Signal => Abort_Undefer;
7163 Abort_Block_Ent
:= Make_Temporary
(Loc
, 'A');
7165 Append_To
(TaskE_Stmts
,
7166 Make_Implicit_Label_Declaration
(Loc
,
7167 Defining_Identifier
=> Abort_Block_Ent
));
7169 Append_To
(TaskE_Stmts
,
7171 (Loc
, Abort_Block_Ent
, Cleanup_Block_Ent
, Cleanup_Block
));
7175 -- <triggering-statements>
7178 Append_To
(TaskE_Stmts
,
7179 Make_Implicit_If_Statement
(N
,
7181 Make_Op_Not
(Loc
, Right_Opnd
=> New_Occurrence_Of
(T
, Loc
)),
7184 New_Copy_List_Tree
(Tstats
)));
7186 ----------------------------------
7187 -- Protected procedure handling --
7188 ----------------------------------
7191 -- <dispatching-call>;
7192 -- <triggering-statements>
7194 ProtP_Stmts
:= New_Copy_List_Tree
(Tstats
);
7195 Prepend_To
(ProtP_Stmts
, New_Copy_Tree
(Ecall
));
7198 -- S := Ada.Tags.Get_Offset_Index
7199 -- (Ada.Tags.Tag (<object>), DT_Position (Call_Ent));
7202 New_List
(Build_S_Assignment
(Loc
, S
, Obj
, Call_Ent
));
7205 -- _Disp_Get_Prim_Op_Kind (<object>, S, C);
7207 Append_To
(Conc_Typ_Stmts
,
7208 Make_Procedure_Call_Statement
(Loc
,
7211 (Find_Prim_Op
(Etype
(Etype
(Obj
)),
7212 Name_uDisp_Get_Prim_Op_Kind
),
7214 Parameter_Associations
=>
7216 New_Copy_Tree
(Obj
),
7217 New_Occurrence_Of
(S
, Loc
),
7218 New_Occurrence_Of
(C
, Loc
))));
7221 -- if C = POK_Procedure_Entry then
7223 -- elsif C = POK_Task_Entry then
7229 Append_To
(Conc_Typ_Stmts
,
7230 Make_Implicit_If_Statement
(N
,
7234 New_Occurrence_Of
(C
, Loc
),
7236 New_Occurrence_Of
(RTE
(RE_POK_Protected_Entry
), Loc
)),
7243 Make_Elsif_Part
(Loc
,
7247 New_Occurrence_Of
(C
, Loc
),
7249 New_Occurrence_Of
(RTE
(RE_POK_Task_Entry
), Loc
)),
7258 -- <dispatching-call>;
7259 -- <triggering-statements>
7261 Lim_Typ_Stmts
:= New_Copy_List_Tree
(Tstats
);
7262 Prepend_To
(Lim_Typ_Stmts
, New_Copy_Tree
(Ecall
));
7265 -- if K = Ada.Tags.TK_Limited_Tagged
7266 -- or else K = Ada.Tags.TK_Tagged
7274 Make_Implicit_If_Statement
(N
,
7275 Condition
=> Build_Dispatching_Tag_Check
(K
, N
),
7276 Then_Statements
=> Lim_Typ_Stmts
,
7277 Else_Statements
=> Conc_Typ_Stmts
));
7280 Make_Block_Statement
(Loc
,
7283 Handled_Statement_Sequence
=>
7284 Make_Handled_Sequence_Of_Statements
(Loc
, Stmts
)));
7289 -- Delay triggering statement processing
7292 -- Add a Delay_Block object to the parameter list of the delay
7293 -- procedure to form the parameter list of the Wait entry call.
7295 Dblock_Ent
:= Make_Temporary
(Loc
, 'D');
7297 Pdef
:= Entity
(Name
(Ecall
));
7299 if Is_RTE
(Pdef
, RO_CA_Delay_For
) then
7301 New_Occurrence_Of
(RTE
(RE_Enqueue_Duration
), Loc
);
7303 elsif Is_RTE
(Pdef
, RO_CA_Delay_Until
) then
7305 New_Occurrence_Of
(RTE
(RE_Enqueue_Calendar
), Loc
);
7307 else pragma Assert
(Is_RTE
(Pdef
, RO_RT_Delay_Until
));
7308 Enqueue_Call
:= New_Occurrence_Of
(RTE
(RE_Enqueue_RT
), Loc
);
7311 Append_To
(Parameter_Associations
(Ecall
),
7312 Make_Attribute_Reference
(Loc
,
7313 Prefix
=> New_Occurrence_Of
(Dblock_Ent
, Loc
),
7314 Attribute_Name
=> Name_Unchecked_Access
));
7316 -- Create the inner block to protect the abortable part
7318 Hdle
:= New_List
(Build_Abort_Block_Handler
(Loc
));
7320 Prepend_To
(Astats
, Build_Runtime_Call
(Loc
, RE_Abort_Undefer
));
7323 Make_Block_Statement
(Loc
,
7324 Identifier
=> New_Occurrence_Of
(Blk_Ent
, Loc
),
7325 Handled_Statement_Sequence
=>
7326 Make_Handled_Sequence_Of_Statements
(Loc
,
7327 Statements
=> Astats
),
7328 Has_Created_Identifier
=> True,
7329 Is_Asynchronous_Call_Block
=> True);
7331 -- Append call to if Enqueue (When, DB'Unchecked_Access) then
7334 Make_Implicit_If_Statement
(N
,
7336 Make_Function_Call
(Loc
,
7337 Name
=> Enqueue_Call
,
7338 Parameter_Associations
=> Parameter_Associations
(Ecall
)),
7340 New_List
(Make_Block_Statement
(Loc
,
7341 Handled_Statement_Sequence
=>
7342 Make_Handled_Sequence_Of_Statements
(Loc
,
7343 Statements
=> New_List
(
7344 Make_Implicit_Label_Declaration
(Loc
,
7345 Defining_Identifier
=> Blk_Ent
,
7346 Label_Construct
=> Abortable_Block
),
7348 Exception_Handlers
=> Hdle
)))));
7350 Stmts
:= New_List
(Ecall
);
7352 -- Construct statement sequence for new block
7355 Make_Implicit_If_Statement
(N
,
7357 Make_Function_Call
(Loc
,
7358 Name
=> New_Occurrence_Of
(
7359 RTE
(RE_Timed_Out
), Loc
),
7360 Parameter_Associations
=> New_List
(
7361 Make_Attribute_Reference
(Loc
,
7362 Prefix
=> New_Occurrence_Of
(Dblock_Ent
, Loc
),
7363 Attribute_Name
=> Name_Unchecked_Access
))),
7364 Then_Statements
=> Tstats
));
7366 -- The result is the new block
7368 Set_Entry_Cancel_Parameter
(Blk_Ent
, Dblock_Ent
);
7371 Make_Block_Statement
(Loc
,
7372 Declarations
=> New_List
(
7373 Make_Object_Declaration
(Loc
,
7374 Defining_Identifier
=> Dblock_Ent
,
7375 Aliased_Present
=> True,
7376 Object_Definition
=>
7377 New_Occurrence_Of
(RTE
(RE_Delay_Block
), Loc
))),
7379 Handled_Statement_Sequence
=>
7380 Make_Handled_Sequence_Of_Statements
(Loc
, Stmts
)));
7390 Extract_Entry
(Ecall
, Concval
, Ename
, Index
);
7391 Build_Simple_Entry_Call
(Ecall
, Concval
, Ename
, Index
);
7393 Stmts
:= Statements
(Handled_Statement_Sequence
(Ecall
));
7394 Decls
:= Declarations
(Ecall
);
7396 if Is_Protected_Type
(Etype
(Concval
)) then
7398 -- Get the declarations of the block expanded from the entry call
7400 Decl
:= First
(Decls
);
7401 while Present
(Decl
)
7402 and then (Nkind
(Decl
) /= N_Object_Declaration
7403 or else not Is_RTE
(Etype
(Object_Definition
(Decl
)),
7404 RE_Communication_Block
))
7409 pragma Assert
(Present
(Decl
));
7410 Cancel_Param
:= Defining_Identifier
(Decl
);
7412 -- Change the mode of the Protected_Entry_Call call
7414 -- Protected_Entry_Call (
7415 -- Object => po._object'Access,
7416 -- E => <entry index>;
7417 -- Uninterpreted_Data => P'Address;
7418 -- Mode => Asynchronous_Call;
7421 -- Skip assignments to temporaries created for in-out parameters
7423 -- This makes unwarranted assumptions about the shape of the expanded
7424 -- tree for the call, and should be cleaned up ???
7426 Stmt
:= First
(Stmts
);
7427 while Nkind
(Stmt
) /= N_Procedure_Call_Statement
loop
7433 Param
:= First
(Parameter_Associations
(Call
));
7434 while Present
(Param
)
7435 and then not Is_RTE
(Etype
(Param
), RE_Call_Modes
)
7440 pragma Assert
(Present
(Param
));
7441 Rewrite
(Param
, New_Occurrence_Of
(RTE
(RE_Asynchronous_Call
), Loc
));
7444 -- Append an if statement to execute the abortable part
7447 -- if Enqueued (Bnn) then
7450 Make_Implicit_If_Statement
(N
,
7452 Make_Function_Call
(Loc
,
7453 Name
=> New_Occurrence_Of
(RTE
(RE_Enqueued
), Loc
),
7454 Parameter_Associations
=> New_List
(
7455 New_Occurrence_Of
(Cancel_Param
, Loc
))),
7456 Then_Statements
=> Astats
));
7459 Make_Block_Statement
(Loc
,
7460 Identifier
=> New_Occurrence_Of
(Blk_Ent
, Loc
),
7461 Handled_Statement_Sequence
=>
7462 Make_Handled_Sequence_Of_Statements
(Loc
, Statements
=> Stmts
),
7463 Has_Created_Identifier
=> True,
7464 Is_Asynchronous_Call_Block
=> True);
7467 Make_Block_Statement
(Loc
,
7468 Handled_Statement_Sequence
=>
7469 Make_Handled_Sequence_Of_Statements
(Loc
,
7470 Statements
=> New_List
(
7471 Make_Implicit_Label_Declaration
(Loc
,
7472 Defining_Identifier
=> Blk_Ent
,
7473 Label_Construct
=> Abortable_Block
),
7478 Exception_Handlers
=> New_List
(
7479 Make_Implicit_Exception_Handler
(Loc
,
7481 -- when Abort_Signal =>
7484 Exception_Choices
=>
7485 New_List
(New_Occurrence_Of
(Stand
.Abort_Signal
, Loc
)),
7486 Statements
=> New_List
(Make_Null_Statement
(Loc
)))))),
7488 -- if not Cancelled (Bnn) then
7489 -- triggered statements
7492 Make_Implicit_If_Statement
(N
,
7493 Condition
=> Make_Op_Not
(Loc
,
7495 Make_Function_Call
(Loc
,
7496 Name
=> New_Occurrence_Of
(RTE
(RE_Cancelled
), Loc
),
7497 Parameter_Associations
=> New_List
(
7498 New_Occurrence_Of
(Cancel_Param
, Loc
)))),
7499 Then_Statements
=> Tstats
));
7501 -- Asynchronous task entry call
7508 B
:= Make_Defining_Identifier
(Loc
, Name_uB
);
7510 -- Insert declaration of B in declarations of existing block
7513 Make_Object_Declaration
(Loc
,
7514 Defining_Identifier
=> B
,
7515 Object_Definition
=>
7516 New_Occurrence_Of
(Standard_Boolean
, Loc
)));
7518 Cancel_Param
:= Make_Defining_Identifier
(Loc
, Name_uC
);
7520 -- Insert the declaration of C in the declarations of the existing
7521 -- block. The variable is initialized to something (True or False,
7522 -- does not matter) to prevent CodePeer from complaining about a
7523 -- possible read of an uninitialized variable.
7526 Make_Object_Declaration
(Loc
,
7527 Defining_Identifier
=> Cancel_Param
,
7528 Object_Definition
=> New_Occurrence_Of
(Standard_Boolean
, Loc
),
7529 Expression
=> New_Occurrence_Of
(Standard_False
, Loc
),
7530 Has_Init_Expression
=> True));
7532 -- Remove and save the call to Call_Simple
7534 Stmt
:= First
(Stmts
);
7536 -- Skip assignments to temporaries created for in-out parameters.
7537 -- This makes unwarranted assumptions about the shape of the expanded
7538 -- tree for the call, and should be cleaned up ???
7540 while Nkind
(Stmt
) /= N_Procedure_Call_Statement
loop
7546 -- Create the inner block to protect the abortable part
7548 Hdle
:= New_List
(Build_Abort_Block_Handler
(Loc
));
7550 if Abort_Allowed
then
7551 Prepend_To
(Astats
, Build_Runtime_Call
(Loc
, RE_Abort_Undefer
));
7555 Make_Block_Statement
(Loc
,
7556 Identifier
=> New_Occurrence_Of
(Blk_Ent
, Loc
),
7557 Handled_Statement_Sequence
=>
7558 Make_Handled_Sequence_Of_Statements
(Loc
, Statements
=> Astats
),
7559 Has_Created_Identifier
=> True,
7560 Is_Asynchronous_Call_Block
=> True);
7563 Make_Block_Statement
(Loc
,
7564 Handled_Statement_Sequence
=>
7565 Make_Handled_Sequence_Of_Statements
(Loc
,
7566 Statements
=> New_List
(
7567 Make_Implicit_Label_Declaration
(Loc
,
7568 Defining_Identifier
=> Blk_Ent
,
7569 Label_Construct
=> Abortable_Block
),
7571 Exception_Handlers
=> Hdle
)));
7573 -- Create new call statement
7575 Params
:= Parameter_Associations
(Call
);
7578 New_Occurrence_Of
(RTE
(RE_Asynchronous_Call
), Loc
));
7579 Append_To
(Params
, New_Occurrence_Of
(B
, Loc
));
7582 Make_Procedure_Call_Statement
(Loc
,
7583 Name
=> New_Occurrence_Of
(RTE
(RE_Task_Entry_Call
), Loc
),
7584 Parameter_Associations
=> Params
));
7586 -- Construct statement sequence for new block
7589 Make_Implicit_If_Statement
(N
,
7591 Make_Op_Not
(Loc
, New_Occurrence_Of
(Cancel_Param
, Loc
)),
7592 Then_Statements
=> Tstats
));
7594 -- Protected the call against abort
7596 Prepend_To
(Stmts
, Build_Runtime_Call
(Loc
, RE_Abort_Defer
));
7599 Set_Entry_Cancel_Parameter
(Blk_Ent
, Cancel_Param
);
7601 -- The result is the new block
7604 Make_Block_Statement
(Loc
,
7605 Declarations
=> Decls
,
7606 Handled_Statement_Sequence
=>
7607 Make_Handled_Sequence_Of_Statements
(Loc
, Stmts
)));
7610 end Expand_N_Asynchronous_Select
;
7612 -------------------------------------
7613 -- Expand_N_Conditional_Entry_Call --
7614 -------------------------------------
7616 -- The conditional task entry call is converted to a call to
7621 -- P : parms := (parm, parm, parm);
7625 -- (<acceptor-task>, -- Acceptor
7626 -- <entry-index>, -- E
7627 -- P'Address, -- Uninterpreted_Data
7628 -- Conditional_Call, -- Mode
7629 -- B); -- Rendezvous_Successful
7634 -- normal-statements
7640 -- For a description of the use of P and the assignments after the call,
7641 -- see Expand_N_Entry_Call_Statement. Note that the entry call of the
7642 -- conditional entry call has already been expanded (by the Expand_N_Entry
7643 -- _Call_Statement procedure) as follows:
7646 -- P : parms := (parm, parm, parm);
7648 -- ... info for in-out parameters
7649 -- Call_Simple (acceptor-task, entry-index, P'Address);
7655 -- so the task at hand is to convert the latter expansion into the former
7657 -- The conditional protected entry call is converted to a call to
7658 -- Protected_Entry_Call:
7661 -- P : parms := (parm, parm, parm);
7662 -- Bnn : Communications_Block;
7665 -- Protected_Entry_Call
7666 -- (po._object'Access, -- Object
7667 -- <entry index>, -- E
7668 -- P'Address, -- Uninterpreted_Data
7669 -- Conditional_Call, -- Mode
7674 -- if Cancelled (Bnn) then
7677 -- normal-statements
7681 -- Ada 2005 (AI-345): A dispatching conditional entry call is converted
7685 -- B : Boolean := False;
7686 -- C : Ada.Tags.Prim_Op_Kind;
7687 -- K : Ada.Tags.Tagged_Kind :=
7688 -- Ada.Tags.Get_Tagged_Kind (Ada.Tags.Tag (<object>));
7689 -- P : Parameters := (Param1 .. ParamN);
7693 -- if K = Ada.Tags.TK_Limited_Tagged
7694 -- or else K = Ada.Tags.TK_Tagged
7696 -- <dispatching-call>;
7697 -- -- <triggering-statements> (code factorized after if-stmt)
7701 -- Ada.Tags.Get_Offset_Index
7702 -- (Ada.Tags.Tag (<object>), DT_Position (<dispatching-call>));
7704 -- _Disp_Conditional_Select (<object>, S, P'Address, C, B);
7706 -- if C = POK_Protected_Entry
7707 -- or else C = POK_Task_Entry
7709 -- Param1 := P.Param1;
7711 -- ParamN := P.ParamN;
7715 -- if C = POK_Procedure
7716 -- or else C = POK_Protected_Procedure
7717 -- or else C = POK_Task_Procedure
7719 -- <dispatching-call>;
7722 -- -- <triggering-statements> (code factorized after if-stmt)
7724 -- <else-statements>
7725 -- goto L0; -- skip triggering statements
7728 -- <triggering-statements>
7732 procedure Expand_N_Conditional_Entry_Call
(N
: Node_Id
) is
7733 Loc
: constant Source_Ptr
:= Sloc
(N
);
7734 Alt
: constant Node_Id
:= Entry_Call_Alternative
(N
);
7735 Blk
: Node_Id
:= Entry_Call_Statement
(Alt
);
7738 Blk_Typ
: Entity_Id
;
7740 Call_Ent
: Entity_Id
;
7741 Conc_Typ_Stmts
: List_Id
;
7746 Label_Id
: Entity_Id
:= Empty
;
7747 Lim_Typ_Stmts
: List_Id
;
7754 Transient_Blk
: Node_Id
;
7757 B
: Entity_Id
; -- Call status flag
7758 C
: Entity_Id
; -- Call kind
7759 K
: Entity_Id
; -- Tagged kind
7760 P
: Entity_Id
; -- Parameter block
7761 S
: Entity_Id
; -- Primitive operation slot
7764 Process_Statements_For_Controlled_Objects
(N
);
7766 if Ada_Version
>= Ada_2005
7767 and then Nkind
(Blk
) = N_Procedure_Call_Statement
7769 Extract_Dispatching_Call
(Blk
, Call_Ent
, Obj
, Actuals
, Formals
);
7774 -- Call status flag processing, generate:
7775 -- B : Boolean := False;
7777 B
:= Build_B
(Loc
, Decls
);
7779 -- Call kind processing, generate:
7780 -- C : Ada.Tags.Prim_Op_Kind;
7782 C
:= Build_C
(Loc
, Decls
);
7784 -- Tagged kind processing, generate:
7785 -- K : Ada.Tags.Tagged_Kind :=
7786 -- Ada.Tags.Get_Tagged_Kind (Ada.Tags.Tag (<object>));
7788 K
:= Build_K
(Loc
, Decls
, Obj
);
7790 -- Parameter block processing
7792 Blk_Typ
:= Build_Parameter_Block
(Loc
, Actuals
, Formals
, Decls
);
7793 P
:= Parameter_Block_Pack
7794 (Loc
, Blk_Typ
, Actuals
, Formals
, Decls
, Stmts
);
7796 -- Dispatch table slot processing, generate:
7799 S
:= Build_S
(Loc
, Decls
);
7802 -- S := Ada.Tags.Get_Offset_Index
7803 -- (Ada.Tags.Tag (<object>), DT_Position (Call_Ent));
7806 New_List
(Build_S_Assignment
(Loc
, S
, Obj
, Call_Ent
));
7809 -- _Disp_Conditional_Select (<object>, S, P'Address, C, B);
7811 Append_To
(Conc_Typ_Stmts
,
7812 Make_Procedure_Call_Statement
(Loc
,
7815 Find_Prim_Op
(Etype
(Etype
(Obj
)),
7816 Name_uDisp_Conditional_Select
),
7818 Parameter_Associations
=>
7820 New_Copy_Tree
(Obj
), -- <object>
7821 New_Occurrence_Of
(S
, Loc
), -- S
7822 Make_Attribute_Reference
(Loc
, -- P'Address
7823 Prefix
=> New_Occurrence_Of
(P
, Loc
),
7824 Attribute_Name
=> Name_Address
),
7825 New_Occurrence_Of
(C
, Loc
), -- C
7826 New_Occurrence_Of
(B
, Loc
)))); -- B
7829 -- if C = POK_Protected_Entry
7830 -- or else C = POK_Task_Entry
7832 -- Param1 := P.Param1;
7834 -- ParamN := P.ParamN;
7837 Unpack
:= Parameter_Block_Unpack
(Loc
, P
, Actuals
, Formals
);
7839 -- Generate the if statement only when the packed parameters need
7840 -- explicit assignments to their corresponding actuals.
7842 if Present
(Unpack
) then
7843 Append_To
(Conc_Typ_Stmts
,
7844 Make_Implicit_If_Statement
(N
,
7850 New_Occurrence_Of
(C
, Loc
),
7852 New_Occurrence_Of
(RTE
(
7853 RE_POK_Protected_Entry
), Loc
)),
7858 New_Occurrence_Of
(C
, Loc
),
7860 New_Occurrence_Of
(RTE
(RE_POK_Task_Entry
), Loc
))),
7862 Then_Statements
=> Unpack
));
7867 -- if C = POK_Procedure
7868 -- or else C = POK_Protected_Procedure
7869 -- or else C = POK_Task_Procedure
7871 -- <dispatching-call>
7873 -- -- <triggering-stataments> (code factorized after if-stmt)
7875 -- <else-statements>
7876 -- goto L0; -- skip triggering statements
7879 N_Stats
:= New_List
;
7881 Prepend_To
(N_Stats
,
7882 Make_Implicit_If_Statement
(N
,
7888 New_Occurrence_Of
(C
, Loc
),
7890 New_Occurrence_Of
(RTE
(RE_POK_Procedure
), Loc
)),
7897 New_Occurrence_Of
(C
, Loc
),
7899 New_Occurrence_Of
(RTE
(
7900 RE_POK_Protected_Procedure
), Loc
)),
7905 New_Occurrence_Of
(C
, Loc
),
7907 New_Occurrence_Of
(RTE
(
7908 RE_POK_Task_Procedure
), Loc
)))),
7913 Label_Id
:= Make_Identifier
(Loc
, New_External_Name
('L', 0));
7914 Set_Entity
(Label_Id
,
7915 Make_Defining_Identifier
(Loc
, Chars
(Label_Id
)));
7917 Append_To
(Else_Statements
(N
),
7918 Make_Goto_Statement
(Loc
,
7919 Name
=> New_Occurrence_Of
(Entity
(Label_Id
), Loc
)));
7921 Append_To
(Conc_Typ_Stmts
,
7922 Make_Implicit_If_Statement
(N
,
7923 Condition
=> New_Occurrence_Of
(B
, Loc
),
7924 Then_Statements
=> N_Stats
,
7925 Else_Statements
=> Else_Statements
(N
)));
7928 -- <dispatching-call>;
7929 -- -- <triggering-statements> (code factorized after if-stmt)
7931 Lim_Typ_Stmts
:= New_List
(New_Copy_Tree
(Blk
));
7934 -- if K = Ada.Tags.TK_Limited_Tagged
7935 -- or else K = Ada.Tags.TK_Tagged
7943 Make_Implicit_If_Statement
(N
,
7944 Condition
=> Build_Dispatching_Tag_Check
(K
, N
),
7945 Then_Statements
=> Lim_Typ_Stmts
,
7946 Else_Statements
=> Conc_Typ_Stmts
));
7948 Label
:= Make_Label
(Loc
, Label_Id
);
7950 Make_Implicit_Label_Declaration
(Loc
,
7951 Defining_Identifier
=> Entity
(Label_Id
),
7952 Label_Construct
=> Label
));
7954 Append_List_To
(Stmts
, Statements
(Alt
)); -- triggering-statements
7955 Append_To
(Stmts
, Label
);
7958 Make_Block_Statement
(Loc
,
7961 Handled_Statement_Sequence
=>
7962 Make_Handled_Sequence_Of_Statements
(Loc
, Stmts
)));
7964 -- As described above, the entry alternative is transformed into a
7965 -- block that contains the gnulli call, and possibly assignment
7966 -- statements for in-out parameters. The gnulli call may itself be
7967 -- rewritten into a transient block if some unconstrained parameters
7968 -- require it. We need to retrieve the call to complete its parameter
7973 First
(Statements
(Handled_Statement_Sequence
(Blk
)));
7975 if Present
(Transient_Blk
)
7976 and then Nkind
(Transient_Blk
) = N_Block_Statement
7978 Blk
:= Transient_Blk
;
7981 Stmts
:= Statements
(Handled_Statement_Sequence
(Blk
));
7982 Stmt
:= First
(Stmts
);
7983 while Nkind
(Stmt
) /= N_Procedure_Call_Statement
loop
7988 Params
:= Parameter_Associations
(Call
);
7990 if Is_RTE
(Entity
(Name
(Call
)), RE_Protected_Entry_Call
) then
7992 -- Substitute Conditional_Entry_Call for Simple_Call parameter
7994 Param
:= First
(Params
);
7995 while Present
(Param
)
7996 and then not Is_RTE
(Etype
(Param
), RE_Call_Modes
)
8001 pragma Assert
(Present
(Param
));
8003 New_Occurrence_Of
(RTE
(RE_Conditional_Call
), Loc
));
8007 -- Find the Communication_Block parameter for the call to the
8008 -- Cancelled function.
8010 Decl
:= First
(Declarations
(Blk
));
8011 while Present
(Decl
)
8012 and then not Is_RTE
(Etype
(Object_Definition
(Decl
)),
8013 RE_Communication_Block
)
8018 -- Add an if statement to execute the else part if the call
8019 -- does not succeed (as indicated by the Cancelled predicate).
8022 Make_Implicit_If_Statement
(N
,
8023 Condition
=> Make_Function_Call
(Loc
,
8024 Name
=> New_Occurrence_Of
(RTE
(RE_Cancelled
), Loc
),
8025 Parameter_Associations
=> New_List
(
8026 New_Occurrence_Of
(Defining_Identifier
(Decl
), Loc
))),
8027 Then_Statements
=> Else_Statements
(N
),
8028 Else_Statements
=> Statements
(Alt
)));
8031 B
:= Make_Defining_Identifier
(Loc
, Name_uB
);
8033 -- Insert declaration of B in declarations of existing block
8035 if No
(Declarations
(Blk
)) then
8036 Set_Declarations
(Blk
, New_List
);
8039 Prepend_To
(Declarations
(Blk
),
8040 Make_Object_Declaration
(Loc
,
8041 Defining_Identifier
=> B
,
8042 Object_Definition
=>
8043 New_Occurrence_Of
(Standard_Boolean
, Loc
)));
8045 -- Create new call statement
8048 New_Occurrence_Of
(RTE
(RE_Conditional_Call
), Loc
));
8049 Append_To
(Params
, New_Occurrence_Of
(B
, Loc
));
8052 Make_Procedure_Call_Statement
(Loc
,
8053 Name
=> New_Occurrence_Of
(RTE
(RE_Task_Entry_Call
), Loc
),
8054 Parameter_Associations
=> Params
));
8056 -- Construct statement sequence for new block
8059 Make_Implicit_If_Statement
(N
,
8060 Condition
=> New_Occurrence_Of
(B
, Loc
),
8061 Then_Statements
=> Statements
(Alt
),
8062 Else_Statements
=> Else_Statements
(N
)));
8065 -- The result is the new block
8068 Make_Block_Statement
(Loc
,
8069 Declarations
=> Declarations
(Blk
),
8070 Handled_Statement_Sequence
=>
8071 Make_Handled_Sequence_Of_Statements
(Loc
, Stmts
)));
8076 Reset_Scopes_To
(N
, Entity
(Identifier
(N
)));
8077 end Expand_N_Conditional_Entry_Call
;
8079 ---------------------------------------
8080 -- Expand_N_Delay_Relative_Statement --
8081 ---------------------------------------
8083 -- Delay statement is implemented as a procedure call to Delay_For
8084 -- defined in Ada.Calendar.Delays in order to reduce the overhead of
8085 -- simple delays imposed by the use of Protected Objects.
8087 procedure Expand_N_Delay_Relative_Statement
(N
: Node_Id
) is
8088 Loc
: constant Source_Ptr
:= Sloc
(N
);
8092 -- Try to use Ada.Calendar.Delays.Delay_For if available.
8094 if RTE_Available
(RO_CA_Delay_For
) then
8095 Proc
:= RTE
(RO_CA_Delay_For
);
8097 -- Otherwise, use System.Relative_Delays.Delay_For and emit an error
8098 -- message if not available. This is the implementation used on
8099 -- restricted platforms when Ada.Calendar is not available.
8102 Proc
:= RTE
(RO_RD_Delay_For
);
8106 Make_Procedure_Call_Statement
(Loc
,
8107 Name
=> New_Occurrence_Of
(Proc
, Loc
),
8108 Parameter_Associations
=> New_List
(Expression
(N
))));
8110 end Expand_N_Delay_Relative_Statement
;
8112 ------------------------------------
8113 -- Expand_N_Delay_Until_Statement --
8114 ------------------------------------
8116 -- Delay Until statement is implemented as a procedure call to
8117 -- Delay_Until defined in Ada.Calendar.Delays and Ada.Real_Time.Delays.
8119 procedure Expand_N_Delay_Until_Statement
(N
: Node_Id
) is
8120 Loc
: constant Source_Ptr
:= Sloc
(N
);
8124 if Is_RTE
(Base_Type
(Etype
(Expression
(N
))), RO_CA_Time
) then
8125 Typ
:= RTE
(RO_CA_Delay_Until
);
8127 Typ
:= RTE
(RO_RT_Delay_Until
);
8131 Make_Procedure_Call_Statement
(Loc
,
8132 Name
=> New_Occurrence_Of
(Typ
, Loc
),
8133 Parameter_Associations
=> New_List
(Expression
(N
))));
8136 end Expand_N_Delay_Until_Statement
;
8138 -------------------------
8139 -- Expand_N_Entry_Body --
8140 -------------------------
8142 procedure Expand_N_Entry_Body
(N
: Node_Id
) is
8144 -- Associate discriminals with the next protected operation body to be
8147 if Present
(Next_Protected_Operation
(N
)) then
8148 Set_Discriminals
(Parent
(Current_Scope
));
8150 end Expand_N_Entry_Body
;
8152 -----------------------------------
8153 -- Expand_N_Entry_Call_Statement --
8154 -----------------------------------
8156 -- An entry call is expanded into GNARLI calls to implement a simple entry
8157 -- call (see Build_Simple_Entry_Call).
8159 procedure Expand_N_Entry_Call_Statement
(N
: Node_Id
) is
8165 if No_Run_Time_Mode
then
8166 Error_Msg_CRT
("entry call", N
);
8170 -- If this entry call is part of an asynchronous select, don't expand it
8171 -- here; it will be expanded with the select statement. Don't expand
8172 -- timed entry calls either, as they are translated into asynchronous
8175 -- ??? This whole approach is questionable; it may be better to go back
8176 -- to allowing the expansion to take place and then attempting to fix it
8177 -- up in Expand_N_Asynchronous_Select. The tricky part is figuring out
8178 -- whether the expanded call is on a task or protected entry.
8180 if (Nkind
(Parent
(N
)) /= N_Triggering_Alternative
8181 or else N
/= Triggering_Statement
(Parent
(N
)))
8182 and then (Nkind
(Parent
(N
)) /= N_Entry_Call_Alternative
8183 or else N
/= Entry_Call_Statement
(Parent
(N
))
8184 or else Nkind
(Parent
(Parent
(N
))) /= N_Timed_Entry_Call
)
8186 Extract_Entry
(N
, Concval
, Ename
, Index
);
8187 Build_Simple_Entry_Call
(N
, Concval
, Ename
, Index
);
8189 end Expand_N_Entry_Call_Statement
;
8191 --------------------------------
8192 -- Expand_N_Entry_Declaration --
8193 --------------------------------
8195 -- If there are parameters, then first, each of the formals is marked by
8196 -- setting Is_Entry_Formal. Next a record type is built which is used to
8197 -- hold the parameter values. The name of this record type is entryP where
8198 -- entry is the name of the entry, with an additional corresponding access
8199 -- type called entryPA. The record type has matching components for each
8200 -- formal (the component names are the same as the formal names). For
8201 -- elementary types, the component type matches the formal type. For
8202 -- composite types, an access type is declared (with the name formalA)
8203 -- which designates the formal type, and the type of the component is this
8204 -- access type. Finally the Entry_Component of each formal is set to
8205 -- reference the corresponding record component.
8207 procedure Expand_N_Entry_Declaration
(N
: Node_Id
) is
8208 Loc
: constant Source_Ptr
:= Sloc
(N
);
8209 Entry_Ent
: constant Entity_Id
:= Defining_Identifier
(N
);
8210 Components
: List_Id
;
8213 Last_Decl
: Node_Id
;
8214 Component
: Entity_Id
;
8217 Rec_Ent
: Entity_Id
;
8218 Acc_Ent
: Entity_Id
;
8221 Formal
:= First_Formal
(Entry_Ent
);
8224 -- Most processing is done only if parameters are present
8226 if Present
(Formal
) then
8227 Components
:= New_List
;
8229 -- Loop through formals
8231 while Present
(Formal
) loop
8232 Set_Is_Entry_Formal
(Formal
);
8234 Make_Defining_Identifier
(Sloc
(Formal
), Chars
(Formal
));
8235 Set_Entry_Component
(Formal
, Component
);
8236 Set_Entry_Formal
(Component
, Formal
);
8237 Ftype
:= Etype
(Formal
);
8239 -- Declare new access type and then append
8241 Ctype
:= Make_Temporary
(Loc
, 'A');
8242 Set_Is_Param_Block_Component_Type
(Ctype
);
8245 Make_Full_Type_Declaration
(Loc
,
8246 Defining_Identifier
=> Ctype
,
8248 Make_Access_To_Object_Definition
(Loc
,
8249 All_Present
=> True,
8250 Constant_Present
=> Ekind
(Formal
) = E_In_Parameter
,
8251 Subtype_Indication
=> New_Occurrence_Of
(Ftype
, Loc
)));
8253 Insert_After
(Last_Decl
, Decl
);
8256 Append_To
(Components
,
8257 Make_Component_Declaration
(Loc
,
8258 Defining_Identifier
=> Component
,
8259 Component_Definition
=>
8260 Make_Component_Definition
(Loc
,
8261 Aliased_Present
=> False,
8262 Subtype_Indication
=> New_Occurrence_Of
(Ctype
, Loc
))));
8264 Next_Formal_With_Extras
(Formal
);
8267 -- Create the Entry_Parameter_Record declaration
8269 Rec_Ent
:= Make_Temporary
(Loc
, 'P');
8272 Make_Full_Type_Declaration
(Loc
,
8273 Defining_Identifier
=> Rec_Ent
,
8275 Make_Record_Definition
(Loc
,
8277 Make_Component_List
(Loc
,
8278 Component_Items
=> Components
)));
8280 Insert_After
(Last_Decl
, Decl
);
8283 -- Construct and link in the corresponding access type
8285 Acc_Ent
:= Make_Temporary
(Loc
, 'A');
8287 Set_Entry_Parameters_Type
(Entry_Ent
, Acc_Ent
);
8290 Make_Full_Type_Declaration
(Loc
,
8291 Defining_Identifier
=> Acc_Ent
,
8293 Make_Access_To_Object_Definition
(Loc
,
8294 All_Present
=> True,
8295 Subtype_Indication
=> New_Occurrence_Of
(Rec_Ent
, Loc
)));
8297 Insert_After
(Last_Decl
, Decl
);
8299 end Expand_N_Entry_Declaration
;
8301 -----------------------------
8302 -- Expand_N_Protected_Body --
8303 -----------------------------
8305 -- Protected bodies are expanded to the completion of the subprograms
8306 -- created for the corresponding protected type. These are a protected and
8307 -- unprotected version of each protected subprogram in the object, a
8308 -- function to calculate each entry barrier, and a procedure to execute the
8309 -- sequence of statements of each protected entry body. For example, for
8310 -- protected type ptype:
8313 -- (O : System.Address;
8314 -- E : Protected_Entry_Index)
8317 -- <discriminant renamings>
8318 -- <private object renamings>
8320 -- return <barrier expression>;
8323 -- procedure pprocN (_object : in out poV;...) is
8324 -- <discriminant renamings>
8325 -- <private object renamings>
8327 -- <sequence of statements>
8330 -- procedure pprocP (_object : in out poV;...) is
8331 -- procedure _clean is
8334 -- ptypeS (_object, Pn);
8335 -- Unlock (_object._object'Access);
8336 -- Abort_Undefer.all;
8341 -- Lock (_object._object'Access);
8342 -- pprocN (_object;...);
8347 -- function pfuncN (_object : poV;...) return Return_Type is
8348 -- <discriminant renamings>
8349 -- <private object renamings>
8351 -- <sequence of statements>
8354 -- function pfuncP (_object : poV) return Return_Type is
8355 -- procedure _clean is
8357 -- Unlock (_object._object'Access);
8358 -- Abort_Undefer.all;
8363 -- Lock (_object._object'Access);
8364 -- return pfuncN (_object);
8371 -- (O : System.Address;
8372 -- P : System.Address;
8373 -- E : Protected_Entry_Index)
8375 -- <discriminant renamings>
8376 -- <private object renamings>
8377 -- type poVP is access poV;
8378 -- _Object : ptVP := ptVP!(O);
8382 -- <statement sequence>
8383 -- Complete_Entry_Body (_Object._Object);
8385 -- when all others =>
8386 -- Exceptional_Complete_Entry_Body (
8387 -- _Object._Object, Get_GNAT_Exception);
8391 -- The type poV is the record created for the protected type to hold
8392 -- the state of the protected object.
8394 procedure Expand_N_Protected_Body
(N
: Node_Id
) is
8395 Loc
: constant Source_Ptr
:= Sloc
(N
);
8396 Pid
: constant Entity_Id
:= Corresponding_Spec
(N
);
8398 Lock_Free_Active
: constant Boolean := Uses_Lock_Free
(Pid
);
8399 -- This flag indicates whether the lock free implementation is active
8401 Current_Node
: Node_Id
;
8402 Disp_Op_Body
: Node_Id
;
8403 New_Op_Body
: Node_Id
;
8404 New_Op_Spec
: Node_Id
;
8408 Op_Spec
: Entity_Id
;
8410 function Build_Dispatching_Subprogram_Body
8413 Prot_Bod
: Node_Id
) return Node_Id
;
8414 -- Build a dispatching version of the protected subprogram body. The
8415 -- newly generated subprogram contains a call to the original protected
8416 -- body. The following code is generated:
8418 -- function <protected-function-name> (Param1 .. ParamN) return
8421 -- return <protected-function-name>P (Param1 .. ParamN);
8422 -- end <protected-function-name>;
8426 -- procedure <protected-procedure-name> (Param1 .. ParamN) is
8428 -- <protected-procedure-name>P (Param1 .. ParamN);
8429 -- end <protected-procedure-name>
8431 ---------------------------------------
8432 -- Build_Dispatching_Subprogram_Body --
8433 ---------------------------------------
8435 function Build_Dispatching_Subprogram_Body
8438 Prot_Bod
: Node_Id
) return Node_Id
8440 Loc
: constant Source_Ptr
:= Sloc
(N
);
8447 -- Generate a specification without a letter suffix in order to
8448 -- override an interface function or procedure.
8450 Spec
:= Build_Protected_Sub_Specification
(N
, Pid
, Dispatching_Mode
);
8452 -- The formal parameters become the actuals of the protected function
8453 -- or procedure call.
8455 Actuals
:= New_List
;
8456 Formal
:= First
(Parameter_Specifications
(Spec
));
8457 while Present
(Formal
) loop
8459 Make_Identifier
(Loc
, Chars
(Defining_Identifier
(Formal
))));
8463 if Nkind
(Spec
) = N_Procedure_Specification
then
8466 Make_Procedure_Call_Statement
(Loc
,
8468 New_Occurrence_Of
(Corresponding_Spec
(Prot_Bod
), Loc
),
8469 Parameter_Associations
=> Actuals
));
8472 pragma Assert
(Nkind
(Spec
) = N_Function_Specification
);
8476 Make_Simple_Return_Statement
(Loc
,
8478 Make_Function_Call
(Loc
,
8480 New_Occurrence_Of
(Corresponding_Spec
(Prot_Bod
), Loc
),
8481 Parameter_Associations
=> Actuals
)));
8485 Make_Subprogram_Body
(Loc
,
8486 Declarations
=> Empty_List
,
8487 Specification
=> Spec
,
8488 Handled_Statement_Sequence
=>
8489 Make_Handled_Sequence_Of_Statements
(Loc
, Stmts
));
8490 end Build_Dispatching_Subprogram_Body
;
8492 -- Start of processing for Expand_N_Protected_Body
8495 if No_Run_Time_Mode
then
8496 Error_Msg_CRT
("protected body", N
);
8500 -- This is the proper body corresponding to a stub. The declarations
8501 -- must be inserted at the point of the stub, which in turn is in the
8502 -- declarative part of the parent unit.
8504 if Nkind
(Parent
(N
)) = N_Subunit
then
8505 Current_Node
:= Corresponding_Stub
(Parent
(N
));
8510 Op_Body
:= First
(Declarations
(N
));
8512 -- The protected body is replaced with the bodies of its protected
8513 -- operations, and the declarations for internal objects that may
8514 -- have been created for entry family bounds.
8516 Rewrite
(N
, Make_Null_Statement
(Sloc
(N
)));
8519 while Present
(Op_Body
) loop
8520 case Nkind
(Op_Body
) is
8521 when N_Subprogram_Declaration
=>
8524 when N_Subprogram_Body
=>
8525 Op_Spec
:= Corresponding_Spec
(Op_Body
);
8527 -- Do not create bodies for eliminated operations
8529 if not Is_Eliminated
(Defining_Entity
(Op_Body
))
8530 and then not Is_Eliminated
(Op_Spec
)
8532 if Lock_Free_Active
then
8534 Build_Lock_Free_Unprotected_Subprogram_Body
8538 Build_Unprotected_Subprogram_Body
(Op_Body
, Pid
);
8541 Insert_After
(Current_Node
, New_Op_Body
);
8542 Current_Node
:= New_Op_Body
;
8543 Analyze
(New_Op_Body
);
8545 New_Op_Spec
:= Corresponding_Spec
(New_Op_Body
);
8547 -- When the original subprogram body has nested subprograms,
8548 -- the new body also has them, so set the flag accordingly.
8550 Set_Has_Nested_Subprogram
8551 (New_Op_Spec
, Has_Nested_Subprogram
(New_Op_Spec
));
8553 -- Similarly, when the original subprogram body uses the
8554 -- secondary stack, the new body also does. This is needed
8555 -- when the cleanup actions of the subprogram are delayed
8556 -- because it contains a package instance with a body.
8558 Set_Uses_Sec_Stack
(New_Op_Spec
, Uses_Sec_Stack
(Op_Spec
));
8560 -- Now reset the scopes of the top-level nested subprograms
8561 -- and other declaration entities so that they now refer to
8562 -- the new body's entity (it would preferable to do this
8563 -- within Build_Protected_Sub_Specification, which is called
8564 -- from Build_Unprotected_Subprogram_Body, but the needed
8565 -- subprogram entity isn't available via Corresponding_Spec
8566 -- until after the above Analyze call).
8568 Reset_Scopes_To
(New_Op_Body
, New_Op_Spec
);
8570 -- Build the corresponding protected operation. This is
8571 -- needed only if this is a public or private operation of
8574 Op_Decl
:= Unit_Declaration_Node
(Op_Spec
);
8576 if Nkind
(Parent
(Op_Decl
)) = N_Protected_Definition
then
8577 if Lock_Free_Active
then
8579 Build_Lock_Free_Protected_Subprogram_Body
8580 (Op_Body
, Pid
, Specification
(New_Op_Body
));
8583 Build_Protected_Subprogram_Body
8584 (Op_Body
, Pid
, Specification
(New_Op_Body
));
8587 Insert_After
(Current_Node
, New_Op_Body
);
8588 Current_Node
:= New_Op_Body
;
8589 Analyze
(New_Op_Body
);
8591 -- Generate an overriding primitive operation body for
8592 -- this subprogram if the protected type implements
8595 if Ada_Version
>= Ada_2005
8597 Present
(Interfaces
(Corresponding_Record_Type
(Pid
)))
8600 Build_Dispatching_Subprogram_Body
(
8601 Op_Body
, Pid
, New_Op_Body
);
8603 Insert_After
(Current_Node
, Disp_Op_Body
);
8604 Current_Node
:= Disp_Op_Body
;
8605 Analyze
(Disp_Op_Body
);
8610 when N_Entry_Body
=>
8611 Op_Id
:= Defining_Identifier
(Op_Body
);
8612 New_Op_Body
:= Build_Protected_Entry
(Op_Body
, Op_Id
, Pid
);
8614 Insert_After
(Current_Node
, New_Op_Body
);
8615 Current_Node
:= New_Op_Body
;
8616 Analyze
(New_Op_Body
);
8618 when N_Implicit_Label_Declaration
=>
8624 New_Op_Body
:= New_Copy
(Op_Body
);
8625 Insert_After
(Current_Node
, New_Op_Body
);
8626 Current_Node
:= New_Op_Body
;
8628 when N_Freeze_Entity
=>
8629 New_Op_Body
:= New_Copy
(Op_Body
);
8631 if Present
(Entity
(Op_Body
))
8632 and then Freeze_Node
(Entity
(Op_Body
)) = Op_Body
8634 Set_Freeze_Node
(Entity
(Op_Body
), New_Op_Body
);
8637 Insert_After
(Current_Node
, New_Op_Body
);
8638 Current_Node
:= New_Op_Body
;
8639 Analyze
(New_Op_Body
);
8642 New_Op_Body
:= New_Copy
(Op_Body
);
8643 Insert_After
(Current_Node
, New_Op_Body
);
8644 Current_Node
:= New_Op_Body
;
8645 Analyze
(New_Op_Body
);
8647 when N_Object_Declaration
=>
8648 pragma Assert
(not Comes_From_Source
(Op_Body
));
8649 New_Op_Body
:= New_Copy
(Op_Body
);
8650 Insert_After
(Current_Node
, New_Op_Body
);
8651 Current_Node
:= New_Op_Body
;
8652 Analyze
(New_Op_Body
);
8655 raise Program_Error
;
8661 -- Finally, create the body of the function that maps an entry index
8662 -- into the corresponding body index, except when there is no entry, or
8663 -- in a Ravenscar-like profile.
8665 if Corresponding_Runtime_Package
(Pid
) =
8666 System_Tasking_Protected_Objects_Entries
8668 New_Op_Body
:= Build_Find_Body_Index
(Pid
);
8669 Insert_After
(Current_Node
, New_Op_Body
);
8670 Current_Node
:= New_Op_Body
;
8671 Analyze
(New_Op_Body
);
8674 -- Ada 2005 (AI-345): Construct the primitive wrapper bodies after the
8675 -- protected body. At this point all wrapper specs have been created,
8676 -- frozen and included in the dispatch table for the protected type.
8678 if Ada_Version
>= Ada_2005
then
8679 Build_Wrapper_Bodies
(Loc
, Pid
, Current_Node
);
8681 end Expand_N_Protected_Body
;
8683 -----------------------------------------
8684 -- Expand_N_Protected_Type_Declaration --
8685 -----------------------------------------
8687 -- First we create a corresponding record type declaration used to
8688 -- represent values of this protected type.
8689 -- The general form of this type declaration is
8691 -- type poV (discriminants) is record
8692 -- _Object : aliased <kind>Protection
8693 -- [(<entry count> [, <handler count>])];
8694 -- [entry_family : array (bounds) of Void;]
8695 -- <private data fields>
8698 -- The discriminants are present only if the corresponding protected type
8699 -- has discriminants, and they exactly mirror the protected type
8700 -- discriminants. The private data fields similarly mirror the private
8701 -- declarations of the protected type.
8703 -- The Object field is always present. It contains RTS specific data used
8704 -- to control the protected object. It is declared as Aliased so that it
8705 -- can be passed as a pointer to the RTS. This allows the protected record
8706 -- to be referenced within RTS data structures. An appropriate Protection
8707 -- type and discriminant are generated.
8709 -- The Service field is present for protected objects with entries. It
8710 -- contains sufficient information to allow the entry service procedure for
8711 -- this object to be called when the object is not known till runtime.
8713 -- One entry_family component is present for each entry family in the
8714 -- task definition (see Expand_N_Task_Type_Declaration).
8716 -- When a protected object is declared, an instance of the protected type
8717 -- value record is created. The elaboration of this declaration creates the
8718 -- correct bounds for the entry families, and also evaluates the priority
8719 -- expression if needed. The initialization routine for the protected type
8720 -- itself then calls Initialize_Protection with appropriate parameters to
8721 -- initialize the value of the Task_Id field. Install_Handlers may be also
8722 -- called if a pragma Attach_Handler applies.
8724 -- Note: this record is passed to the subprograms created by the expansion
8725 -- of protected subprograms and entries. It is an in parameter to protected
8726 -- functions and an in out parameter to procedures and entry bodies. The
8727 -- Entity_Id for this created record type is placed in the
8728 -- Corresponding_Record_Type field of the associated protected type entity.
8730 -- Next we create a procedure specifications for protected subprograms and
8731 -- entry bodies. For each protected subprograms two subprograms are
8732 -- created, an unprotected and a protected version. The unprotected version
8733 -- is called from within other operations of the same protected object.
8735 -- We also build the call to register the procedure if a pragma
8736 -- Interrupt_Handler applies.
8738 -- A single subprogram is created to service all entry bodies; it has an
8739 -- additional boolean out parameter indicating that the previous entry call
8740 -- made by the current task was serviced immediately, i.e. not by proxy.
8741 -- The O parameter contains a pointer to a record object of the type
8742 -- described above. An untyped interface is used here to allow this
8743 -- procedure to be called in places where the type of the object to be
8744 -- serviced is not known. This must be done, for example, when a call that
8745 -- may have been requeued is cancelled; the corresponding object must be
8746 -- serviced, but which object that is not known till runtime.
8749 -- (O : System.Address; P : out Boolean);
8750 -- procedure pprocN (_object : in out poV);
8751 -- procedure pproc (_object : in out poV);
8752 -- function pfuncN (_object : poV);
8753 -- function pfunc (_object : poV);
8756 -- Note that this must come after the record type declaration, since
8757 -- the specs refer to this type.
8759 procedure Expand_N_Protected_Type_Declaration
(N
: Node_Id
) is
8760 Discr_Map
: constant Elist_Id
:= New_Elmt_List
;
8761 Loc
: constant Source_Ptr
:= Sloc
(N
);
8762 Prot_Typ
: constant Entity_Id
:= Defining_Identifier
(N
);
8764 Lock_Free_Active
: constant Boolean := Uses_Lock_Free
(Prot_Typ
);
8765 -- This flag indicates whether the lock free implementation is active
8767 Pdef
: constant Node_Id
:= Protected_Definition
(N
);
8768 -- This contains two lists; one for visible and one for private decls
8770 Current_Node
: Node_Id
:= N
;
8772 Entries_Aggr
: Node_Id
;
8776 procedure Check_Inlining
(Subp
: Entity_Id
);
8777 -- If the original operation has a pragma Inline, propagate the flag
8778 -- to the internal body, for possible inlining later on. The source
8779 -- operation is invisible to the back-end and is never actually called.
8781 procedure Expand_Entry_Declaration
(Decl
: Node_Id
);
8782 -- Create the entry barrier and the procedure body for entry declaration
8783 -- Decl. All generated subprograms are added to Entry_Bodies_Array.
8785 function Static_Component_Size
(Comp
: Entity_Id
) return Boolean;
8786 -- When compiling under the Ravenscar profile, private components must
8787 -- have a static size, or else a protected object will require heap
8788 -- allocation, violating the corresponding restriction. It is preferable
8789 -- to make this check here, because it provides a better error message
8790 -- than the back-end, which refers to the object as a whole.
8792 procedure Register_Handler
;
8793 -- For a protected operation that is an interrupt handler, add the
8794 -- freeze action that will register it as such.
8796 procedure Replace_Access_Definition
(Comp
: Node_Id
);
8797 -- If a private component of the type is an access to itself, this
8798 -- is not a reference to the current instance, but an access type out
8799 -- of which one might construct a list. If such a component exists, we
8800 -- create an incomplete type for the equivalent record type, and
8801 -- a named access type for it, that replaces the access definition
8802 -- of the original component. This is similar to what is done for
8803 -- records in Check_Anonymous_Access_Components, but simpler, because
8804 -- the corresponding record type has no previous declaration.
8805 -- This needs to be done only once, even if there are several such
8806 -- access components. The following entity stores the constructed
8809 Acc_T
: Entity_Id
:= Empty
;
8811 --------------------
8812 -- Check_Inlining --
8813 --------------------
8815 procedure Check_Inlining
(Subp
: Entity_Id
) is
8817 if Is_Inlined
(Subp
) then
8818 Set_Is_Inlined
(Protected_Body_Subprogram
(Subp
));
8819 Set_Is_Inlined
(Subp
, False);
8822 if Has_Pragma_No_Inline
(Subp
) then
8823 Set_Has_Pragma_No_Inline
(Protected_Body_Subprogram
(Subp
));
8827 ---------------------------
8828 -- Static_Component_Size --
8829 ---------------------------
8831 function Static_Component_Size
(Comp
: Entity_Id
) return Boolean is
8832 Typ
: constant Entity_Id
:= Etype
(Comp
);
8836 if Is_Scalar_Type
(Typ
) then
8839 elsif Is_Array_Type
(Typ
) then
8840 return Compile_Time_Known_Bounds
(Typ
);
8842 elsif Is_Record_Type
(Typ
) then
8843 C
:= First_Component
(Typ
);
8844 while Present
(C
) loop
8845 if not Static_Component_Size
(C
) then
8854 -- Any other type will be checked by the back-end
8859 end Static_Component_Size
;
8861 ------------------------------
8862 -- Expand_Entry_Declaration --
8863 ------------------------------
8865 procedure Expand_Entry_Declaration
(Decl
: Node_Id
) is
8866 Ent_Id
: constant Entity_Id
:= Defining_Entity
(Decl
);
8872 E_Count
:= E_Count
+ 1;
8874 -- Create the protected body subprogram
8877 Make_Defining_Identifier
(Loc
,
8878 Chars
=> Build_Selected_Name
(Prot_Typ
, Ent_Id
, 'E'));
8879 Set_Protected_Body_Subprogram
(Ent_Id
, Bod_Id
);
8882 Make_Subprogram_Declaration
(Loc
,
8884 Build_Protected_Entry_Specification
(Loc
, Bod_Id
, Ent_Id
));
8886 Insert_After
(Current_Node
, Subp
);
8887 Current_Node
:= Subp
;
8891 -- Build a wrapper procedure to handle contract cases, preconditions,
8892 -- and postconditions.
8894 Build_Entry_Contract_Wrapper
(Ent_Id
, N
);
8896 -- Create the barrier function
8899 Make_Defining_Identifier
(Loc
,
8900 Chars
=> Build_Selected_Name
(Prot_Typ
, Ent_Id
, 'B'));
8901 Set_Barrier_Function
(Ent_Id
, Bar_Id
);
8904 Make_Subprogram_Declaration
(Loc
,
8906 Build_Barrier_Function_Specification
(Loc
, Bar_Id
));
8907 Set_Is_Entry_Barrier_Function
(Subp
);
8909 Insert_After
(Current_Node
, Subp
);
8910 Current_Node
:= Subp
;
8914 Set_Protected_Body_Subprogram
(Bar_Id
, Bar_Id
);
8915 Set_Scope
(Bar_Id
, Scope
(Ent_Id
));
8917 -- Collect pointers to the protected subprogram and the barrier
8918 -- of the current entry, for insertion into Entry_Bodies_Array.
8920 Append_To
(Expressions
(Entries_Aggr
),
8921 Make_Aggregate
(Loc
,
8922 Expressions
=> New_List
(
8923 Make_Attribute_Reference
(Loc
,
8924 Prefix
=> New_Occurrence_Of
(Bar_Id
, Loc
),
8925 Attribute_Name
=> Name_Unrestricted_Access
),
8926 Make_Attribute_Reference
(Loc
,
8927 Prefix
=> New_Occurrence_Of
(Bod_Id
, Loc
),
8928 Attribute_Name
=> Name_Unrestricted_Access
))));
8929 end Expand_Entry_Declaration
;
8931 ----------------------
8932 -- Register_Handler --
8933 ----------------------
8935 procedure Register_Handler
is
8937 -- All semantic checks already done in Sem_Prag
8939 Prot_Proc
: constant Entity_Id
:=
8940 Defining_Unit_Name
(Specification
(Current_Node
));
8942 Proc_Address
: constant Node_Id
:=
8943 Make_Attribute_Reference
(Loc
,
8945 New_Occurrence_Of
(Prot_Proc
, Loc
),
8946 Attribute_Name
=> Name_Address
);
8948 RTS_Call
: constant Entity_Id
:=
8949 Make_Procedure_Call_Statement
(Loc
,
8952 (RTE
(RE_Register_Interrupt_Handler
), Loc
),
8953 Parameter_Associations
=> New_List
(Proc_Address
));
8955 Append_Freeze_Action
(Prot_Proc
, RTS_Call
);
8956 end Register_Handler
;
8958 -------------------------------
8959 -- Replace_Access_Definition --
8960 -------------------------------
8962 procedure Replace_Access_Definition
(Comp
: Node_Id
) is
8963 Loc
: constant Source_Ptr
:= Sloc
(Comp
);
8971 Inc_T
:= Make_Defining_Identifier
(Loc
, Chars
(Rec_Id
));
8972 Inc_D
:= Make_Incomplete_Type_Declaration
(Loc
, Inc_T
);
8973 Acc_T
:= Make_Temporary
(Loc
, 'S');
8975 Make_Access_To_Object_Definition
(Loc
,
8976 Subtype_Indication
=> New_Occurrence_Of
(Inc_T
, Loc
));
8978 Make_Full_Type_Declaration
(Loc
,
8979 Defining_Identifier
=> Acc_T
,
8980 Type_Definition
=> Acc_Def
);
8982 Insert_Before
(Rec_Decl
, Inc_D
);
8985 Insert_Before
(Rec_Decl
, Acc_D
);
8989 Set_Access_Definition
(Comp
, Empty
);
8990 Set_Subtype_Indication
(Comp
, New_Occurrence_Of
(Acc_T
, Loc
));
8991 end Replace_Access_Definition
;
8996 Body_Id
: Entity_Id
;
9002 Object_Comp
: Node_Id
;
9006 -- Start of processing for Expand_N_Protected_Type_Declaration
9009 if Present
(Corresponding_Record_Type
(Prot_Typ
)) then
9012 Rec_Decl
:= Build_Corresponding_Record
(N
, Prot_Typ
, Loc
);
9013 Rec_Id
:= Defining_Identifier
(Rec_Decl
);
9016 Cdecls
:= Component_Items
(Component_List
(Type_Definition
(Rec_Decl
)));
9018 Qualify_Entity_Names
(N
);
9020 -- If the type has discriminants, their occurrences in the declaration
9021 -- have been replaced by the corresponding discriminals. For components
9022 -- that are constrained by discriminants, their homologues in the
9023 -- corresponding record type must refer to the discriminants of that
9024 -- record, so we must apply a new renaming to subtypes_indications:
9026 -- protected discriminant => discriminal => record discriminant
9028 -- This replacement is not applied to default expressions, for which
9029 -- the discriminal is correct.
9031 if Has_Discriminants
(Prot_Typ
) then
9037 Disc
:= First_Discriminant
(Prot_Typ
);
9038 Decl
:= First
(Discriminant_Specifications
(Rec_Decl
));
9039 while Present
(Disc
) loop
9040 Append_Elmt
(Discriminal
(Disc
), Discr_Map
);
9041 Append_Elmt
(Defining_Identifier
(Decl
), Discr_Map
);
9042 Next_Discriminant
(Disc
);
9048 -- Fill in the component declarations
9050 -- Add components for entry families. For each entry family, create an
9051 -- anonymous type declaration with the same size, and analyze the type.
9053 Collect_Entry_Families
(Loc
, Cdecls
, Current_Node
, Prot_Typ
);
9055 pragma Assert
(Present
(Pdef
));
9057 Insert_After
(Current_Node
, Rec_Decl
);
9058 Current_Node
:= Rec_Decl
;
9060 -- Add private field components
9062 Priv
:= First
(Private_Declarations
(Pdef
));
9063 while Present
(Priv
) loop
9064 if Nkind
(Priv
) = N_Component_Declaration
then
9065 if not Static_Component_Size
(Defining_Identifier
(Priv
)) then
9067 -- When compiling for a restricted profile, the private
9068 -- components must have a static size. If not, this is an error
9069 -- for a single protected declaration, and rates a warning on a
9070 -- protected type declaration.
9072 if not Comes_From_Source
(Prot_Typ
) then
9074 -- It's ok to be checking this restriction at expansion
9075 -- time, because this is only for the restricted profile,
9076 -- which is not subject to strict RM conformance, so it
9077 -- is OK to miss this check in -gnatc mode.
9079 Check_Restriction
(No_Implicit_Heap_Allocations
, Priv
);
9081 (No_Implicit_Protected_Object_Allocations
, Priv
);
9083 elsif Restriction_Active
(No_Implicit_Heap_Allocations
) then
9084 if not Discriminated_Size
(Defining_Identifier
(Priv
))
9086 -- Any object of the type will be non-static
9088 Error_Msg_N
("component has non-static size??", Priv
);
9090 ("\creation of protected object of type& will "
9091 & "violate restriction "
9092 & "No_Implicit_Heap_Allocations??", Priv
, Prot_Typ
);
9094 -- Object will be non-static if discriminants are
9097 ("creation of protected object of type& with "
9098 & "non-static discriminants will violate "
9099 & "restriction No_Implicit_Heap_Allocations??",
9103 -- Likewise for No_Implicit_Protected_Object_Allocations
9105 elsif Restriction_Active
9106 (No_Implicit_Protected_Object_Allocations
)
9108 if not Discriminated_Size
(Defining_Identifier
(Priv
)) then
9109 -- Any object of the type will be non-static
9111 Error_Msg_N
("component has non-static size??", Priv
);
9113 ("\creation of protected object of type& will violate "
9115 & "No_Implicit_Protected_Object_Allocations??",
9118 -- Object will be non-static if discriminants are
9121 ("creation of protected object of type& with "
9122 & "non-static discriminants will violate restriction "
9123 & "No_Implicit_Protected_Object_Allocations??",
9129 -- The component definition consists of a subtype indication, or
9130 -- (in Ada 2005) an access definition. Make a copy of the proper
9134 Old_Comp
: constant Node_Id
:= Component_Definition
(Priv
);
9135 Oent
: constant Entity_Id
:= Defining_Identifier
(Priv
);
9136 Nent
: constant Entity_Id
:=
9137 Make_Defining_Identifier
(Sloc
(Oent
),
9138 Chars
=> Chars
(Oent
));
9142 if Present
(Subtype_Indication
(Old_Comp
)) then
9144 Make_Component_Definition
(Sloc
(Oent
),
9145 Aliased_Present
=> False,
9146 Subtype_Indication
=>
9148 (Subtype_Indication
(Old_Comp
), Discr_Map
));
9151 Make_Component_Definition
(Sloc
(Oent
),
9152 Aliased_Present
=> False,
9153 Access_Definition
=>
9155 (Access_Definition
(Old_Comp
), Discr_Map
));
9157 -- A self-reference in the private part becomes a
9158 -- self-reference to the corresponding record.
9160 if Entity
(Subtype_Mark
(Access_Definition
(New_Comp
)))
9163 Replace_Access_Definition
(New_Comp
);
9168 Make_Component_Declaration
(Loc
,
9169 Defining_Identifier
=> Nent
,
9170 Component_Definition
=> New_Comp
,
9171 Expression
=> Expression
(Priv
));
9173 Set_Has_Per_Object_Constraint
(Nent
,
9174 Has_Per_Object_Constraint
(Oent
));
9176 Append_To
(Cdecls
, New_Priv
);
9179 elsif Nkind
(Priv
) = N_Subprogram_Declaration
then
9181 -- Make the unprotected version of the subprogram available for
9182 -- expansion of intra object calls. There is need for a protected
9183 -- version only if the subprogram is an interrupt handler,
9184 -- otherwise this operation can only be called from within the
9188 Make_Subprogram_Declaration
(Loc
,
9190 Build_Protected_Sub_Specification
9191 (Priv
, Prot_Typ
, Unprotected_Mode
));
9193 Insert_After
(Current_Node
, Sub
);
9196 Set_Protected_Body_Subprogram
9197 (Defining_Unit_Name
(Specification
(Priv
)),
9198 Defining_Unit_Name
(Specification
(Sub
)));
9199 Check_Inlining
(Defining_Unit_Name
(Specification
(Priv
)));
9200 Current_Node
:= Sub
;
9203 Make_Subprogram_Declaration
(Loc
,
9205 Build_Protected_Sub_Specification
9206 (Priv
, Prot_Typ
, Protected_Mode
));
9208 Insert_After
(Current_Node
, Sub
);
9210 Current_Node
:= Sub
;
9212 if Is_Interrupt_Handler
9213 (Defining_Unit_Name
(Specification
(Priv
)))
9215 if not Restricted_Profile
then
9224 -- Except for the lock-free implementation, append the _Object field
9225 -- with the right type to the component list. We need to compute the
9226 -- number of entries, and in some cases the number of Attach_Handler
9229 if not Lock_Free_Active
then
9231 Entry_Count_Expr
: constant Node_Id
:=
9232 Build_Entry_Count_Expression
9234 Num_Attach_Handler
: Nat
:= 0;
9235 Protection_Subtype
: Node_Id
;
9239 if Has_Attach_Handler
(Prot_Typ
) then
9240 Ritem
:= First_Rep_Item
(Prot_Typ
);
9241 while Present
(Ritem
) loop
9242 if Nkind
(Ritem
) = N_Pragma
9243 and then Pragma_Name
(Ritem
) = Name_Attach_Handler
9245 Num_Attach_Handler
:= Num_Attach_Handler
+ 1;
9248 Next_Rep_Item
(Ritem
);
9252 -- Determine the proper protection type. There are two special
9253 -- cases: 1) when the protected type has dynamic interrupt
9254 -- handlers, and 2) when it has static handlers and we use a
9255 -- restricted profile.
9257 if Has_Attach_Handler
(Prot_Typ
)
9258 and then not Restricted_Profile
9260 Protection_Subtype
:=
9261 Make_Subtype_Indication
(Loc
,
9264 (RTE
(RE_Static_Interrupt_Protection
), Loc
),
9266 Make_Index_Or_Discriminant_Constraint
(Loc
,
9267 Constraints
=> New_List
(
9269 Make_Integer_Literal
(Loc
, Num_Attach_Handler
))));
9271 elsif Has_Interrupt_Handler
(Prot_Typ
)
9272 and then not Restriction_Active
(No_Dynamic_Attachment
)
9274 Protection_Subtype
:=
9275 Make_Subtype_Indication
(Loc
,
9278 (RTE
(RE_Dynamic_Interrupt_Protection
), Loc
),
9280 Make_Index_Or_Discriminant_Constraint
(Loc
,
9281 Constraints
=> New_List
(Entry_Count_Expr
)));
9284 case Corresponding_Runtime_Package
(Prot_Typ
) is
9285 when System_Tasking_Protected_Objects_Entries
=>
9286 Protection_Subtype
:=
9287 Make_Subtype_Indication
(Loc
,
9290 (RTE
(RE_Protection_Entries
), Loc
),
9292 Make_Index_Or_Discriminant_Constraint
(Loc
,
9293 Constraints
=> New_List
(Entry_Count_Expr
)));
9295 when System_Tasking_Protected_Objects_Single_Entry
=>
9296 Protection_Subtype
:=
9297 New_Occurrence_Of
(RTE
(RE_Protection_Entry
), Loc
);
9299 when System_Tasking_Protected_Objects
=>
9300 Protection_Subtype
:=
9301 New_Occurrence_Of
(RTE
(RE_Protection
), Loc
);
9304 raise Program_Error
;
9309 Make_Component_Declaration
(Loc
,
9310 Defining_Identifier
=>
9311 Make_Defining_Identifier
(Loc
, Name_uObject
),
9312 Component_Definition
=>
9313 Make_Component_Definition
(Loc
,
9314 Aliased_Present
=> True,
9315 Subtype_Indication
=> Protection_Subtype
));
9318 -- Put the _Object component after the private component so that it
9319 -- be finalized early as required by 9.4 (20)
9321 Append_To
(Cdecls
, Object_Comp
);
9324 -- Analyze the record declaration immediately after construction,
9325 -- because the initialization procedure is needed for single object
9326 -- declarations before the next entity is analyzed (the freeze call
9327 -- that generates this initialization procedure is found below).
9329 Analyze
(Rec_Decl
, Suppress
=> All_Checks
);
9331 -- Ada 2005 (AI-345): Construct the primitive entry wrappers before
9332 -- the corresponding record is frozen. If any wrappers are generated,
9333 -- Current_Node is updated accordingly.
9335 if Ada_Version
>= Ada_2005
then
9336 Build_Wrapper_Specs
(Loc
, Prot_Typ
, Current_Node
);
9339 -- Collect pointers to entry bodies and their barriers, to be placed
9340 -- in the Entry_Bodies_Array for the type. For each entry/family we
9341 -- add an expression to the aggregate which is the initial value of
9342 -- this array. The array is declared after all protected subprograms.
9344 if Has_Entries
(Prot_Typ
) then
9345 Entries_Aggr
:= Make_Aggregate
(Loc
, Expressions
=> New_List
);
9347 Entries_Aggr
:= Empty
;
9350 -- Build two new procedure specifications for each protected subprogram;
9351 -- one to call from outside the object and one to call from inside.
9352 -- Build a barrier function and an entry body action procedure
9353 -- specification for each protected entry. Initialize the entry body
9354 -- array. If subprogram is flagged as eliminated, do not generate any
9355 -- internal operations.
9358 Comp
:= First
(Visible_Declarations
(Pdef
));
9359 while Present
(Comp
) loop
9360 if Nkind
(Comp
) = N_Subprogram_Declaration
then
9362 Make_Subprogram_Declaration
(Loc
,
9364 Build_Protected_Sub_Specification
9365 (Comp
, Prot_Typ
, Unprotected_Mode
));
9367 Insert_After
(Current_Node
, Sub
);
9370 Set_Protected_Body_Subprogram
9371 (Defining_Unit_Name
(Specification
(Comp
)),
9372 Defining_Unit_Name
(Specification
(Sub
)));
9373 Check_Inlining
(Defining_Unit_Name
(Specification
(Comp
)));
9375 -- Make the protected version of the subprogram available for
9376 -- expansion of external calls.
9378 Current_Node
:= Sub
;
9381 Make_Subprogram_Declaration
(Loc
,
9383 Build_Protected_Sub_Specification
9384 (Comp
, Prot_Typ
, Protected_Mode
));
9386 Insert_After
(Current_Node
, Sub
);
9389 Current_Node
:= Sub
;
9391 -- Generate an overriding primitive operation specification for
9392 -- this subprogram if the protected type implements an interface
9393 -- and Build_Wrapper_Spec did not generate its wrapper.
9395 if Ada_Version
>= Ada_2005
9397 Present
(Interfaces
(Corresponding_Record_Type
(Prot_Typ
)))
9400 Found
: Boolean := False;
9401 Prim_Elmt
: Elmt_Id
;
9407 (Primitive_Operations
9408 (Corresponding_Record_Type
(Prot_Typ
)));
9410 while Present
(Prim_Elmt
) loop
9411 Prim_Op
:= Node
(Prim_Elmt
);
9413 if Is_Primitive_Wrapper
(Prim_Op
)
9414 and then Wrapped_Entity
(Prim_Op
) =
9415 Defining_Entity
(Specification
(Comp
))
9421 Next_Elmt
(Prim_Elmt
);
9426 Make_Subprogram_Declaration
(Loc
,
9428 Build_Protected_Sub_Specification
9429 (Comp
, Prot_Typ
, Dispatching_Mode
));
9431 Insert_After
(Current_Node
, Sub
);
9434 Current_Node
:= Sub
;
9439 -- If a pragma Interrupt_Handler applies, build and add a call to
9440 -- Register_Interrupt_Handler to the freezing actions of the
9441 -- protected version (Current_Node) of the subprogram:
9443 -- system.interrupts.register_interrupt_handler
9444 -- (prot_procP'address);
9446 if not Restricted_Profile
9447 and then Is_Interrupt_Handler
9448 (Defining_Unit_Name
(Specification
(Comp
)))
9453 elsif Nkind
(Comp
) = N_Entry_Declaration
then
9454 Expand_Entry_Declaration
(Comp
);
9460 -- If there are some private entry declarations, expand it as if they
9461 -- were visible entries.
9463 Comp
:= First
(Private_Declarations
(Pdef
));
9464 while Present
(Comp
) loop
9465 if Nkind
(Comp
) = N_Entry_Declaration
then
9466 Expand_Entry_Declaration
(Comp
);
9472 -- Create the declaration of an array object which contains the values
9473 -- of aspect/pragma Max_Queue_Length for all entries of the protected
9474 -- type. This object is later passed to the appropriate protected object
9475 -- initialization routine.
9477 if Has_Entries
(Prot_Typ
)
9478 and then Corresponding_Runtime_Package
(Prot_Typ
) =
9479 System_Tasking_Protected_Objects_Entries
9486 Maxes_Id
: Entity_Id
;
9487 Need_Array
: Boolean := False;
9490 -- First check if there is any Max_Queue_Length pragma
9492 Item
:= First_Entity
(Prot_Typ
);
9493 while Present
(Item
) loop
9494 if Is_Entry
(Item
) and then Has_Max_Queue_Length
(Item
) then
9502 -- Gather the Max_Queue_Length values of all entries in a list. A
9503 -- value of zero indicates that the entry has no limitation on its
9508 Item
:= First_Entity
(Prot_Typ
);
9510 while Present
(Item
) loop
9511 if Is_Entry
(Item
) then
9514 Make_Integer_Literal
9515 (Loc
, Get_Max_Queue_Length
(Item
)));
9521 -- Create the declaration of the array object. Generate:
9523 -- Maxes_Id : aliased constant
9524 -- Protected_Entry_Queue_Max_Array
9525 -- (1 .. Count) := (..., ...);
9528 Make_Defining_Identifier
(Loc
,
9529 Chars
=> New_External_Name
(Chars
(Prot_Typ
), 'B'));
9532 Make_Object_Declaration
(Loc
,
9533 Defining_Identifier
=> Maxes_Id
,
9534 Aliased_Present
=> True,
9535 Constant_Present
=> True,
9536 Object_Definition
=>
9537 Make_Subtype_Indication
(Loc
,
9540 (RTE
(RE_Protected_Entry_Queue_Max_Array
), Loc
),
9542 Make_Index_Or_Discriminant_Constraint
(Loc
,
9543 Constraints
=> New_List
(
9545 Make_Integer_Literal
(Loc
, 1),
9546 Make_Integer_Literal
(Loc
, Count
))))),
9547 Expression
=> Make_Aggregate
(Loc
, Maxes
));
9549 -- A pointer to this array will be placed in the corresponding
9550 -- record by its initialization procedure so this needs to be
9553 Insert_After
(Current_Node
, Max_Vals
);
9554 Current_Node
:= Max_Vals
;
9557 Set_Entry_Max_Queue_Lengths_Array
(Prot_Typ
, Maxes_Id
);
9562 -- Emit declaration for Entry_Bodies_Array, now that the addresses of
9563 -- all protected subprograms have been collected.
9565 if Has_Entries
(Prot_Typ
) then
9567 Make_Defining_Identifier
(Sloc
(Prot_Typ
),
9568 Chars
=> New_External_Name
(Chars
(Prot_Typ
), 'A'));
9570 case Corresponding_Runtime_Package
(Prot_Typ
) is
9571 when System_Tasking_Protected_Objects_Entries
=>
9572 Expr
:= Entries_Aggr
;
9574 Make_Subtype_Indication
(Loc
,
9577 (RTE
(RE_Protected_Entry_Body_Array
), Loc
),
9579 Make_Index_Or_Discriminant_Constraint
(Loc
,
9580 Constraints
=> New_List
(
9582 Make_Integer_Literal
(Loc
, 1),
9583 Make_Integer_Literal
(Loc
, E_Count
)))));
9585 when System_Tasking_Protected_Objects_Single_Entry
=>
9586 Expr
:= Remove_Head
(Expressions
(Entries_Aggr
));
9587 Obj_Def
:= New_Occurrence_Of
(RTE
(RE_Entry_Body
), Loc
);
9590 raise Program_Error
;
9594 Make_Object_Declaration
(Loc
,
9595 Defining_Identifier
=> Body_Id
,
9596 Aliased_Present
=> True,
9597 Constant_Present
=> True,
9598 Object_Definition
=> Obj_Def
,
9599 Expression
=> Expr
);
9601 -- A pointer to this array will be placed in the corresponding record
9602 -- by its initialization procedure so this needs to be analyzed here.
9604 Insert_After
(Current_Node
, Body_Arr
);
9605 Current_Node
:= Body_Arr
;
9608 Set_Entry_Bodies_Array
(Prot_Typ
, Body_Id
);
9610 -- Finally, build the function that maps an entry index into the
9611 -- corresponding body. A pointer to this function is placed in each
9612 -- object of the type. Except for a ravenscar-like profile (no abort,
9613 -- no entry queue, 1 entry)
9615 if Corresponding_Runtime_Package
(Prot_Typ
) =
9616 System_Tasking_Protected_Objects_Entries
9619 Make_Subprogram_Declaration
(Loc
,
9620 Specification
=> Build_Find_Body_Index_Spec
(Prot_Typ
));
9622 Insert_After
(Current_Node
, Sub
);
9626 end Expand_N_Protected_Type_Declaration
;
9628 --------------------------------
9629 -- Expand_N_Requeue_Statement --
9630 --------------------------------
9632 -- A nondispatching requeue statement is expanded into one of four GNARLI
9633 -- operations, depending on the source and destination (task or protected
9634 -- object). A dispatching requeue statement is expanded into a call to the
9635 -- predefined primitive _Disp_Requeue. In addition, code is generated to
9636 -- jump around the remainder of processing for the original entry and, if
9637 -- the destination is (different) protected object, to attempt to service
9638 -- it. The following illustrates the various cases:
9641 -- (O : System.Address;
9642 -- P : System.Address;
9643 -- E : Protected_Entry_Index)
9645 -- <discriminant renamings>
9646 -- <private object renamings>
9647 -- type poVP is access poV;
9648 -- _object : ptVP := ptVP!(O);
9652 -- <start of statement sequence for entry>
9654 -- -- Requeue from one protected entry body to another protected
9657 -- Requeue_Protected_Entry (
9658 -- _object._object'Access,
9659 -- new._object'Access,
9664 -- <some more of the statement sequence for entry>
9666 -- -- Requeue from an entry body to a task entry
9668 -- Requeue_Protected_To_Task_Entry (
9674 -- <rest of statement sequence for entry>
9675 -- Complete_Entry_Body (_object._object);
9678 -- when all others =>
9679 -- Exceptional_Complete_Entry_Body (
9680 -- _object._object, Get_GNAT_Exception);
9684 -- Requeue of a task entry call to a task entry
9686 -- Accept_Call (E, Ann);
9687 -- <start of statement sequence for accept statement>
9688 -- Requeue_Task_Entry (New._task_id, E, Abort_Present);
9690 -- <rest of statement sequence for accept statement>
9692 -- Complete_Rendezvous;
9695 -- when all others =>
9696 -- Exceptional_Complete_Rendezvous (Get_GNAT_Exception);
9698 -- Requeue of a task entry call to a protected entry
9700 -- Accept_Call (E, Ann);
9701 -- <start of statement sequence for accept statement>
9702 -- Requeue_Task_To_Protected_Entry (
9703 -- new._object'Access,
9708 -- <rest of statement sequence for accept statement>
9710 -- Complete_Rendezvous;
9713 -- when all others =>
9714 -- Exceptional_Complete_Rendezvous (Get_GNAT_Exception);
9716 -- Ada 2012 (AI05-0030): Dispatching requeue to an interface primitive
9717 -- marked by pragma Implemented (XXX, By_Entry).
9719 -- The requeue is inside a protected entry:
9722 -- (O : System.Address;
9723 -- P : System.Address;
9724 -- E : Protected_Entry_Index)
9726 -- <discriminant renamings>
9727 -- <private object renamings>
9728 -- type poVP is access poV;
9729 -- _object : ptVP := ptVP!(O);
9733 -- <start of statement sequence for entry>
9736 -- (<interface class-wide object>,
9739 -- Ada.Tags.Get_Offset_Index
9741 -- <interface dispatch table index of target entry>),
9745 -- <rest of statement sequence for entry>
9746 -- Complete_Entry_Body (_object._object);
9749 -- when all others =>
9750 -- Exceptional_Complete_Entry_Body (
9751 -- _object._object, Get_GNAT_Exception);
9755 -- The requeue is inside a task entry:
9757 -- Accept_Call (E, Ann);
9758 -- <start of statement sequence for accept statement>
9760 -- (<interface class-wide object>,
9763 -- Ada.Tags.Get_Offset_Index
9765 -- <interface dispatch table index of target entrt>),
9769 -- <rest of statement sequence for accept statement>
9771 -- Complete_Rendezvous;
9774 -- when all others =>
9775 -- Exceptional_Complete_Rendezvous (Get_GNAT_Exception);
9777 -- Ada 2012 (AI05-0030): Dispatching requeue to an interface primitive
9778 -- marked by pragma Implemented (XXX, By_Protected_Procedure). The requeue
9779 -- statement is replaced by a dispatching call with actual parameters taken
9780 -- from the inner-most accept statement or entry body.
9782 -- Target.Primitive (Param1, ..., ParamN);
9784 -- Ada 2012 (AI05-0030): Dispatching requeue to an interface primitive
9785 -- marked by pragma Implemented (XXX, By_Any | Optional) or not marked
9789 -- S : constant Offset_Index :=
9790 -- Get_Offset_Index (Tag (Concval), DT_Position (Ename));
9791 -- C : constant Prim_Op_Kind := Get_Prim_Op_Kind (Tag (Concval), S);
9794 -- if C = POK_Protected_Entry
9795 -- or else C = POK_Task_Entry
9797 -- <statements for dispatching requeue>
9799 -- elsif C = POK_Protected_Procedure then
9800 -- <dispatching call equivalent>
9803 -- raise Program_Error;
9807 procedure Expand_N_Requeue_Statement
(N
: Node_Id
) is
9808 Loc
: constant Source_Ptr
:= Sloc
(N
);
9809 Conc_Typ
: Entity_Id
;
9812 Enc_Subp
: Entity_Id
;
9814 Old_Typ
: Entity_Id
;
9816 function Build_Dispatching_Call_Equivalent
return Node_Id
;
9817 -- Ada 2012 (AI05-0030): N denotes a dispatching requeue statement of
9818 -- the form Concval.Ename. It is statically known that Ename is allowed
9819 -- to be implemented by a protected procedure. Create a dispatching call
9820 -- equivalent of Concval.Ename taking the actual parameters from the
9821 -- inner-most accept statement or entry body.
9823 function Build_Dispatching_Requeue
return Node_Id
;
9824 -- Ada 2012 (AI05-0030): N denotes a dispatching requeue statement of
9825 -- the form Concval.Ename. It is statically known that Ename is allowed
9826 -- to be implemented by a protected or a task entry. Create a call to
9827 -- primitive _Disp_Requeue which handles the low-level actions.
9829 function Build_Dispatching_Requeue_To_Any
return Node_Id
;
9830 -- Ada 2012 (AI05-0030): N denotes a dispatching requeue statement of
9831 -- the form Concval.Ename. Ename is either marked by pragma Implemented
9832 -- (XXX, By_Any | Optional) or not marked at all. Create a block which
9833 -- determines at runtime whether Ename denotes an entry or a procedure
9834 -- and perform the appropriate kind of dispatching select.
9836 function Build_Normal_Requeue
return Node_Id
;
9837 -- N denotes a nondispatching requeue statement to either a task or a
9838 -- protected entry. Build the appropriate runtime call to perform the
9841 function Build_Skip_Statement
(Search
: Node_Id
) return Node_Id
;
9842 -- For a protected entry, create a return statement to skip the rest of
9843 -- the entry body. Otherwise, create a goto statement to skip the rest
9844 -- of a task accept statement. The lookup for the enclosing entry body
9845 -- or accept statement starts from Search.
9847 ---------------------------------------
9848 -- Build_Dispatching_Call_Equivalent --
9849 ---------------------------------------
9851 function Build_Dispatching_Call_Equivalent
return Node_Id
is
9852 Call_Ent
: constant Entity_Id
:= Entity
(Ename
);
9853 Obj
: constant Node_Id
:= Original_Node
(Concval
);
9860 -- Climb the parent chain looking for the inner-most entry body or
9861 -- accept statement.
9864 while Present
(Acc_Ent
)
9865 and then Nkind
(Acc_Ent
) not in N_Accept_Statement | N_Entry_Body
9867 Acc_Ent
:= Parent
(Acc_Ent
);
9870 -- A requeue statement should be housed inside an entry body or an
9871 -- accept statement at some level. If this is not the case, then the
9872 -- tree is malformed.
9874 pragma Assert
(Present
(Acc_Ent
));
9876 -- Recover the list of formal parameters
9878 if Nkind
(Acc_Ent
) = N_Entry_Body
then
9879 Acc_Ent
:= Entry_Body_Formal_Part
(Acc_Ent
);
9882 Formals
:= Parameter_Specifications
(Acc_Ent
);
9884 -- Create the actual parameters for the dispatching call. These are
9885 -- simply copies of the entry body or accept statement formals in the
9886 -- same order as they appear.
9890 if Present
(Formals
) then
9891 Actuals
:= New_List
;
9892 Formal
:= First
(Formals
);
9893 while Present
(Formal
) loop
9895 Make_Identifier
(Loc
, Chars
(Defining_Identifier
(Formal
))));
9901 -- Obj.Call_Ent (Actuals);
9904 Make_Procedure_Call_Statement
(Loc
,
9906 Make_Selected_Component
(Loc
,
9907 Prefix
=> Make_Identifier
(Loc
, Chars
(Obj
)),
9908 Selector_Name
=> Make_Identifier
(Loc
, Chars
(Call_Ent
))),
9910 Parameter_Associations
=> Actuals
);
9911 end Build_Dispatching_Call_Equivalent
;
9913 -------------------------------
9914 -- Build_Dispatching_Requeue --
9915 -------------------------------
9917 function Build_Dispatching_Requeue
return Node_Id
is
9918 Params
: constant List_Id
:= New_List
;
9921 -- Process the "with abort" parameter
9924 New_Occurrence_Of
(Boolean_Literals
(Abort_Present
(N
)), Loc
));
9926 -- Process the entry wrapper's position in the primary dispatch
9927 -- table parameter. Generate:
9929 -- Ada.Tags.Get_Entry_Index
9930 -- (T => To_Tag_Ptr (Obj'Address).all,
9932 -- Ada.Tags.Get_Offset_Index
9933 -- (Ada.Tags.Tag (Concval),
9934 -- <interface dispatch table position of Ename>));
9936 -- Note that Obj'Address is recursively expanded into a call to
9937 -- Base_Address (Obj).
9939 if Tagged_Type_Expansion
then
9941 Make_Function_Call
(Loc
,
9942 Name
=> New_Occurrence_Of
(RTE
(RE_Get_Entry_Index
), Loc
),
9943 Parameter_Associations
=> New_List
(
9945 Make_Explicit_Dereference
(Loc
,
9946 Unchecked_Convert_To
(RTE
(RE_Tag_Ptr
),
9947 Make_Attribute_Reference
(Loc
,
9948 Prefix
=> New_Copy_Tree
(Concval
),
9949 Attribute_Name
=> Name_Address
))),
9951 Make_Function_Call
(Loc
,
9952 Name
=> New_Occurrence_Of
(RTE
(RE_Get_Offset_Index
), Loc
),
9953 Parameter_Associations
=> New_List
(
9954 Unchecked_Convert_To
(RTE
(RE_Tag
), Concval
),
9955 Make_Integer_Literal
(Loc
,
9956 DT_Position
(Entity
(Ename
))))))));
9962 Make_Function_Call
(Loc
,
9963 Name
=> New_Occurrence_Of
(RTE
(RE_Get_Entry_Index
), Loc
),
9964 Parameter_Associations
=> New_List
(
9966 Make_Attribute_Reference
(Loc
,
9968 Attribute_Name
=> Name_Tag
),
9970 Make_Function_Call
(Loc
,
9971 Name
=> New_Occurrence_Of
(RTE
(RE_Get_Offset_Index
), Loc
),
9973 Parameter_Associations
=> New_List
(
9977 Make_Attribute_Reference
(Loc
,
9979 Attribute_Name
=> Name_Tag
),
9983 Make_Attribute_Reference
(Loc
,
9984 Prefix
=> New_Occurrence_Of
(Etype
(Concval
), Loc
),
9985 Attribute_Name
=> Name_Tag
),
9989 Make_Integer_Literal
(Loc
,
9990 DT_Position
(Entity
(Ename
))))))));
9993 -- Specific actuals for protected to XXX requeue
9995 if Is_Protected_Type
(Old_Typ
) then
9997 Make_Attribute_Reference
(Loc
, -- _object'Address
9999 Concurrent_Ref
(New_Occurrence_Of
(Old_Typ
, Loc
)),
10000 Attribute_Name
=> Name_Address
));
10002 Prepend_To
(Params
, -- True
10003 New_Occurrence_Of
(Standard_True
, Loc
));
10005 -- Specific actuals for task to XXX requeue
10008 pragma Assert
(Is_Task_Type
(Old_Typ
));
10010 Prepend_To
(Params
, -- null
10011 New_Occurrence_Of
(RTE
(RE_Null_Address
), Loc
));
10013 Prepend_To
(Params
, -- False
10014 New_Occurrence_Of
(Standard_False
, Loc
));
10017 -- Add the object parameter
10019 Prepend_To
(Params
, New_Copy_Tree
(Concval
));
10022 -- _Disp_Requeue (<Params>);
10024 -- Find entity for Disp_Requeue operation, which belongs to
10025 -- the type and may not be directly visible.
10029 Op
: Entity_Id
:= Empty
;
10032 Elmt
:= First_Elmt
(Primitive_Operations
(Etype
(Conc_Typ
)));
10033 while Present
(Elmt
) loop
10035 exit when Chars
(Op
) = Name_uDisp_Requeue
;
10039 pragma Assert
(Present
(Op
));
10042 Make_Procedure_Call_Statement
(Loc
,
10043 Name
=> New_Occurrence_Of
(Op
, Loc
),
10044 Parameter_Associations
=> Params
);
10046 end Build_Dispatching_Requeue
;
10048 --------------------------------------
10049 -- Build_Dispatching_Requeue_To_Any --
10050 --------------------------------------
10052 function Build_Dispatching_Requeue_To_Any
return Node_Id
is
10053 Call_Ent
: constant Entity_Id
:= Entity
(Ename
);
10054 Obj
: constant Node_Id
:= Original_Node
(Concval
);
10055 Skip
: constant Node_Id
:= Build_Skip_Statement
(N
);
10065 -- Dispatch table slot processing, generate:
10068 S
:= Build_S
(Loc
, Decls
);
10070 -- Call kind processing, generate:
10071 -- C : Ada.Tags.Prim_Op_Kind;
10073 C
:= Build_C
(Loc
, Decls
);
10076 -- S := Ada.Tags.Get_Offset_Index
10077 -- (Ada.Tags.Tag (Obj), DT_Position (Call_Ent));
10079 Append_To
(Stmts
, Build_S_Assignment
(Loc
, S
, Obj
, Call_Ent
));
10082 -- _Disp_Get_Prim_Op_Kind (Obj, S, C);
10085 Make_Procedure_Call_Statement
(Loc
,
10087 New_Occurrence_Of
(
10088 Find_Prim_Op
(Etype
(Etype
(Obj
)),
10089 Name_uDisp_Get_Prim_Op_Kind
),
10091 Parameter_Associations
=> New_List
(
10092 New_Copy_Tree
(Obj
),
10093 New_Occurrence_Of
(S
, Loc
),
10094 New_Occurrence_Of
(C
, Loc
))));
10098 -- if C = POK_Protected_Entry
10099 -- or else C = POK_Task_Entry
10102 Make_Implicit_If_Statement
(N
,
10108 New_Occurrence_Of
(C
, Loc
),
10110 New_Occurrence_Of
(RTE
(RE_POK_Protected_Entry
), Loc
)),
10115 New_Occurrence_Of
(C
, Loc
),
10117 New_Occurrence_Of
(RTE
(RE_POK_Task_Entry
), Loc
))),
10119 -- Dispatching requeue equivalent
10121 Then_Statements
=> New_List
(
10122 Build_Dispatching_Requeue
,
10125 -- elsif C = POK_Protected_Procedure then
10127 Elsif_Parts
=> New_List
(
10128 Make_Elsif_Part
(Loc
,
10132 New_Occurrence_Of
(C
, Loc
),
10134 New_Occurrence_Of
(
10135 RTE
(RE_POK_Protected_Procedure
), Loc
)),
10137 -- Dispatching call equivalent
10139 Then_Statements
=> New_List
(
10140 Build_Dispatching_Call_Equivalent
))),
10143 -- raise Program_Error;
10146 Else_Statements
=> New_List
(
10147 Make_Raise_Program_Error
(Loc
,
10148 Reason
=> PE_Explicit_Raise
))));
10150 -- Wrap everything into a block
10153 Make_Block_Statement
(Loc
,
10154 Declarations
=> Decls
,
10155 Handled_Statement_Sequence
=>
10156 Make_Handled_Sequence_Of_Statements
(Loc
,
10157 Statements
=> Stmts
));
10158 end Build_Dispatching_Requeue_To_Any
;
10160 --------------------------
10161 -- Build_Normal_Requeue --
10162 --------------------------
10164 function Build_Normal_Requeue
return Node_Id
is
10165 Params
: constant List_Id
:= New_List
;
10170 -- Process the "with abort" parameter
10172 Prepend_To
(Params
,
10173 New_Occurrence_Of
(Boolean_Literals
(Abort_Present
(N
)), Loc
));
10175 -- Add the index expression to the parameters. It is common among all
10178 Prepend_To
(Params
,
10179 Entry_Index_Expression
(Loc
, Entity
(Ename
), Index
, Conc_Typ
));
10181 if Is_Protected_Type
(Old_Typ
) then
10183 Self_Param
: Node_Id
;
10187 Make_Attribute_Reference
(Loc
,
10189 Concurrent_Ref
(New_Occurrence_Of
(Old_Typ
, Loc
)),
10191 Name_Unchecked_Access
);
10193 -- Protected to protected requeue
10195 if Is_Protected_Type
(Conc_Typ
) then
10197 New_Occurrence_Of
(
10198 RTE
(RE_Requeue_Protected_Entry
), Loc
);
10201 Make_Attribute_Reference
(Loc
,
10203 Concurrent_Ref
(Concval
),
10205 Name_Unchecked_Access
);
10207 -- Protected to task requeue
10209 else pragma Assert
(Is_Task_Type
(Conc_Typ
));
10211 New_Occurrence_Of
(
10212 RTE
(RE_Requeue_Protected_To_Task_Entry
), Loc
);
10214 Param
:= Concurrent_Ref
(Concval
);
10217 Prepend_To
(Params
, Param
);
10218 Prepend_To
(Params
, Self_Param
);
10221 else pragma Assert
(Is_Task_Type
(Old_Typ
));
10223 -- Task to protected requeue
10225 if Is_Protected_Type
(Conc_Typ
) then
10227 New_Occurrence_Of
(
10228 RTE
(RE_Requeue_Task_To_Protected_Entry
), Loc
);
10231 Make_Attribute_Reference
(Loc
,
10233 Concurrent_Ref
(Concval
),
10235 Name_Unchecked_Access
);
10237 -- Task to task requeue
10239 else pragma Assert
(Is_Task_Type
(Conc_Typ
));
10241 New_Occurrence_Of
(RTE
(RE_Requeue_Task_Entry
), Loc
);
10243 Param
:= Concurrent_Ref
(Concval
);
10246 Prepend_To
(Params
, Param
);
10250 Make_Procedure_Call_Statement
(Loc
,
10252 Parameter_Associations
=> Params
);
10253 end Build_Normal_Requeue
;
10255 --------------------------
10256 -- Build_Skip_Statement --
10257 --------------------------
10259 function Build_Skip_Statement
(Search
: Node_Id
) return Node_Id
is
10260 Skip_Stmt
: Node_Id
;
10263 -- Build a return statement to skip the rest of the entire body
10265 if Is_Protected_Type
(Old_Typ
) then
10266 Skip_Stmt
:= Make_Simple_Return_Statement
(Loc
);
10268 -- If the requeue is within a task, find the end label of the
10269 -- enclosing accept statement and create a goto statement to it.
10277 -- Climb the parent chain looking for the enclosing accept
10280 Acc
:= Parent
(Search
);
10281 while Present
(Acc
)
10282 and then Nkind
(Acc
) /= N_Accept_Statement
10284 Acc
:= Parent
(Acc
);
10287 -- The last statement is the second label used for completing
10288 -- the rendezvous the usual way. The label we are looking for
10289 -- is right before it.
10292 Prev
(Last
(Statements
(Handled_Statement_Sequence
(Acc
))));
10294 pragma Assert
(Nkind
(Label
) = N_Label
);
10296 -- Generate a goto statement to skip the rest of the accept
10299 Make_Goto_Statement
(Loc
,
10301 New_Occurrence_Of
(Entity
(Identifier
(Label
)), Loc
));
10305 Set_Analyzed
(Skip_Stmt
);
10308 end Build_Skip_Statement
;
10310 -- Start of processing for Expand_N_Requeue_Statement
10313 -- Extract the components of the entry call
10315 Extract_Entry
(N
, Concval
, Ename
, Index
);
10316 Conc_Typ
:= Etype
(Concval
);
10318 -- Examine the scope stack in order to find nearest enclosing concurrent
10319 -- type. This will constitute our invocation source.
10321 Old_Typ
:= Current_Scope
;
10322 while Present
(Old_Typ
)
10323 and then not Is_Concurrent_Type
(Old_Typ
)
10325 Old_Typ
:= Scope
(Old_Typ
);
10328 -- Obtain the innermost enclosing callable construct for use in
10329 -- generating a dynamic accessibility check.
10331 Enc_Subp
:= Current_Scope
;
10333 if Ekind
(Enc_Subp
) not in Entry_Kind | Subprogram_Kind
then
10334 Enc_Subp
:= Enclosing_Subprogram
(Enc_Subp
);
10337 -- Generate a dynamic accessibility check on the target object
10339 Insert_Before_And_Analyze
(N
,
10340 Make_Raise_Program_Error
(Loc
,
10343 Left_Opnd
=> Accessibility_Level
(Name
(N
), Dynamic_Level
),
10344 Right_Opnd
=> Make_Integer_Literal
(Loc
,
10345 Scope_Depth
(Enc_Subp
))),
10346 Reason
=> PE_Accessibility_Check_Failed
));
10348 -- Ada 2012 (AI05-0030): We have a dispatching requeue of the form
10349 -- Concval.Ename where the type of Concval is class-wide concurrent
10352 if Ada_Version
>= Ada_2012
10353 and then Present
(Concval
)
10354 and then Is_Class_Wide_Type
(Conc_Typ
)
10355 and then Is_Concurrent_Interface
(Conc_Typ
)
10358 Has_Impl
: Boolean := False;
10359 Impl_Kind
: Name_Id
:= No_Name
;
10362 -- Check whether the Ename is flagged by pragma Implemented
10364 if Has_Rep_Pragma
(Entity
(Ename
), Name_Implemented
) then
10366 Impl_Kind
:= Implementation_Kind
(Entity
(Ename
));
10369 -- The procedure_or_entry_NAME is guaranteed to be overridden by
10370 -- an entry. Create a call to predefined primitive _Disp_Requeue.
10372 if Has_Impl
and then Impl_Kind
= Name_By_Entry
then
10373 Rewrite
(N
, Build_Dispatching_Requeue
);
10375 Insert_After
(N
, Build_Skip_Statement
(N
));
10377 -- The procedure_or_entry_NAME is guaranteed to be overridden by
10378 -- a protected procedure. In this case the requeue is transformed
10379 -- into a dispatching call.
10382 and then Impl_Kind
= Name_By_Protected_Procedure
10384 Rewrite
(N
, Build_Dispatching_Call_Equivalent
);
10387 -- The procedure_or_entry_NAME's implementation kind is either
10388 -- By_Any, Optional, or pragma Implemented was not applied at all.
10389 -- In this case a runtime test determines whether Ename denotes an
10390 -- entry or a protected procedure and performs the appropriate
10394 Rewrite
(N
, Build_Dispatching_Requeue_To_Any
);
10399 -- Processing for regular (nondispatching) requeues
10402 Rewrite
(N
, Build_Normal_Requeue
);
10404 Insert_After
(N
, Build_Skip_Statement
(N
));
10406 end Expand_N_Requeue_Statement
;
10408 -------------------------------
10409 -- Expand_N_Selective_Accept --
10410 -------------------------------
10412 procedure Expand_N_Selective_Accept
(N
: Node_Id
) is
10413 Loc
: constant Source_Ptr
:= Sloc
(N
);
10414 Alts
: constant List_Id
:= Select_Alternatives
(N
);
10416 -- Note: in the below declarations a lot of new lists are allocated
10417 -- unconditionally which may well not end up being used. That's not
10418 -- a good idea since it wastes space gratuitously ???
10420 Accept_Case
: List_Id
;
10421 Accept_List
: constant List_Id
:= New_List
;
10424 Alt_List
: constant List_Id
:= New_List
;
10425 Alt_Stats
: List_Id
;
10426 Ann
: Entity_Id
:= Empty
;
10428 Check_Guard
: Boolean := True;
10430 Decls
: constant List_Id
:= New_List
;
10431 Stats
: constant List_Id
:= New_List
;
10432 Body_List
: constant List_Id
:= New_List
;
10433 Trailing_List
: constant List_Id
:= New_List
;
10436 Else_Present
: Boolean := False;
10437 Terminate_Alt
: Node_Id
:= Empty
;
10438 Select_Mode
: Node_Id
;
10440 Delay_Case
: List_Id
;
10441 Delay_Count
: Integer := 0;
10442 Delay_Val
: Entity_Id
;
10443 Delay_Index
: Entity_Id
;
10444 Delay_Min
: Entity_Id
;
10445 Delay_Num
: Pos
:= 1;
10446 Delay_Alt_List
: List_Id
:= New_List
;
10447 Delay_List
: constant List_Id
:= New_List
;
10451 First_Delay
: Boolean := True;
10452 Guard_Open
: Entity_Id
;
10458 Num_Accept
: Nat
:= 0;
10460 Time_Type
: Entity_Id
:= Empty
;
10461 Select_Call
: Node_Id
;
10463 Qnam
: constant Entity_Id
:=
10464 Make_Defining_Identifier
(Loc
, New_External_Name
('S', 0));
10466 Xnam
: constant Entity_Id
:=
10467 Make_Defining_Identifier
(Loc
, New_External_Name
('J', 1));
10469 -----------------------
10470 -- Local subprograms --
10471 -----------------------
10473 function Accept_Or_Raise
return List_Id
;
10474 -- For the rare case where delay alternatives all have guards, and
10475 -- all of them are closed, it is still possible that there were open
10476 -- accept alternatives with no callers. We must reexamine the
10477 -- Accept_List, and execute a selective wait with no else if some
10478 -- accept is open. If none, we raise program_error.
10480 procedure Add_Accept
(Alt
: Node_Id
);
10481 -- Process a single accept statement in a select alternative. Build
10482 -- procedure for body of accept, and add entry to dispatch table with
10483 -- expression for guard, in preparation for call to run time select.
10485 function Make_And_Declare_Label
(Num
: Int
) return Node_Id
;
10486 -- Manufacture a label using Num as a serial number and declare it.
10487 -- The declaration is appended to Decls. The label marks the trailing
10488 -- statements of an accept or delay alternative.
10490 function Make_Select_Call
(Select_Mode
: Entity_Id
) return Node_Id
;
10491 -- Build call to Selective_Wait runtime routine
10493 procedure Process_Delay_Alternative
(Alt
: Node_Id
; Index
: Int
);
10494 -- Add code to compare value of delay with previous values, and
10495 -- generate case entry for trailing statements.
10497 procedure Process_Accept_Alternative
10501 -- Add code to call corresponding procedure, and branch to
10502 -- trailing statements, if any.
10504 ---------------------
10505 -- Accept_Or_Raise --
10506 ---------------------
10508 function Accept_Or_Raise
return List_Id
is
10511 J
: constant Entity_Id
:= Make_Temporary
(Loc
, 'J');
10514 -- We generate the following:
10516 -- for J in q'range loop
10517 -- if q(J).S /=null_task_entry then
10518 -- selective_wait (simple_mode,...);
10524 -- if no rendez_vous then
10525 -- raise program_error;
10528 -- Note that the code needs to know that the selector name
10529 -- in an Accept_Alternative is named S.
10531 Cond
:= Make_Op_Ne
(Loc
,
10533 Make_Selected_Component
(Loc
,
10535 Make_Indexed_Component
(Loc
,
10536 Prefix
=> New_Occurrence_Of
(Qnam
, Loc
),
10537 Expressions
=> New_List
(New_Occurrence_Of
(J
, Loc
))),
10538 Selector_Name
=> Make_Identifier
(Loc
, Name_S
)),
10540 New_Occurrence_Of
(RTE
(RE_Null_Task_Entry
), Loc
));
10542 Stats
:= New_List
(
10543 Make_Implicit_Loop_Statement
(N
,
10544 Iteration_Scheme
=>
10545 Make_Iteration_Scheme
(Loc
,
10546 Loop_Parameter_Specification
=>
10547 Make_Loop_Parameter_Specification
(Loc
,
10548 Defining_Identifier
=> J
,
10549 Discrete_Subtype_Definition
=>
10550 Make_Attribute_Reference
(Loc
,
10551 Prefix
=> New_Occurrence_Of
(Qnam
, Loc
),
10552 Attribute_Name
=> Name_Range
,
10553 Expressions
=> New_List
(
10554 Make_Integer_Literal
(Loc
, 1))))),
10556 Statements
=> New_List
(
10557 Make_Implicit_If_Statement
(N
,
10559 Then_Statements
=> New_List
(
10561 New_Occurrence_Of
(RTE
(RE_Simple_Mode
), Loc
)),
10562 Make_Exit_Statement
(Loc
))))));
10565 Make_Raise_Program_Error
(Loc
,
10566 Condition
=> Make_Op_Eq
(Loc
,
10567 Left_Opnd
=> New_Occurrence_Of
(Xnam
, Loc
),
10569 New_Occurrence_Of
(RTE
(RE_No_Rendezvous
), Loc
)),
10570 Reason
=> PE_All_Guards_Closed
));
10573 end Accept_Or_Raise
;
10579 procedure Add_Accept
(Alt
: Node_Id
) is
10580 Acc_Stm
: constant Node_Id
:= Accept_Statement
(Alt
);
10581 Ename
: constant Node_Id
:= Entry_Direct_Name
(Acc_Stm
);
10582 Eloc
: constant Source_Ptr
:= Sloc
(Ename
);
10583 Eent
: constant Entity_Id
:= Entity
(Ename
);
10584 Index
: constant Node_Id
:= Entry_Index
(Acc_Stm
);
10588 Null_Body
: Node_Id
;
10589 PB_Ent
: Entity_Id
;
10590 Proc_Body
: Node_Id
;
10592 -- Start of processing for Add_Accept
10596 Ann
:= Node
(Last_Elmt
(Accept_Address
(Eent
)));
10599 if Present
(Condition
(Alt
)) then
10601 Make_If_Expression
(Eloc
, New_List
(
10603 Entry_Index_Expression
(Eloc
, Eent
, Index
, Scope
(Eent
)),
10604 New_Occurrence_Of
(RTE
(RE_Null_Task_Entry
), Eloc
)));
10606 Expr
:= Entry_Index_Expression
(Eloc
, Eent
, Index
, Scope
(Eent
));
10609 if Present
(Handled_Statement_Sequence
(Accept_Statement
(Alt
))) then
10610 Null_Body
:= New_Occurrence_Of
(Standard_False
, Eloc
);
10612 -- Always add call to Abort_Undefer when generating code, since
10613 -- this is what the runtime expects (abort deferred in
10614 -- Selective_Wait). In CodePeer mode this only confuses the
10615 -- analysis with unknown calls, so don't do it.
10617 if not CodePeer_Mode
then
10618 Call
:= Build_Runtime_Call
(Loc
, RE_Abort_Undefer
);
10620 (First
(Statements
(Handled_Statement_Sequence
10621 (Accept_Statement
(Alt
)))),
10627 Make_Defining_Identifier
(Eloc
,
10628 New_External_Name
(Chars
(Ename
), 'A', Num_Accept
));
10630 -- Link the acceptor to the original receiving entry
10632 Mutate_Ekind
(PB_Ent
, E_Procedure
);
10633 Set_Receiving_Entry
(PB_Ent
, Eent
);
10635 if Comes_From_Source
(Alt
) then
10636 Set_Debug_Info_Needed
(PB_Ent
);
10640 Make_Subprogram_Body
(Eloc
,
10642 Make_Procedure_Specification
(Eloc
,
10643 Defining_Unit_Name
=> PB_Ent
),
10644 Declarations
=> Declarations
(Acc_Stm
),
10645 Handled_Statement_Sequence
=>
10646 Build_Accept_Body
(Accept_Statement
(Alt
)));
10648 Reset_Scopes_To
(Proc_Body
, PB_Ent
);
10650 -- During the analysis of the body of the accept statement, any
10651 -- zero cost exception handler records were collected in the
10652 -- Accept_Handler_Records field of the N_Accept_Alternative node.
10653 -- This is where we move them to where they belong, namely the
10654 -- newly created procedure.
10656 Set_Handler_Records
(PB_Ent
, Accept_Handler_Records
(Alt
));
10657 Append
(Proc_Body
, Body_List
);
10660 Null_Body
:= New_Occurrence_Of
(Standard_True
, Eloc
);
10662 -- if accept statement has declarations, insert above, given that
10663 -- we are not creating a body for the accept.
10665 if Present
(Declarations
(Acc_Stm
)) then
10666 Insert_Actions
(N
, Declarations
(Acc_Stm
));
10670 Append_To
(Accept_List
,
10671 Make_Aggregate
(Eloc
, Expressions
=> New_List
(Null_Body
, Expr
)));
10673 Num_Accept
:= Num_Accept
+ 1;
10676 ----------------------------
10677 -- Make_And_Declare_Label --
10678 ----------------------------
10680 function Make_And_Declare_Label
(Num
: Int
) return Node_Id
is
10684 Lab_Id
:= Make_Identifier
(Loc
, New_External_Name
('L', Num
));
10686 Make_Label
(Loc
, Lab_Id
);
10689 Make_Implicit_Label_Declaration
(Loc
,
10690 Defining_Identifier
=>
10691 Make_Defining_Identifier
(Loc
, Chars
(Lab_Id
)),
10692 Label_Construct
=> Lab
));
10695 end Make_And_Declare_Label
;
10697 ----------------------
10698 -- Make_Select_Call --
10699 ----------------------
10701 function Make_Select_Call
(Select_Mode
: Entity_Id
) return Node_Id
is
10702 Params
: constant List_Id
:= New_List
;
10706 Make_Attribute_Reference
(Loc
,
10707 Prefix
=> New_Occurrence_Of
(Qnam
, Loc
),
10708 Attribute_Name
=> Name_Unchecked_Access
));
10709 Append_To
(Params
, Select_Mode
);
10710 Append_To
(Params
, New_Occurrence_Of
(Ann
, Loc
));
10711 Append_To
(Params
, New_Occurrence_Of
(Xnam
, Loc
));
10714 Make_Procedure_Call_Statement
(Loc
,
10715 Name
=> New_Occurrence_Of
(RTE
(RE_Selective_Wait
), Loc
),
10716 Parameter_Associations
=> Params
);
10717 end Make_Select_Call
;
10719 --------------------------------
10720 -- Process_Accept_Alternative --
10721 --------------------------------
10723 procedure Process_Accept_Alternative
10728 Astmt
: constant Node_Id
:= Accept_Statement
(Alt
);
10729 Alt_Stats
: List_Id
;
10732 Adjust_Condition
(Condition
(Alt
));
10734 -- Accept with body
10736 if Present
(Handled_Statement_Sequence
(Astmt
)) then
10739 Make_Procedure_Call_Statement
(Sloc
(Proc
),
10742 (Defining_Unit_Name
(Specification
(Proc
)),
10745 -- Accept with no body (followed by trailing statements)
10749 Entry_Id
: constant Entity_Id
:=
10750 Entity
(Entry_Direct_Name
(Accept_Statement
(Alt
)));
10752 -- Ada 2022 (AI12-0279)
10754 if Has_Yield_Aspect
(Entry_Id
)
10755 and then RTE_Available
(RE_Yield
)
10759 Make_Procedure_Call_Statement
(Sloc
(Proc
),
10760 New_Occurrence_Of
(RTE
(RE_Yield
), Sloc
(Proc
))));
10762 Alt_Stats
:= Empty_List
;
10767 Ensure_Statement_Present
(Sloc
(Astmt
), Alt
);
10769 -- After the call, if any, branch to trailing statements, if any.
10770 -- We create a label for each, as well as the corresponding label
10773 if not Is_Empty_List
(Statements
(Alt
)) then
10774 Lab
:= Make_And_Declare_Label
(Index
);
10775 Append
(Lab
, Trailing_List
);
10776 Append_List
(Statements
(Alt
), Trailing_List
);
10777 Append_To
(Trailing_List
,
10778 Make_Goto_Statement
(Loc
,
10779 Name
=> New_Copy
(Identifier
(End_Lab
))));
10785 Append_To
(Alt_Stats
,
10786 Make_Goto_Statement
(Loc
, Name
=> New_Copy
(Identifier
(Lab
))));
10788 Append_To
(Alt_List
,
10789 Make_Case_Statement_Alternative
(Loc
,
10790 Discrete_Choices
=> New_List
(Make_Integer_Literal
(Loc
, Index
)),
10791 Statements
=> Alt_Stats
));
10792 end Process_Accept_Alternative
;
10794 -------------------------------
10795 -- Process_Delay_Alternative --
10796 -------------------------------
10798 procedure Process_Delay_Alternative
(Alt
: Node_Id
; Index
: Int
) is
10799 Dloc
: constant Source_Ptr
:= Sloc
(Delay_Statement
(Alt
));
10801 Delay_Alt
: List_Id
;
10804 -- Deal with C/Fortran boolean as delay condition
10806 Adjust_Condition
(Condition
(Alt
));
10808 -- Determine the smallest specified delay
10810 -- for each delay alternative generate:
10812 -- if guard-expression then
10813 -- Delay_Val := delay-expression;
10814 -- Guard_Open := True;
10815 -- if Delay_Val < Delay_Min then
10816 -- Delay_Min := Delay_Val;
10817 -- Delay_Index := Index;
10821 -- The enclosing if-statement is omitted if there is no guard
10823 if Delay_Count
= 1 or else First_Delay
then
10824 First_Delay
:= False;
10826 Delay_Alt
:= New_List
(
10827 Make_Assignment_Statement
(Loc
,
10828 Name
=> New_Occurrence_Of
(Delay_Min
, Loc
),
10829 Expression
=> Expression
(Delay_Statement
(Alt
))));
10831 if Delay_Count
> 1 then
10832 Append_To
(Delay_Alt
,
10833 Make_Assignment_Statement
(Loc
,
10834 Name
=> New_Occurrence_Of
(Delay_Index
, Loc
),
10835 Expression
=> Make_Integer_Literal
(Loc
, Index
)));
10839 Delay_Alt
:= New_List
(
10840 Make_Assignment_Statement
(Loc
,
10841 Name
=> New_Occurrence_Of
(Delay_Val
, Loc
),
10842 Expression
=> Expression
(Delay_Statement
(Alt
))));
10844 if Time_Type
= Standard_Duration
then
10847 Left_Opnd
=> New_Occurrence_Of
(Delay_Val
, Loc
),
10848 Right_Opnd
=> New_Occurrence_Of
(Delay_Min
, Loc
));
10851 -- The scope of the time type must define a comparison
10852 -- operator. The scope itself may not be visible, so we
10853 -- construct a node with entity information to insure that
10854 -- semantic analysis can find the proper operator.
10857 Make_Function_Call
(Loc
,
10858 Name
=> Make_Selected_Component
(Loc
,
10860 New_Occurrence_Of
(Scope
(Time_Type
), Loc
),
10862 Make_Operator_Symbol
(Loc
,
10863 Chars
=> Name_Op_Lt
,
10864 Strval
=> No_String
)),
10865 Parameter_Associations
=>
10867 New_Occurrence_Of
(Delay_Val
, Loc
),
10868 New_Occurrence_Of
(Delay_Min
, Loc
)));
10870 Set_Entity
(Prefix
(Name
(Cond
)), Scope
(Time_Type
));
10873 Append_To
(Delay_Alt
,
10874 Make_Implicit_If_Statement
(N
,
10876 Then_Statements
=> New_List
(
10877 Make_Assignment_Statement
(Loc
,
10878 Name
=> New_Occurrence_Of
(Delay_Min
, Loc
),
10879 Expression
=> New_Occurrence_Of
(Delay_Val
, Loc
)),
10881 Make_Assignment_Statement
(Loc
,
10882 Name
=> New_Occurrence_Of
(Delay_Index
, Loc
),
10883 Expression
=> Make_Integer_Literal
(Loc
, Index
)))));
10886 if Check_Guard
then
10887 Append_To
(Delay_Alt
,
10888 Make_Assignment_Statement
(Loc
,
10889 Name
=> New_Occurrence_Of
(Guard_Open
, Loc
),
10890 Expression
=> New_Occurrence_Of
(Standard_True
, Loc
)));
10893 if Present
(Condition
(Alt
)) then
10894 Delay_Alt
:= New_List
(
10895 Make_Implicit_If_Statement
(N
,
10896 Condition
=> Condition
(Alt
),
10897 Then_Statements
=> Delay_Alt
));
10900 Append_List
(Delay_Alt
, Delay_List
);
10902 Ensure_Statement_Present
(Dloc
, Alt
);
10904 -- If the delay alternative has a statement part, add choice to the
10905 -- case statements for delays.
10907 if not Is_Empty_List
(Statements
(Alt
)) then
10909 if Delay_Count
= 1 then
10910 Append_List
(Statements
(Alt
), Delay_Alt_List
);
10913 Append_To
(Delay_Alt_List
,
10914 Make_Case_Statement_Alternative
(Loc
,
10915 Discrete_Choices
=> New_List
(
10916 Make_Integer_Literal
(Loc
, Index
)),
10917 Statements
=> Statements
(Alt
)));
10920 elsif Delay_Count
= 1 then
10922 -- If the single delay has no trailing statements, add a branch
10923 -- to the exit label to the selective wait.
10925 Delay_Alt_List
:= New_List
(
10926 Make_Goto_Statement
(Loc
,
10927 Name
=> New_Copy
(Identifier
(End_Lab
))));
10930 end Process_Delay_Alternative
;
10932 -- Start of processing for Expand_N_Selective_Accept
10935 Process_Statements_For_Controlled_Objects
(N
);
10937 -- First insert some declarations before the select. The first is:
10941 -- This variable holds the parameters passed to the accept body. This
10942 -- declaration has already been inserted by the time we get here by
10943 -- a call to Expand_Accept_Declarations made from the semantics when
10944 -- processing the first accept statement contained in the select. We
10945 -- can find this entity as Accept_Address (E), where E is any of the
10946 -- entries references by contained accept statements.
10948 -- The first step is to scan the list of Selective_Accept_Statements
10949 -- to find this entity, and also count the number of accepts, and
10950 -- determine if terminated, delay or else is present:
10954 Alt
:= First
(Alts
);
10955 while Present
(Alt
) loop
10956 Process_Statements_For_Controlled_Objects
(Alt
);
10958 if Nkind
(Alt
) = N_Accept_Alternative
then
10961 elsif Nkind
(Alt
) = N_Delay_Alternative
then
10962 Delay_Count
:= Delay_Count
+ 1;
10964 -- If the delays are relative delays, the delay expressions have
10965 -- type Standard_Duration. Otherwise they must have some time type
10966 -- recognized by GNAT.
10968 if Nkind
(Delay_Statement
(Alt
)) = N_Delay_Relative_Statement
then
10969 Time_Type
:= Standard_Duration
;
10971 Time_Type
:= Etype
(Expression
(Delay_Statement
(Alt
)));
10973 if Is_RTE
(Base_Type
(Etype
(Time_Type
)), RO_CA_Time
)
10974 or else Is_RTE
(Base_Type
(Etype
(Time_Type
)), RO_RT_Time
)
10978 -- Move this check to sem???
10980 "& is not a time type (RM 9.6(6))",
10981 Expression
(Delay_Statement
(Alt
)), Time_Type
);
10982 Time_Type
:= Standard_Duration
;
10983 Set_Etype
(Expression
(Delay_Statement
(Alt
)), Any_Type
);
10987 if No
(Condition
(Alt
)) then
10989 -- This guard will always be open
10991 Check_Guard
:= False;
10994 elsif Nkind
(Alt
) = N_Terminate_Alternative
then
10995 Adjust_Condition
(Condition
(Alt
));
10996 Terminate_Alt
:= Alt
;
10999 Num_Alts
:= Num_Alts
+ 1;
11003 Else_Present
:= Present
(Else_Statements
(N
));
11005 -- At the same time (see procedure Add_Accept) we build the accept list:
11007 -- Qnn : Accept_List (1 .. num-select) := (
11008 -- (null-body, entry-index),
11009 -- (null-body, entry-index),
11011 -- (null_body, entry-index));
11013 -- In the above declaration, null-body is True if the corresponding
11014 -- accept has no body, and false otherwise. The entry is either the
11015 -- entry index expression if there is no guard, or if a guard is
11016 -- present, then an if expression of the form:
11018 -- (if guard then entry-index else Null_Task_Entry)
11020 -- If a guard is statically known to be false, the entry can simply
11021 -- be omitted from the accept list.
11024 Make_Object_Declaration
(Loc
,
11025 Defining_Identifier
=> Qnam
,
11026 Object_Definition
=> New_Occurrence_Of
(RTE
(RE_Accept_List
), Loc
),
11027 Aliased_Present
=> True,
11029 Make_Qualified_Expression
(Loc
,
11031 New_Occurrence_Of
(RTE
(RE_Accept_List
), Loc
),
11033 Make_Aggregate
(Loc
, Expressions
=> Accept_List
))));
11035 -- Then we declare the variable that holds the index for the accept
11036 -- that will be selected for service:
11038 -- Xnn : Select_Index;
11041 Make_Object_Declaration
(Loc
,
11042 Defining_Identifier
=> Xnam
,
11043 Object_Definition
=>
11044 New_Occurrence_Of
(RTE
(RE_Select_Index
), Loc
),
11046 New_Occurrence_Of
(RTE
(RE_No_Rendezvous
), Loc
)));
11048 -- After this follow procedure declarations for each accept body
11050 -- procedure Pnn is
11055 -- where the ... are statements from the corresponding procedure body.
11056 -- No parameters are involved, since the parameters are passed via Ann
11057 -- and the parameter references have already been expanded to be direct
11058 -- references to Ann (see Exp_Ch2.Expand_Entry_Parameter). Furthermore,
11059 -- any embedded tasking statements (which would normally be illegal in
11060 -- procedures), have been converted to calls to the tasking runtime so
11061 -- there is no problem in putting them into procedures.
11063 -- The original accept statement has been expanded into a block in
11064 -- the same fashion as for simple accepts (see Build_Accept_Body).
11066 -- Note: we don't really need to build these procedures for the case
11067 -- where no delay statement is present, but it is just as easy to
11068 -- build them unconditionally, and not significantly inefficient,
11069 -- since if they are short they will be inlined anyway.
11071 -- The procedure declarations have been assembled in Body_List
11073 -- If delays are present, we must compute the required delay.
11074 -- We first generate the declarations:
11076 -- Delay_Index : Boolean := 0;
11077 -- Delay_Min : Some_Time_Type.Time;
11078 -- Delay_Val : Some_Time_Type.Time;
11080 -- Delay_Index will be set to the index of the minimum delay, i.e. the
11081 -- active delay that is actually chosen as the basis for the possible
11082 -- delay if an immediate rendez-vous is not possible.
11084 -- In the most common case there is a single delay statement, and this
11085 -- is handled specially.
11087 if Delay_Count
> 0 then
11089 -- Generate the required declarations
11092 Make_Defining_Identifier
(Loc
, New_External_Name
('D', 1));
11094 Make_Defining_Identifier
(Loc
, New_External_Name
('D', 2));
11096 Make_Defining_Identifier
(Loc
, New_External_Name
('D', 3));
11098 pragma Assert
(Present
(Time_Type
));
11101 Make_Object_Declaration
(Loc
,
11102 Defining_Identifier
=> Delay_Val
,
11103 Object_Definition
=> New_Occurrence_Of
(Time_Type
, Loc
)));
11106 Make_Object_Declaration
(Loc
,
11107 Defining_Identifier
=> Delay_Index
,
11108 Object_Definition
=> New_Occurrence_Of
(Standard_Integer
, Loc
),
11109 Expression
=> Make_Integer_Literal
(Loc
, 0)));
11112 Make_Object_Declaration
(Loc
,
11113 Defining_Identifier
=> Delay_Min
,
11114 Object_Definition
=> New_Occurrence_Of
(Time_Type
, Loc
),
11116 Unchecked_Convert_To
(Time_Type
,
11117 Make_Attribute_Reference
(Loc
,
11119 New_Occurrence_Of
(Underlying_Type
(Time_Type
), Loc
),
11120 Attribute_Name
=> Name_Last
))));
11122 -- Create Duration and Delay_Mode objects used for passing a delay
11125 D
:= Make_Temporary
(Loc
, 'D');
11126 M
:= Make_Temporary
(Loc
, 'M');
11132 -- Note that these values are defined in s-osprim.ads and must
11133 -- be kept in sync:
11135 -- Relative : constant := 0;
11136 -- Absolute_Calendar : constant := 1;
11137 -- Absolute_RT : constant := 2;
11139 if Time_Type
= Standard_Duration
then
11140 Discr
:= Make_Integer_Literal
(Loc
, 0);
11142 elsif Is_RTE
(Base_Type
(Etype
(Time_Type
)), RO_CA_Time
) then
11143 Discr
:= Make_Integer_Literal
(Loc
, 1);
11147 (Is_RTE
(Base_Type
(Etype
(Time_Type
)), RO_RT_Time
));
11148 Discr
:= Make_Integer_Literal
(Loc
, 2);
11152 Make_Object_Declaration
(Loc
,
11153 Defining_Identifier
=> D
,
11154 Object_Definition
=>
11155 New_Occurrence_Of
(Standard_Duration
, Loc
)));
11158 Make_Object_Declaration
(Loc
,
11159 Defining_Identifier
=> M
,
11160 Object_Definition
=>
11161 New_Occurrence_Of
(Standard_Integer
, Loc
),
11162 Expression
=> Discr
));
11165 if Check_Guard
then
11167 Make_Defining_Identifier
(Loc
, New_External_Name
('G', 1));
11170 Make_Object_Declaration
(Loc
,
11171 Defining_Identifier
=> Guard_Open
,
11172 Object_Definition
=>
11173 New_Occurrence_Of
(Standard_Boolean
, Loc
),
11175 New_Occurrence_Of
(Standard_False
, Loc
)));
11178 -- Delay_Count is zero, don't need M and D set (suppress warning)
11185 if Present
(Terminate_Alt
) then
11187 -- If the terminate alternative guard is False, use
11188 -- Simple_Mode; otherwise use Terminate_Mode.
11190 if Present
(Condition
(Terminate_Alt
)) then
11191 Select_Mode
:= Make_If_Expression
(Loc
,
11192 New_List
(Condition
(Terminate_Alt
),
11193 New_Occurrence_Of
(RTE
(RE_Terminate_Mode
), Loc
),
11194 New_Occurrence_Of
(RTE
(RE_Simple_Mode
), Loc
)));
11196 Select_Mode
:= New_Occurrence_Of
(RTE
(RE_Terminate_Mode
), Loc
);
11199 elsif Else_Present
or Delay_Count
> 0 then
11200 Select_Mode
:= New_Occurrence_Of
(RTE
(RE_Else_Mode
), Loc
);
11203 Select_Mode
:= New_Occurrence_Of
(RTE
(RE_Simple_Mode
), Loc
);
11206 Select_Call
:= Make_Select_Call
(Select_Mode
);
11207 Append
(Select_Call
, Stats
);
11209 -- Now generate code to act on the result. There is an entry
11210 -- in this case for each accept statement with a non-null body,
11211 -- followed by a branch to the statements that follow the Accept.
11212 -- In the absence of delay alternatives, we generate:
11215 -- when No_Rendezvous => -- omitted if simple mode
11230 -- Lab0: Else_Statements;
11233 -- Lab1: Trailing_Statements1;
11236 -- Lab2: Trailing_Statements2;
11241 -- Generate label for common exit
11243 End_Lab
:= Make_And_Declare_Label
(Num_Alts
+ 1);
11245 -- First entry is the default case, when no rendezvous is possible
11247 Choices
:= New_List
(New_Occurrence_Of
(RTE
(RE_No_Rendezvous
), Loc
));
11249 if Else_Present
then
11251 -- If no rendezvous is possible, the else part is executed
11253 Lab
:= Make_And_Declare_Label
(0);
11254 Alt_Stats
:= New_List
(
11255 Make_Goto_Statement
(Loc
,
11256 Name
=> New_Copy
(Identifier
(Lab
))));
11258 Append
(Lab
, Trailing_List
);
11259 Append_List
(Else_Statements
(N
), Trailing_List
);
11260 Append_To
(Trailing_List
,
11261 Make_Goto_Statement
(Loc
,
11262 Name
=> New_Copy
(Identifier
(End_Lab
))));
11264 Alt_Stats
:= New_List
(
11265 Make_Goto_Statement
(Loc
,
11266 Name
=> New_Copy
(Identifier
(End_Lab
))));
11269 Append_To
(Alt_List
,
11270 Make_Case_Statement_Alternative
(Loc
,
11271 Discrete_Choices
=> Choices
,
11272 Statements
=> Alt_Stats
));
11274 -- We make use of the fact that Accept_Index is an integer type, and
11275 -- generate successive literals for entries for each accept. Only those
11276 -- for which there is a body or trailing statements get a case entry.
11278 Alt
:= First
(Select_Alternatives
(N
));
11279 Proc
:= First
(Body_List
);
11280 while Present
(Alt
) loop
11282 if Nkind
(Alt
) = N_Accept_Alternative
then
11283 Process_Accept_Alternative
(Alt
, Index
, Proc
);
11284 Index
:= Index
+ 1;
11287 (Handled_Statement_Sequence
(Accept_Statement
(Alt
)))
11292 elsif Nkind
(Alt
) = N_Delay_Alternative
then
11293 Process_Delay_Alternative
(Alt
, Delay_Num
);
11294 Delay_Num
:= Delay_Num
+ 1;
11300 -- An others choice is always added to the main case, as well
11301 -- as the delay case (to satisfy the compiler).
11303 Append_To
(Alt_List
,
11304 Make_Case_Statement_Alternative
(Loc
,
11305 Discrete_Choices
=>
11306 New_List
(Make_Others_Choice
(Loc
)),
11308 New_List
(Make_Goto_Statement
(Loc
,
11309 Name
=> New_Copy
(Identifier
(End_Lab
))))));
11311 Accept_Case
:= New_List
(
11312 Make_Case_Statement
(Loc
,
11313 Expression
=> New_Occurrence_Of
(Xnam
, Loc
),
11314 Alternatives
=> Alt_List
));
11316 Append_List
(Trailing_List
, Accept_Case
);
11317 Append_List
(Body_List
, Decls
);
11319 -- Construct case statement for trailing statements of delay
11320 -- alternatives, if there are several of them.
11322 if Delay_Count
> 1 then
11323 Append_To
(Delay_Alt_List
,
11324 Make_Case_Statement_Alternative
(Loc
,
11325 Discrete_Choices
=>
11326 New_List
(Make_Others_Choice
(Loc
)),
11328 New_List
(Make_Null_Statement
(Loc
))));
11330 Delay_Case
:= New_List
(
11331 Make_Case_Statement
(Loc
,
11332 Expression
=> New_Occurrence_Of
(Delay_Index
, Loc
),
11333 Alternatives
=> Delay_Alt_List
));
11335 Delay_Case
:= Delay_Alt_List
;
11338 -- If there are no delay alternatives, we append the case statement
11339 -- to the statement list.
11341 if Delay_Count
= 0 then
11342 Append_List
(Accept_Case
, Stats
);
11344 -- Delay alternatives present
11347 -- If delay alternatives are present we generate:
11349 -- find minimum delay.
11350 -- DX := minimum delay;
11351 -- M := <delay mode>;
11352 -- Timed_Selective_Wait (Q'Unchecked_Access, Delay_Mode, P,
11355 -- if X = No_Rendezvous then
11356 -- case statement for delay statements.
11358 -- case statement for accept alternatives.
11369 -- The type of the delay expression is known to be legal
11371 if Time_Type
= Standard_Duration
then
11372 Conv
:= New_Occurrence_Of
(Delay_Min
, Loc
);
11374 elsif Is_RTE
(Base_Type
(Etype
(Time_Type
)), RO_CA_Time
) then
11375 Conv
:= Make_Function_Call
(Loc
,
11376 New_Occurrence_Of
(RTE
(RO_CA_To_Duration
), Loc
),
11377 New_List
(New_Occurrence_Of
(Delay_Min
, Loc
)));
11381 (Is_RTE
(Base_Type
(Etype
(Time_Type
)), RO_RT_Time
));
11383 Conv
:= Make_Function_Call
(Loc
,
11384 New_Occurrence_Of
(RTE
(RO_RT_To_Duration
), Loc
),
11385 New_List
(New_Occurrence_Of
(Delay_Min
, Loc
)));
11388 Stmt
:= Make_Assignment_Statement
(Loc
,
11389 Name
=> New_Occurrence_Of
(D
, Loc
),
11390 Expression
=> Conv
);
11392 -- Change the value for Accept_Modes. (Else_Mode -> Delay_Mode)
11394 Parms
:= Parameter_Associations
(Select_Call
);
11396 Parm
:= First
(Parms
);
11397 while Present
(Parm
) and then Parm
/= Select_Mode
loop
11401 pragma Assert
(Present
(Parm
));
11402 Rewrite
(Parm
, New_Occurrence_Of
(RTE
(RE_Delay_Mode
), Loc
));
11405 -- Prepare two new parameters of Duration and Delay_Mode type
11406 -- which represent the value and the mode of the minimum delay.
11409 Insert_After
(Parm
, New_Occurrence_Of
(M
, Loc
));
11410 Insert_After
(Parm
, New_Occurrence_Of
(D
, Loc
));
11412 -- Create a call to RTS
11414 Rewrite
(Select_Call
,
11415 Make_Procedure_Call_Statement
(Loc
,
11416 Name
=> New_Occurrence_Of
(RTE
(RE_Timed_Selective_Wait
), Loc
),
11417 Parameter_Associations
=> Parms
));
11419 -- This new call should follow the calculation of the minimum
11422 Insert_List_Before
(Select_Call
, Delay_List
);
11424 if Check_Guard
then
11426 Make_Implicit_If_Statement
(N
,
11427 Condition
=> New_Occurrence_Of
(Guard_Open
, Loc
),
11428 Then_Statements
=> New_List
(
11429 New_Copy_Tree
(Stmt
),
11430 New_Copy_Tree
(Select_Call
)),
11431 Else_Statements
=> Accept_Or_Raise
);
11432 Rewrite
(Select_Call
, Stmt
);
11434 Insert_Before
(Select_Call
, Stmt
);
11438 Make_Implicit_If_Statement
(N
,
11439 Condition
=> Make_Op_Eq
(Loc
,
11440 Left_Opnd
=> New_Occurrence_Of
(Xnam
, Loc
),
11442 New_Occurrence_Of
(RTE
(RE_No_Rendezvous
), Loc
)),
11444 Then_Statements
=> Delay_Case
,
11445 Else_Statements
=> Accept_Case
);
11447 Append
(Cases
, Stats
);
11451 Append
(End_Lab
, Stats
);
11453 -- Replace accept statement with appropriate block
11456 Make_Block_Statement
(Loc
,
11457 Declarations
=> Decls
,
11458 Handled_Statement_Sequence
=>
11459 Make_Handled_Sequence_Of_Statements
(Loc
, Statements
=> Stats
)));
11462 -- Note: have to worry more about abort deferral in above code ???
11464 -- Final step is to unstack the Accept_Address entries for all accept
11465 -- statements appearing in accept alternatives in the select statement
11467 Alt
:= First
(Alts
);
11468 while Present
(Alt
) loop
11469 if Nkind
(Alt
) = N_Accept_Alternative
then
11470 Remove_Last_Elmt
(Accept_Address
11471 (Entity
(Entry_Direct_Name
(Accept_Statement
(Alt
)))));
11476 end Expand_N_Selective_Accept
;
11478 -------------------------------------------
11479 -- Expand_N_Single_Protected_Declaration --
11480 -------------------------------------------
11482 -- A single protected declaration should never be present after semantic
11483 -- analysis because it is transformed into a protected type declaration
11484 -- and an accompanying anonymous object. This routine ensures that the
11485 -- transformation takes place.
11487 procedure Expand_N_Single_Protected_Declaration
(N
: Node_Id
) is
11489 raise Program_Error
;
11490 end Expand_N_Single_Protected_Declaration
;
11492 --------------------------------------
11493 -- Expand_N_Single_Task_Declaration --
11494 --------------------------------------
11496 -- A single task declaration should never be present after semantic
11497 -- analysis because it is transformed into a task type declaration and
11498 -- an accompanying anonymous object. This routine ensures that the
11499 -- transformation takes place.
11501 procedure Expand_N_Single_Task_Declaration
(N
: Node_Id
) is
11503 raise Program_Error
;
11504 end Expand_N_Single_Task_Declaration
;
11506 ------------------------
11507 -- Expand_N_Task_Body --
11508 ------------------------
11510 -- Given a task body
11512 -- task body tname is
11518 -- This expansion routine converts it into a procedure and sets the
11519 -- elaboration flag for the procedure to true, to represent the fact
11520 -- that the task body is now elaborated:
11522 -- procedure tnameB (_Task : access tnameV) is
11523 -- discriminal : dtype renames _Task.discriminant;
11525 -- procedure _clean is
11527 -- Abort_Defer.all;
11529 -- Abort_Undefer.all;
11534 -- Abort_Undefer.all;
11536 -- System.Task_Stages.Complete_Activation;
11544 -- In addition, if the task body is an activator, then a call to activate
11545 -- tasks is added at the start of the statements, before the call to
11546 -- Complete_Activation, and if in addition the task is a master then it
11547 -- must be established as a master. These calls are inserted and analyzed
11548 -- in Expand_Cleanup_Actions, when the Handled_Sequence_Of_Statements is
11551 -- There is one discriminal declaration line generated for each
11552 -- discriminant that is present to provide an easy reference point for
11553 -- discriminant references inside the body (see Exp_Ch2.Expand_Name).
11555 -- Note on relationship to GNARLI definition. In the GNARLI definition,
11556 -- task body procedures have a profile (Arg : System.Address). That is
11557 -- needed because GNARLI has to use the same access-to-subprogram type
11558 -- for all task types. We depend here on knowing that in GNAT, passing
11559 -- an address argument by value is identical to passing a record value
11560 -- by access (in either case a single pointer is passed), so even though
11561 -- this procedure has the wrong profile. In fact it's all OK, since the
11562 -- callings sequence is identical.
11564 procedure Expand_N_Task_Body
(N
: Node_Id
) is
11565 Loc
: constant Source_Ptr
:= Sloc
(N
);
11566 Ttyp
: constant Entity_Id
:= Corresponding_Spec
(N
);
11570 Insert_Nod
: Node_Id
;
11571 -- Used to determine the proper location of wrapper body insertions
11574 -- if no task body procedure, means we had an error in configurable
11575 -- run-time mode, and there is no point in proceeding further.
11577 if No
(Task_Body_Procedure
(Ttyp
)) then
11581 -- Add renaming declarations for discriminals and a declaration for the
11582 -- entry family index (if applicable).
11584 Install_Private_Data_Declarations
11585 (Loc
, Task_Body_Procedure
(Ttyp
), Ttyp
, N
, Declarations
(N
));
11587 -- Add a call to Abort_Undefer at the very beginning of the task
11588 -- body since this body is called with abort still deferred.
11590 if Abort_Allowed
then
11591 Call
:= Build_Runtime_Call
(Loc
, RE_Abort_Undefer
);
11592 Prepend
(Call
, Declarations
(N
));
11596 -- Place call to Complete_Activation at the head of the statement list.
11598 if Restricted_Profile
then
11599 Call
:= Build_Runtime_Call
(Loc
, RE_Complete_Restricted_Activation
);
11601 Call
:= Build_Runtime_Call
(Loc
, RE_Complete_Activation
);
11605 (First
(Statements
(Handled_Statement_Sequence
(N
))), Call
);
11609 Make_Subprogram_Body
(Loc
,
11610 Specification
=> Build_Task_Proc_Specification
(Ttyp
),
11611 Declarations
=> Declarations
(N
),
11612 Handled_Statement_Sequence
=> Handled_Statement_Sequence
(N
));
11613 Set_Is_Task_Body_Procedure
(New_N
);
11614 Set_At_End_Proc
(New_N
, At_End_Proc
(N
));
11616 -- If the task contains generic instantiations, cleanup actions are
11617 -- delayed until after instantiation. Transfer the activation chain to
11618 -- the subprogram, to insure that the activation call is properly
11619 -- generated. It the task body contains inner tasks, indicate that the
11620 -- subprogram is a task master.
11622 if Delay_Cleanups
(Ttyp
) then
11623 Set_Activation_Chain_Entity
(New_N
, Activation_Chain_Entity
(N
));
11624 Set_Is_Task_Master
(New_N
, Is_Task_Master
(N
));
11627 Rewrite
(N
, New_N
);
11630 -- Set elaboration flag immediately after task body. If the body is a
11631 -- subunit, the flag is set in the declarative part containing the stub.
11633 if Nkind
(Parent
(N
)) /= N_Subunit
then
11635 Make_Assignment_Statement
(Loc
,
11637 Make_Identifier
(Loc
, New_External_Name
(Chars
(Ttyp
), 'E')),
11638 Expression
=> New_Occurrence_Of
(Standard_True
, Loc
)));
11641 -- Ada 2005 (AI-345): Construct the primitive entry wrapper bodies after
11642 -- the task body. At this point all wrapper specs have been created,
11643 -- frozen and included in the dispatch table for the task type.
11645 if Ada_Version
>= Ada_2005
then
11646 if Nkind
(Parent
(N
)) = N_Subunit
then
11647 Insert_Nod
:= Corresponding_Stub
(Parent
(N
));
11652 Build_Wrapper_Bodies
(Loc
, Ttyp
, Insert_Nod
);
11654 end Expand_N_Task_Body
;
11656 ------------------------------------
11657 -- Expand_N_Task_Type_Declaration --
11658 ------------------------------------
11660 -- We have several things to do. First we must create a Boolean flag used
11661 -- to mark if the body is elaborated yet. This variable gets set to True
11662 -- when the body of the task is elaborated (we can't rely on the normal
11663 -- ABE mechanism for the task body, since we need to pass an access to
11664 -- this elaboration boolean to the runtime routines).
11666 -- taskE : aliased Boolean := False;
11668 -- Next a variable is declared to hold the task stack size (either the
11669 -- default : Unspecified_Size, or a value that is set by a pragma
11670 -- Storage_Size). If the value of the pragma Storage_Size is static, then
11671 -- the variable is initialized with this value:
11673 -- taskZ : Size_Type := Unspecified_Size;
11675 -- taskZ : Size_Type := Size_Type (size_expression);
11677 -- Note: No variable is needed to hold the task relative deadline since
11678 -- its value would never be static because the parameter is of a private
11679 -- type (Ada.Real_Time.Time_Span).
11681 -- Next we create a corresponding record type declaration used to represent
11682 -- values of this task. The general form of this type declaration is
11684 -- type taskV (discriminants) is record
11685 -- _Task_Id : Task_Id;
11686 -- entry_family : array (bounds) of Void;
11687 -- _Priority : Integer := priority_expression;
11688 -- _Size : Size_Type := size_expression;
11689 -- _Secondary_Stack_Size : Size_Type := size_expression;
11690 -- _Task_Info : Task_Info_Type := task_info_expression;
11691 -- _CPU : Integer := cpu_range_expression;
11692 -- _Relative_Deadline : Time_Span := time_span_expression;
11693 -- _Domain : Dispatching_Domain := dd_expression;
11696 -- The discriminants are present only if the corresponding task type has
11697 -- discriminants, and they exactly mirror the task type discriminants.
11699 -- The Id field is always present. It contains the Task_Id value, as set by
11700 -- the call to Create_Task. Note that although the task is limited, the
11701 -- task value record type is not limited, so there is no problem in passing
11702 -- this field as an out parameter to Create_Task.
11704 -- One entry_family component is present for each entry family in the task
11705 -- definition. The bounds correspond to the bounds of the entry family
11706 -- (which may depend on discriminants). The element type is void, since we
11707 -- only need the bounds information for determining the entry index. Note
11708 -- that the use of an anonymous array would normally be illegal in this
11709 -- context, but this is a parser check, and the semantics is quite prepared
11710 -- to handle such a case.
11712 -- The _Size field is present only if a Storage_Size pragma appears in the
11713 -- task definition. The expression captures the argument that was present
11714 -- in the pragma, and is used to override the task stack size otherwise
11715 -- associated with the task type.
11717 -- The _Secondary_Stack_Size field is present only the task entity has a
11718 -- Secondary_Stack_Size rep item. It will be filled at the freeze point,
11719 -- when the record init proc is built, to capture the expression of the
11720 -- rep item (see Build_Record_Init_Proc in Exp_Ch3). Note that it cannot
11721 -- be filled here since aspect evaluations are delayed till the freeze
11724 -- The _Priority field is present only if the task entity has a Priority or
11725 -- Interrupt_Priority rep item (pragma, aspect specification or attribute
11726 -- definition clause). It will be filled at the freeze point, when the
11727 -- record init proc is built, to capture the expression of the rep item
11728 -- (see Build_Record_Init_Proc in Exp_Ch3). Note that it cannot be filled
11729 -- here since aspect evaluations are delayed till the freeze point.
11731 -- The _Task_Info field is present only if a Task_Info pragma appears in
11732 -- the task definition. The expression captures the argument that was
11733 -- present in the pragma, and is used to provide the Task_Image parameter
11734 -- to the call to Create_Task.
11736 -- The _CPU field is present only if the task entity has a CPU rep item
11737 -- (pragma, aspect specification or attribute definition clause). It will
11738 -- be filled at the freeze point, when the record init proc is built, to
11739 -- capture the expression of the rep item (see Build_Record_Init_Proc in
11740 -- Exp_Ch3). Note that it cannot be filled here since aspect evaluations
11741 -- are delayed till the freeze point.
11743 -- The _Relative_Deadline field is present only if a Relative_Deadline
11744 -- pragma appears in the task definition. The expression captures the
11745 -- argument that was present in the pragma, and is used to provide the
11746 -- Relative_Deadline parameter to the call to Create_Task.
11748 -- The _Domain field is present only if the task entity has a
11749 -- Dispatching_Domain rep item (pragma, aspect specification or attribute
11750 -- definition clause). It will be filled at the freeze point, when the
11751 -- record init proc is built, to capture the expression of the rep item
11752 -- (see Build_Record_Init_Proc in Exp_Ch3). Note that it cannot be filled
11753 -- here since aspect evaluations are delayed till the freeze point.
11755 -- When a task is declared, an instance of the task value record is
11756 -- created. The elaboration of this declaration creates the correct bounds
11757 -- for the entry families, and also evaluates the size, priority, and
11758 -- task_Info expressions if needed. The initialization routine for the task
11759 -- type itself then calls Create_Task with appropriate parameters to
11760 -- initialize the value of the Task_Id field.
11762 -- Note: the address of this record is passed as the "Discriminants"
11763 -- parameter for Create_Task. Since Create_Task merely passes this onto the
11764 -- body procedure, it does not matter that it does not quite match the
11765 -- GNARLI model of what is being passed (the record contains more than just
11766 -- the discriminants, but the discriminants can be found from the record
11769 -- The Entity_Id for this created record type is placed in the
11770 -- Corresponding_Record_Type field of the associated task type entity.
11772 -- Next we create a procedure specification for the task body procedure:
11774 -- procedure taskB (_Task : access taskV);
11776 -- Note that this must come after the record type declaration, since
11777 -- the spec refers to this type. It turns out that the initialization
11778 -- procedure for the value type references the task body spec, but that's
11779 -- fine, since it won't be generated till the freeze point for the type,
11780 -- which is certainly after the task body spec declaration.
11782 -- Finally, we set the task index value field of the entry attribute in
11783 -- the case of a simple entry.
11785 procedure Expand_N_Task_Type_Declaration
(N
: Node_Id
) is
11786 Loc
: constant Source_Ptr
:= Sloc
(N
);
11787 TaskId
: constant Entity_Id
:= Defining_Identifier
(N
);
11788 Tasktyp
: constant Entity_Id
:= Etype
(Defining_Identifier
(N
));
11789 Tasknm
: constant Name_Id
:= Chars
(Tasktyp
);
11790 Taskdef
: constant Node_Id
:= Task_Definition
(N
);
11792 Body_Decl
: Node_Id
;
11794 Decl_Stack
: Node_Id
;
11796 Elab_Decl
: Node_Id
;
11797 Ent_Stack
: Entity_Id
;
11798 Proc_Spec
: Node_Id
;
11799 Rec_Decl
: Node_Id
;
11800 Rec_Ent
: Entity_Id
;
11801 Size_Decl
: Entity_Id
;
11802 Task_Size
: Node_Id
;
11804 function Get_Relative_Deadline_Pragma
(T
: Node_Id
) return Node_Id
;
11805 -- Searches the task definition T for the first occurrence of the pragma
11806 -- Relative Deadline. The caller has ensured that the pragma is present
11807 -- in the task definition. Note that this routine cannot be implemented
11808 -- with the Rep Item chain mechanism since Relative_Deadline pragmas are
11809 -- not chained because their expansion into a procedure call statement
11810 -- would cause a break in the chain.
11812 ----------------------------------
11813 -- Get_Relative_Deadline_Pragma --
11814 ----------------------------------
11816 function Get_Relative_Deadline_Pragma
(T
: Node_Id
) return Node_Id
is
11820 N
:= First
(Visible_Declarations
(T
));
11821 while Present
(N
) loop
11822 if Nkind
(N
) = N_Pragma
11823 and then Pragma_Name
(N
) = Name_Relative_Deadline
11831 N
:= First
(Private_Declarations
(T
));
11832 while Present
(N
) loop
11833 if Nkind
(N
) = N_Pragma
11834 and then Pragma_Name
(N
) = Name_Relative_Deadline
11842 raise Program_Error
;
11843 end Get_Relative_Deadline_Pragma
;
11845 -- Start of processing for Expand_N_Task_Type_Declaration
11848 -- If already expanded, nothing to do
11850 if Present
(Corresponding_Record_Type
(Tasktyp
)) then
11854 -- Here we will do the expansion
11856 Rec_Decl
:= Build_Corresponding_Record
(N
, Tasktyp
, Loc
);
11858 Rec_Ent
:= Defining_Identifier
(Rec_Decl
);
11859 Cdecls
:= Component_Items
(Component_List
11860 (Type_Definition
(Rec_Decl
)));
11862 Qualify_Entity_Names
(N
);
11864 -- First create the elaboration variable
11867 Make_Object_Declaration
(Loc
,
11868 Defining_Identifier
=>
11869 Make_Defining_Identifier
(Sloc
(Tasktyp
),
11870 Chars
=> New_External_Name
(Tasknm
, 'E')),
11871 Aliased_Present
=> True,
11872 Object_Definition
=> New_Occurrence_Of
(Standard_Boolean
, Loc
),
11873 Expression
=> New_Occurrence_Of
(Standard_False
, Loc
));
11875 Insert_After
(N
, Elab_Decl
);
11877 -- Next create the declaration of the size variable (tasknmZ)
11879 Set_Storage_Size_Variable
(Tasktyp
,
11880 Make_Defining_Identifier
(Sloc
(Tasktyp
),
11881 Chars
=> New_External_Name
(Tasknm
, 'Z')));
11883 if Present
(Taskdef
)
11884 and then Has_Storage_Size_Pragma
(Taskdef
)
11886 Is_OK_Static_Expression
11888 (First
(Pragma_Argument_Associations
11889 (Get_Rep_Pragma
(TaskId
, Name_Storage_Size
)))))
11892 Make_Object_Declaration
(Loc
,
11893 Defining_Identifier
=> Storage_Size_Variable
(Tasktyp
),
11894 Object_Definition
=>
11895 New_Occurrence_Of
(RTE
(RE_Size_Type
), Loc
),
11897 Convert_To
(RTE
(RE_Size_Type
),
11899 (Expression
(First
(Pragma_Argument_Associations
11901 (TaskId
, Name_Storage_Size
)))))));
11905 Make_Object_Declaration
(Loc
,
11906 Defining_Identifier
=> Storage_Size_Variable
(Tasktyp
),
11907 Object_Definition
=>
11908 New_Occurrence_Of
(RTE
(RE_Size_Type
), Loc
),
11910 New_Occurrence_Of
(RTE
(RE_Unspecified_Size
), Loc
));
11913 Insert_After
(Elab_Decl
, Size_Decl
);
11915 -- Next build the rest of the corresponding record declaration. This is
11916 -- done last, since the corresponding record initialization procedure
11917 -- will reference the previously created entities.
11919 -- Fill in the component declarations -- first the _Task_Id field
11922 Make_Component_Declaration
(Loc
,
11923 Defining_Identifier
=>
11924 Make_Defining_Identifier
(Loc
, Name_uTask_Id
),
11925 Component_Definition
=>
11926 Make_Component_Definition
(Loc
,
11927 Aliased_Present
=> False,
11928 Subtype_Indication
=> New_Occurrence_Of
(RTE
(RO_ST_Task_Id
),
11931 -- Declare static ATCB (that is, created by the expander) if we are
11932 -- using the Restricted run time.
11934 if Restricted_Profile
then
11936 Make_Component_Declaration
(Loc
,
11937 Defining_Identifier
=>
11938 Make_Defining_Identifier
(Loc
, Name_uATCB
),
11940 Component_Definition
=>
11941 Make_Component_Definition
(Loc
,
11942 Aliased_Present
=> True,
11943 Subtype_Indication
=> Make_Subtype_Indication
(Loc
,
11945 New_Occurrence_Of
(RTE
(RE_Ada_Task_Control_Block
), Loc
),
11948 Make_Index_Or_Discriminant_Constraint
(Loc
,
11950 New_List
(Make_Integer_Literal
(Loc
, 0)))))));
11954 -- Declare static stack (that is, created by the expander) if we are
11955 -- using the Restricted run time on a bare board configuration.
11957 if Restricted_Profile
and then Preallocated_Stacks_On_Target
then
11959 -- First we need to extract the appropriate stack size
11961 Ent_Stack
:= Make_Defining_Identifier
(Loc
, Name_uStack
);
11963 if Present
(Taskdef
) and then Has_Storage_Size_Pragma
(Taskdef
) then
11965 Expr_N
: constant Node_Id
:=
11966 Expression
(First
(
11967 Pragma_Argument_Associations
(
11968 Get_Rep_Pragma
(TaskId
, Name_Storage_Size
))));
11969 Etyp
: constant Entity_Id
:= Etype
(Expr_N
);
11970 P
: constant Node_Id
:= Parent
(Expr_N
);
11973 -- The stack is defined inside the corresponding record.
11974 -- Therefore if the size of the stack is set by means of
11975 -- a discriminant, we must reference the discriminant of the
11976 -- corresponding record type.
11978 if Nkind
(Expr_N
) in N_Has_Entity
11979 and then Present
(Discriminal_Link
(Entity
(Expr_N
)))
11983 (CR_Discriminant
(Discriminal_Link
(Entity
(Expr_N
))),
11985 Set_Parent
(Task_Size
, P
);
11986 Set_Etype
(Task_Size
, Etyp
);
11987 Set_Analyzed
(Task_Size
);
11990 Task_Size
:= New_Copy_Tree
(Expr_N
);
11996 New_Occurrence_Of
(RTE
(RE_Default_Stack_Size
), Loc
);
11999 Decl_Stack
:= Make_Component_Declaration
(Loc
,
12000 Defining_Identifier
=> Ent_Stack
,
12002 Component_Definition
=>
12003 Make_Component_Definition
(Loc
,
12004 Aliased_Present
=> True,
12005 Subtype_Indication
=> Make_Subtype_Indication
(Loc
,
12007 New_Occurrence_Of
(RTE
(RE_Storage_Array
), Loc
),
12010 Make_Index_Or_Discriminant_Constraint
(Loc
,
12011 Constraints
=> New_List
(Make_Range
(Loc
,
12012 Low_Bound
=> Make_Integer_Literal
(Loc
, 1),
12013 High_Bound
=> Convert_To
(RTE
(RE_Storage_Offset
),
12016 Append_To
(Cdecls
, Decl_Stack
);
12018 -- The appropriate alignment for the stack is ensured by the run-time
12019 -- code in charge of task creation.
12023 -- Declare a static secondary stack if the conditions for a statically
12024 -- generated stack are met.
12026 if Create_Secondary_Stack_For_Task
(TaskId
) then
12028 Size_Expr
: constant Node_Id
:=
12029 Expression
(First
(
12030 Pragma_Argument_Associations
(
12031 Get_Rep_Pragma
(TaskId
,
12032 Name_Secondary_Stack_Size
))));
12034 Stack_Size
: Node_Id
;
12037 -- The secondary stack is defined inside the corresponding
12038 -- record. Therefore if the size of the stack is set by means
12039 -- of a discriminant, we must reference the discriminant of the
12040 -- corresponding record type.
12042 if Nkind
(Size_Expr
) in N_Has_Entity
12043 and then Present
(Discriminal_Link
(Entity
(Size_Expr
)))
12047 (CR_Discriminant
(Discriminal_Link
(Entity
(Size_Expr
))),
12049 Set_Parent
(Stack_Size
, Parent
(Size_Expr
));
12050 Set_Etype
(Stack_Size
, Etype
(Size_Expr
));
12051 Set_Analyzed
(Stack_Size
);
12054 Stack_Size
:= New_Copy_Tree
(Size_Expr
);
12057 -- Create the secondary stack for the task
12060 Make_Component_Declaration
(Loc
,
12061 Defining_Identifier
=>
12062 Make_Defining_Identifier
(Loc
, Name_uSecondary_Stack
),
12063 Component_Definition
=>
12064 Make_Component_Definition
(Loc
,
12065 Aliased_Present
=> True,
12066 Subtype_Indication
=>
12067 Make_Subtype_Indication
(Loc
,
12069 New_Occurrence_Of
(RTE
(RE_SS_Stack
), Loc
),
12071 Make_Index_Or_Discriminant_Constraint
(Loc
,
12072 Constraints
=> New_List
(
12073 Convert_To
(RTE
(RE_Size_Type
),
12076 Append_To
(Cdecls
, Decl_SS
);
12080 -- Add components for entry families
12082 Collect_Entry_Families
(Loc
, Cdecls
, Size_Decl
, Tasktyp
);
12084 -- Add the _Priority component if a Interrupt_Priority or Priority rep
12085 -- item is present.
12087 if Has_Rep_Item
(TaskId
, Name_Priority
, Check_Parents
=> False) then
12089 Make_Component_Declaration
(Loc
,
12090 Defining_Identifier
=>
12091 Make_Defining_Identifier
(Loc
, Name_uPriority
),
12092 Component_Definition
=>
12093 Make_Component_Definition
(Loc
,
12094 Aliased_Present
=> False,
12095 Subtype_Indication
=>
12096 New_Occurrence_Of
(Standard_Integer
, Loc
))));
12099 -- Add the _Size component if a Storage_Size pragma is present
12101 if Present
(Taskdef
) and then Has_Storage_Size_Pragma
(Taskdef
) then
12103 Make_Component_Declaration
(Loc
,
12104 Defining_Identifier
=>
12105 Make_Defining_Identifier
(Loc
, Name_uSize
),
12107 Component_Definition
=>
12108 Make_Component_Definition
(Loc
,
12109 Aliased_Present
=> False,
12110 Subtype_Indication
=>
12111 New_Occurrence_Of
(RTE
(RE_Size_Type
), Loc
)),
12114 Convert_To
(RTE
(RE_Size_Type
),
12116 Expression
(First
(
12117 Pragma_Argument_Associations
(
12118 Get_Rep_Pragma
(TaskId
, Name_Storage_Size
))))))));
12121 -- Add the _Secondary_Stack_Size component if a Secondary_Stack_Size
12122 -- pragma is present.
12125 (TaskId
, Name_Secondary_Stack_Size
, Check_Parents
=> False)
12128 Make_Component_Declaration
(Loc
,
12129 Defining_Identifier
=>
12130 Make_Defining_Identifier
(Loc
, Name_uSecondary_Stack_Size
),
12132 Component_Definition
=>
12133 Make_Component_Definition
(Loc
,
12134 Aliased_Present
=> False,
12135 Subtype_Indication
=>
12136 New_Occurrence_Of
(RTE
(RE_Size_Type
), Loc
))));
12139 -- Add the _Task_Info component if a Task_Info pragma is present
12141 if Has_Rep_Pragma
(TaskId
, Name_Task_Info
, Check_Parents
=> False) then
12143 Make_Component_Declaration
(Loc
,
12144 Defining_Identifier
=>
12145 Make_Defining_Identifier
(Loc
, Name_uTask_Info
),
12147 Component_Definition
=>
12148 Make_Component_Definition
(Loc
,
12149 Aliased_Present
=> False,
12150 Subtype_Indication
=>
12151 New_Occurrence_Of
(RTE
(RE_Task_Info_Type
), Loc
)),
12153 Expression
=> New_Copy
(
12154 Expression
(First
(
12155 Pragma_Argument_Associations
(
12157 (TaskId
, Name_Task_Info
, Check_Parents
=> False)))))));
12160 -- Add the _CPU component if a CPU rep item is present
12162 if Has_Rep_Item
(TaskId
, Name_CPU
, Check_Parents
=> False) then
12164 Make_Component_Declaration
(Loc
,
12165 Defining_Identifier
=>
12166 Make_Defining_Identifier
(Loc
, Name_uCPU
),
12168 Component_Definition
=>
12169 Make_Component_Definition
(Loc
,
12170 Aliased_Present
=> False,
12171 Subtype_Indication
=>
12172 New_Occurrence_Of
(RTE
(RE_CPU_Range
), Loc
))));
12175 -- Add the _Relative_Deadline component if a Relative_Deadline pragma is
12176 -- present. If we are using a restricted run time this component will
12177 -- not be added (deadlines are not allowed by the Ravenscar profile),
12178 -- unless the task dispatching policy is EDF (for GNAT_Ravenscar_EDF
12181 if (not Restricted_Profile
or else Task_Dispatching_Policy
= 'E')
12182 and then Present
(Taskdef
)
12183 and then Has_Relative_Deadline_Pragma
(Taskdef
)
12186 Make_Component_Declaration
(Loc
,
12187 Defining_Identifier
=>
12188 Make_Defining_Identifier
(Loc
, Name_uRelative_Deadline
),
12190 Component_Definition
=>
12191 Make_Component_Definition
(Loc
,
12192 Aliased_Present
=> False,
12193 Subtype_Indication
=>
12194 New_Occurrence_Of
(RTE
(RE_Time_Span
), Loc
)),
12197 Convert_To
(RTE
(RE_Time_Span
),
12199 Expression
(First
(
12200 Pragma_Argument_Associations
(
12201 Get_Relative_Deadline_Pragma
(Taskdef
))))))));
12204 -- Add the _Dispatching_Domain component if a Dispatching_Domain rep
12205 -- item is present. If we are using a restricted run time this component
12206 -- will not be added (dispatching domains are not allowed by the
12207 -- Ravenscar profile).
12209 if not Restricted_Profile
12212 (TaskId
, Name_Dispatching_Domain
, Check_Parents
=> False)
12215 Make_Component_Declaration
(Loc
,
12216 Defining_Identifier
=>
12217 Make_Defining_Identifier
(Loc
, Name_uDispatching_Domain
),
12219 Component_Definition
=>
12220 Make_Component_Definition
(Loc
,
12221 Aliased_Present
=> False,
12222 Subtype_Indication
=>
12224 (RTE
(RE_Dispatching_Domain_Access
), Loc
))));
12227 Insert_After
(Size_Decl
, Rec_Decl
);
12229 -- Analyze the record declaration immediately after construction,
12230 -- because the initialization procedure is needed for single task
12231 -- declarations before the next entity is analyzed.
12233 Analyze
(Rec_Decl
);
12235 -- Create the declaration of the task body procedure
12237 Proc_Spec
:= Build_Task_Proc_Specification
(Tasktyp
);
12239 Make_Subprogram_Declaration
(Loc
,
12240 Specification
=> Proc_Spec
);
12241 Set_Is_Task_Body_Procedure
(Body_Decl
);
12243 Insert_After
(Rec_Decl
, Body_Decl
);
12245 -- The subprogram does not comes from source, so we have to indicate the
12246 -- need for debugging information explicitly.
12248 if Comes_From_Source
(Original_Node
(N
)) then
12249 Set_Debug_Info_Needed
(Defining_Entity
(Proc_Spec
));
12252 -- Ada 2005 (AI-345): Construct the primitive entry wrapper specs before
12253 -- the corresponding record has been frozen.
12255 if Ada_Version
>= Ada_2005
then
12256 Build_Wrapper_Specs
(Loc
, Tasktyp
, Rec_Decl
);
12259 -- Ada 2005 (AI-345): We must defer freezing to allow further
12260 -- declaration of primitive subprograms covering task interfaces
12262 if Ada_Version
<= Ada_95
then
12264 -- Now we can freeze the corresponding record. This needs manually
12265 -- freezing, since it is really part of the task type, and the task
12266 -- type is frozen at this stage. We of course need the initialization
12267 -- procedure for this corresponding record type and we won't get it
12268 -- in time if we don't freeze now.
12270 Insert_List_After
(Body_Decl
, List
=> Freeze_Entity
(Rec_Ent
, N
));
12273 -- Complete the expansion of access types to the current task type, if
12274 -- any were declared.
12276 Expand_Previous_Access_Type
(Tasktyp
);
12278 -- Create wrappers for entries that have contract cases, preconditions
12279 -- and postconditions.
12285 Ent
:= First_Entity
(Tasktyp
);
12286 while Present
(Ent
) loop
12287 if Ekind
(Ent
) in E_Entry | E_Entry_Family
then
12288 Build_Entry_Contract_Wrapper
(Ent
, N
);
12294 end Expand_N_Task_Type_Declaration
;
12296 -------------------------------
12297 -- Expand_N_Timed_Entry_Call --
12298 -------------------------------
12300 -- A timed entry call in normal case is not implemented using ATC mechanism
12301 -- anymore for efficiency reason.
12311 -- is expanded as follows:
12313 -- 1) When T.E is a task entry_call;
12317 -- X : Task_Entry_Index := <entry index>;
12318 -- DX : Duration := To_Duration (D);
12319 -- M : Delay_Mode := <discriminant>;
12320 -- P : parms := (parm, parm, parm);
12323 -- Timed_Protected_Entry_Call
12324 -- (<acceptor-task>, X, P'Address, DX, M, B);
12332 -- 2) When T.E is a protected entry_call;
12336 -- X : Protected_Entry_Index := <entry index>;
12337 -- DX : Duration := To_Duration (D);
12338 -- M : Delay_Mode := <discriminant>;
12339 -- P : parms := (parm, parm, parm);
12342 -- Timed_Protected_Entry_Call
12343 -- (<object>'unchecked_access, X, P'Address, DX, M, B);
12351 -- 3) Ada 2005 (AI-345): When T.E is a dispatching procedure call, there
12352 -- is no delay and the triggering statements are executed. We first
12353 -- determine the kind of the triggering call and then execute a
12354 -- synchronized operation or a direct call.
12357 -- B : Boolean := False;
12358 -- C : Ada.Tags.Prim_Op_Kind;
12359 -- DX : Duration := To_Duration (D)
12360 -- K : Ada.Tags.Tagged_Kind :=
12361 -- Ada.Tags.Get_Tagged_Kind (Ada.Tags.Tag (<object>));
12362 -- M : Integer :=...;
12363 -- P : Parameters := (Param1 .. ParamN);
12367 -- if K = Ada.Tags.TK_Limited_Tagged
12368 -- or else K = Ada.Tags.TK_Tagged
12370 -- <dispatching-call>;
12375 -- Ada.Tags.Get_Offset_Index
12376 -- (Ada.Tags.Tag (<object>), DT_Position (<dispatching-call>));
12378 -- _Disp_Timed_Select (<object>, S, P'Address, DX, M, C, B);
12380 -- if C = POK_Protected_Entry
12381 -- or else C = POK_Task_Entry
12383 -- Param1 := P.Param1;
12385 -- ParamN := P.ParamN;
12389 -- if C = POK_Procedure
12390 -- or else C = POK_Protected_Procedure
12391 -- or else C = POK_Task_Procedure
12393 -- <dispatching-call>;
12399 -- <triggering-statements>
12401 -- <timed-statements>
12405 -- The triggering statement and the sequence of timed statements have not
12406 -- been analyzed yet (see Analyzed_Timed_Entry_Call), but they may contain
12407 -- global references if within an instantiation.
12409 procedure Expand_N_Timed_Entry_Call
(N
: Node_Id
) is
12411 Blk_Typ
: Entity_Id
;
12413 Call_Ent
: Entity_Id
;
12414 Conc_Typ_Stmts
: List_Id
;
12415 Concval
: Node_Id
:= Empty
; -- init to avoid warning
12416 D_Alt
: constant Node_Id
:= Delay_Alternative
(N
);
12419 D_Stat
: Node_Id
:= Delay_Statement
(D_Alt
);
12421 D_Type
: Entity_Id
;
12424 E_Alt
: constant Node_Id
:= Entry_Call_Alternative
(N
);
12425 E_Call
: Node_Id
:= Entry_Call_Statement
(E_Alt
);
12430 Is_Disp_Select
: Boolean;
12431 Lim_Typ_Stmts
: List_Id
;
12432 Loc
: constant Source_Ptr
:= Sloc
(D_Stat
);
12441 B
: Entity_Id
; -- Call status flag
12442 C
: Entity_Id
; -- Call kind
12443 D
: Entity_Id
; -- Delay
12444 K
: Entity_Id
; -- Tagged kind
12445 M
: Entity_Id
; -- Delay mode
12446 P
: Entity_Id
; -- Parameter block
12447 S
: Entity_Id
; -- Primitive operation slot
12449 -- Start of processing for Expand_N_Timed_Entry_Call
12452 -- Under the Ravenscar profile, timed entry calls are excluded. An error
12453 -- was already reported on spec, so do not attempt to expand the call.
12455 if Restriction_Active
(No_Select_Statements
) then
12459 Process_Statements_For_Controlled_Objects
(E_Alt
);
12460 Process_Statements_For_Controlled_Objects
(D_Alt
);
12462 Ensure_Statement_Present
(Sloc
(D_Stat
), D_Alt
);
12464 -- Retrieve E_Stats and D_Stats now because the finalization machinery
12465 -- may wrap them in blocks.
12467 E_Stats
:= Statements
(E_Alt
);
12468 D_Stats
:= Statements
(D_Alt
);
12470 -- The arguments in the call may require dynamic allocation, and the
12471 -- call statement may have been transformed into a block. The block
12472 -- may contain additional declarations for internal entities, and the
12473 -- original call is found by sequential search.
12475 if Nkind
(E_Call
) = N_Block_Statement
then
12476 E_Call
:= First
(Statements
(Handled_Statement_Sequence
(E_Call
)));
12477 while Nkind
(E_Call
) not in
12478 N_Procedure_Call_Statement | N_Entry_Call_Statement
12485 Ada_Version
>= Ada_2005
12486 and then Nkind
(E_Call
) = N_Procedure_Call_Statement
;
12488 if Is_Disp_Select
then
12489 Extract_Dispatching_Call
(E_Call
, Call_Ent
, Obj
, Actuals
, Formals
);
12495 -- B : Boolean := False;
12497 B
:= Build_B
(Loc
, Decls
);
12500 -- C : Ada.Tags.Prim_Op_Kind;
12502 C
:= Build_C
(Loc
, Decls
);
12504 -- Because the analysis of all statements was disabled, manually
12505 -- analyze the delay statement.
12508 D_Stat
:= Original_Node
(D_Stat
);
12511 -- Build an entry call using Simple_Entry_Call
12513 Extract_Entry
(E_Call
, Concval
, Ename
, Index
);
12514 Build_Simple_Entry_Call
(E_Call
, Concval
, Ename
, Index
);
12516 Decls
:= Declarations
(E_Call
);
12517 Stmts
:= Statements
(Handled_Statement_Sequence
(E_Call
));
12526 B
:= Make_Defining_Identifier
(Loc
, Name_uB
);
12529 Make_Object_Declaration
(Loc
,
12530 Defining_Identifier
=> B
,
12531 Object_Definition
=>
12532 New_Occurrence_Of
(Standard_Boolean
, Loc
)));
12535 -- Duration and mode processing
12537 D_Type
:= Base_Type
(Etype
(Expression
(D_Stat
)));
12539 -- Use the type of the delay expression (Calendar or Real_Time) to
12540 -- generate the appropriate conversion.
12542 if Nkind
(D_Stat
) = N_Delay_Relative_Statement
then
12543 D_Disc
:= Make_Integer_Literal
(Loc
, 0);
12544 D_Conv
:= Relocate_Node
(Expression
(D_Stat
));
12546 elsif Is_RTE
(D_Type
, RO_CA_Time
) then
12547 D_Disc
:= Make_Integer_Literal
(Loc
, 1);
12549 Make_Function_Call
(Loc
,
12550 Name
=> New_Occurrence_Of
(RTE
(RO_CA_To_Duration
), Loc
),
12551 Parameter_Associations
=>
12552 New_List
(New_Copy
(Expression
(D_Stat
))));
12554 else pragma Assert
(Is_RTE
(D_Type
, RO_RT_Time
));
12555 D_Disc
:= Make_Integer_Literal
(Loc
, 2);
12557 Make_Function_Call
(Loc
,
12558 Name
=> New_Occurrence_Of
(RTE
(RO_RT_To_Duration
), Loc
),
12559 Parameter_Associations
=>
12560 New_List
(New_Copy
(Expression
(D_Stat
))));
12563 D
:= Make_Temporary
(Loc
, 'D');
12569 Make_Object_Declaration
(Loc
,
12570 Defining_Identifier
=> D
,
12571 Object_Definition
=> New_Occurrence_Of
(Standard_Duration
, Loc
)));
12573 M
:= Make_Temporary
(Loc
, 'M');
12576 -- M : Integer := (0 | 1 | 2);
12579 Make_Object_Declaration
(Loc
,
12580 Defining_Identifier
=> M
,
12581 Object_Definition
=> New_Occurrence_Of
(Standard_Integer
, Loc
),
12582 Expression
=> D_Disc
));
12584 -- Parameter block processing
12586 -- Manually create the parameter block for dispatching calls. In the
12587 -- case of entries, the block has already been created during the call
12588 -- to Build_Simple_Entry_Call.
12590 if Is_Disp_Select
then
12592 -- Compute the delay at this stage because the evaluation of its
12593 -- expression must not occur earlier (see ACVC C97302A).
12596 Make_Assignment_Statement
(Loc
,
12597 Name
=> New_Occurrence_Of
(D
, Loc
),
12598 Expression
=> D_Conv
));
12600 -- Tagged kind processing, generate:
12601 -- K : Ada.Tags.Tagged_Kind :=
12602 -- Ada.Tags.Get_Tagged_Kind (Ada.Tags.Tag <object>));
12604 K
:= Build_K
(Loc
, Decls
, Obj
);
12606 Blk_Typ
:= Build_Parameter_Block
(Loc
, Actuals
, Formals
, Decls
);
12608 Parameter_Block_Pack
(Loc
, Blk_Typ
, Actuals
, Formals
, Decls
, Stmts
);
12610 -- Dispatch table slot processing, generate:
12613 S
:= Build_S
(Loc
, Decls
);
12616 -- S := Ada.Tags.Get_Offset_Index
12617 -- (Ada.Tags.Tag (<object>), DT_Position (Call_Ent));
12620 New_List
(Build_S_Assignment
(Loc
, S
, Obj
, Call_Ent
));
12623 -- _Disp_Timed_Select (<object>, S, P'Address, D, M, C, B);
12625 -- where Obj is the controlling formal parameter, S is the dispatch
12626 -- table slot number of the dispatching operation, P is the wrapped
12627 -- parameter block, D is the duration, M is the duration mode, C is
12628 -- the call kind and B is the call status.
12630 Params
:= New_List
;
12632 Append_To
(Params
, New_Copy_Tree
(Obj
));
12633 Append_To
(Params
, New_Occurrence_Of
(S
, Loc
));
12635 Make_Attribute_Reference
(Loc
,
12636 Prefix
=> New_Occurrence_Of
(P
, Loc
),
12637 Attribute_Name
=> Name_Address
));
12638 Append_To
(Params
, New_Occurrence_Of
(D
, Loc
));
12639 Append_To
(Params
, New_Occurrence_Of
(M
, Loc
));
12640 Append_To
(Params
, New_Occurrence_Of
(C
, Loc
));
12641 Append_To
(Params
, New_Occurrence_Of
(B
, Loc
));
12643 Append_To
(Conc_Typ_Stmts
,
12644 Make_Procedure_Call_Statement
(Loc
,
12648 (Etype
(Etype
(Obj
)), Name_uDisp_Timed_Select
), Loc
),
12649 Parameter_Associations
=> Params
));
12652 -- if C = POK_Protected_Entry
12653 -- or else C = POK_Task_Entry
12655 -- Param1 := P.Param1;
12657 -- ParamN := P.ParamN;
12660 Unpack
:= Parameter_Block_Unpack
(Loc
, P
, Actuals
, Formals
);
12662 -- Generate the if statement only when the packed parameters need
12663 -- explicit assignments to their corresponding actuals.
12665 if Present
(Unpack
) then
12666 Append_To
(Conc_Typ_Stmts
,
12667 Make_Implicit_If_Statement
(N
,
12673 Left_Opnd
=> New_Occurrence_Of
(C
, Loc
),
12676 (RTE
(RE_POK_Protected_Entry
), Loc
)),
12680 Left_Opnd
=> New_Occurrence_Of
(C
, Loc
),
12682 New_Occurrence_Of
(RTE
(RE_POK_Task_Entry
), Loc
))),
12684 Then_Statements
=> Unpack
));
12690 -- if C = POK_Procedure
12691 -- or else C = POK_Protected_Procedure
12692 -- or else C = POK_Task_Procedure
12694 -- <dispatching-call>
12698 N_Stats
:= New_List
(
12699 Make_Implicit_If_Statement
(N
,
12704 Left_Opnd
=> New_Occurrence_Of
(C
, Loc
),
12706 New_Occurrence_Of
(RTE
(RE_POK_Procedure
), Loc
)),
12712 Left_Opnd
=> New_Occurrence_Of
(C
, Loc
),
12714 New_Occurrence_Of
(RTE
(
12715 RE_POK_Protected_Procedure
), Loc
)),
12718 Left_Opnd
=> New_Occurrence_Of
(C
, Loc
),
12721 (RTE
(RE_POK_Task_Procedure
), Loc
)))),
12723 Then_Statements
=> New_List
(E_Call
)));
12725 Append_To
(Conc_Typ_Stmts
,
12726 Make_Implicit_If_Statement
(N
,
12727 Condition
=> New_Occurrence_Of
(B
, Loc
),
12728 Then_Statements
=> N_Stats
));
12731 -- <dispatching-call>;
12735 New_List
(New_Copy_Tree
(E_Call
),
12736 Make_Assignment_Statement
(Loc
,
12737 Name
=> New_Occurrence_Of
(B
, Loc
),
12738 Expression
=> New_Occurrence_Of
(Standard_True
, Loc
)));
12741 -- if K = Ada.Tags.TK_Limited_Tagged
12742 -- or else K = Ada.Tags.TK_Tagged
12750 Make_Implicit_If_Statement
(N
,
12751 Condition
=> Build_Dispatching_Tag_Check
(K
, N
),
12752 Then_Statements
=> Lim_Typ_Stmts
,
12753 Else_Statements
=> Conc_Typ_Stmts
));
12758 -- <triggering-statements>
12760 -- <timed-statements>
12764 Make_Implicit_If_Statement
(N
,
12765 Condition
=> New_Occurrence_Of
(B
, Loc
),
12766 Then_Statements
=> E_Stats
,
12767 Else_Statements
=> D_Stats
));
12770 -- Simple case of a nondispatching trigger. Skip assignments to
12771 -- temporaries created for in-out parameters.
12773 -- This makes unwarranted assumptions about the shape of the expanded
12774 -- tree for the call, and should be cleaned up ???
12776 Stmt
:= First
(Stmts
);
12777 while Nkind
(Stmt
) /= N_Procedure_Call_Statement
loop
12781 -- Compute the delay at this stage because the evaluation of
12782 -- its expression must not occur earlier (see ACVC C97302A).
12784 Insert_Before
(Stmt
,
12785 Make_Assignment_Statement
(Loc
,
12786 Name
=> New_Occurrence_Of
(D
, Loc
),
12787 Expression
=> D_Conv
));
12790 Params
:= Parameter_Associations
(Call
);
12792 -- For a protected type, we build a Timed_Protected_Entry_Call
12794 if Is_Protected_Type
(Etype
(Concval
)) then
12796 -- Create a new call statement
12798 Param
:= First
(Params
);
12799 while Present
(Param
)
12800 and then not Is_RTE
(Etype
(Param
), RE_Call_Modes
)
12805 Dummy
:= Remove_Next
(Next
(Param
));
12807 -- Remove garbage is following the Cancel_Param if present
12809 Dummy
:= Next
(Param
);
12811 -- Remove the mode of the Protected_Entry_Call call, then remove
12812 -- the Communication_Block of the Protected_Entry_Call call, and
12813 -- finally add Duration and a Delay_Mode parameter
12815 pragma Assert
(Present
(Param
));
12816 Rewrite
(Param
, New_Occurrence_Of
(D
, Loc
));
12818 Rewrite
(Dummy
, New_Occurrence_Of
(M
, Loc
));
12820 -- Add a Boolean flag for successful entry call
12822 Append_To
(Params
, New_Occurrence_Of
(B
, Loc
));
12824 case Corresponding_Runtime_Package
(Etype
(Concval
)) is
12825 when System_Tasking_Protected_Objects_Entries
=>
12827 Make_Procedure_Call_Statement
(Loc
,
12830 (RTE
(RE_Timed_Protected_Entry_Call
), Loc
),
12831 Parameter_Associations
=> Params
));
12834 raise Program_Error
;
12837 -- For the task case, build a Timed_Task_Entry_Call
12840 -- Create a new call statement
12842 Append_To
(Params
, New_Occurrence_Of
(D
, Loc
));
12843 Append_To
(Params
, New_Occurrence_Of
(M
, Loc
));
12844 Append_To
(Params
, New_Occurrence_Of
(B
, Loc
));
12847 Make_Procedure_Call_Statement
(Loc
,
12849 New_Occurrence_Of
(RTE
(RE_Timed_Task_Entry_Call
), Loc
),
12850 Parameter_Associations
=> Params
));
12854 Make_Implicit_If_Statement
(N
,
12855 Condition
=> New_Occurrence_Of
(B
, Loc
),
12856 Then_Statements
=> E_Stats
,
12857 Else_Statements
=> D_Stats
));
12861 Make_Block_Statement
(Loc
,
12862 Declarations
=> Decls
,
12863 Handled_Statement_Sequence
=>
12864 Make_Handled_Sequence_Of_Statements
(Loc
, Stmts
)));
12868 -- Some items in Decls used to be in the N_Block in E_Call that is
12869 -- constructed in Expand_Entry_Call, and are now in the new Block
12870 -- into which N has been rewritten. Adjust their scopes to reflect that.
12872 if Nkind
(E_Call
) = N_Block_Statement
then
12873 Obj
:= First_Entity
(Entity
(Identifier
(E_Call
)));
12874 while Present
(Obj
) loop
12875 Set_Scope
(Obj
, Entity
(Identifier
(N
)));
12880 Reset_Scopes_To
(N
, Entity
(Identifier
(N
)));
12881 end Expand_N_Timed_Entry_Call
;
12883 ----------------------------------------
12884 -- Expand_Protected_Body_Declarations --
12885 ----------------------------------------
12887 procedure Expand_Protected_Body_Declarations
12889 Spec_Id
: Entity_Id
)
12892 if No_Run_Time_Mode
then
12893 Error_Msg_CRT
("protected body", N
);
12896 elsif Expander_Active
then
12898 -- Associate discriminals with the first subprogram or entry body to
12901 if Present
(First_Protected_Operation
(Declarations
(N
))) then
12902 Set_Discriminals
(Parent
(Spec_Id
));
12905 end Expand_Protected_Body_Declarations
;
12907 -------------------------
12908 -- External_Subprogram --
12909 -------------------------
12911 function External_Subprogram
(E
: Entity_Id
) return Entity_Id
is
12912 Subp
: constant Entity_Id
:= Protected_Body_Subprogram
(E
);
12915 -- The internal and external subprograms follow each other on the entity
12916 -- chain. Note that previously private operations had no separate
12917 -- external subprogram. We now create one in all cases, because a
12918 -- private operation may actually appear in an external call, through
12919 -- a 'Access reference used for a callback.
12921 -- If the operation is a function that returns an anonymous access type,
12922 -- the corresponding itype appears before the operation, and must be
12925 -- This mechanism is fragile, there should be a real link between the
12926 -- two versions of the operation, but there is no place to put it ???
12928 if Is_Access_Type
(Next_Entity
(Subp
)) then
12929 return Next_Entity
(Next_Entity
(Subp
));
12931 return Next_Entity
(Subp
);
12933 end External_Subprogram
;
12935 ------------------------------
12936 -- Extract_Dispatching_Call --
12937 ------------------------------
12939 procedure Extract_Dispatching_Call
12941 Call_Ent
: out Entity_Id
;
12942 Object
: out Entity_Id
;
12943 Actuals
: out List_Id
;
12944 Formals
: out List_Id
)
12946 Call_Nam
: Node_Id
;
12949 pragma Assert
(Nkind
(N
) = N_Procedure_Call_Statement
);
12951 if Present
(Original_Node
(N
)) then
12952 Call_Nam
:= Name
(Original_Node
(N
));
12954 Call_Nam
:= Name
(N
);
12957 -- Retrieve the name of the dispatching procedure. It contains the
12958 -- dispatch table slot number.
12961 case Nkind
(Call_Nam
) is
12962 when N_Identifier
=>
12965 when N_Selected_Component
=>
12966 Call_Nam
:= Selector_Name
(Call_Nam
);
12969 raise Program_Error
;
12973 Actuals
:= Parameter_Associations
(N
);
12974 Call_Ent
:= Entity
(Call_Nam
);
12975 Formals
:= Parameter_Specifications
(Parent
(Call_Ent
));
12976 Object
:= First
(Actuals
);
12978 if Present
(Original_Node
(Object
)) then
12979 Object
:= Original_Node
(Object
);
12982 -- If the type of the dispatching object is an access type then return
12983 -- an explicit dereference of a copy of the object, and note that this
12984 -- is the controlling actual of the call.
12986 if Is_Access_Type
(Etype
(Object
)) then
12988 Make_Explicit_Dereference
(Sloc
(N
), New_Copy_Tree
(Object
));
12990 Set_Is_Controlling_Actual
(Object
);
12992 end Extract_Dispatching_Call
;
12994 -------------------
12995 -- Extract_Entry --
12996 -------------------
12998 procedure Extract_Entry
13000 Concval
: out Node_Id
;
13001 Ename
: out Node_Id
;
13002 Index
: out Node_Id
)
13004 Nam
: constant Node_Id
:= Name
(N
);
13007 -- For a simple entry, the name is a selected component, with the
13008 -- prefix being the task value, and the selector being the entry.
13010 if Nkind
(Nam
) = N_Selected_Component
then
13011 Concval
:= Prefix
(Nam
);
13012 Ename
:= Selector_Name
(Nam
);
13015 -- For a member of an entry family, the name is an indexed component
13016 -- where the prefix is a selected component, whose prefix in turn is
13017 -- the task value, and whose selector is the entry family. The single
13018 -- expression in the expressions list of the indexed component is the
13019 -- subscript for the family.
13021 else pragma Assert
(Nkind
(Nam
) = N_Indexed_Component
);
13022 Concval
:= Prefix
(Prefix
(Nam
));
13023 Ename
:= Selector_Name
(Prefix
(Nam
));
13024 Index
:= First
(Expressions
(Nam
));
13027 -- Through indirection, the type may actually be a limited view of a
13028 -- concurrent type. When compiling a call, the non-limited view of the
13029 -- type is visible.
13031 if From_Limited_With
(Etype
(Concval
)) then
13032 Set_Etype
(Concval
, Non_Limited_View
(Etype
(Concval
)));
13036 -------------------
13037 -- Family_Offset --
13038 -------------------
13040 function Family_Offset
13045 Cap
: Boolean) return Node_Id
13051 function Convert_Discriminant_Ref
(Bound
: Node_Id
) return Node_Id
;
13052 -- If one of the bounds is a reference to a discriminant, replace with
13053 -- corresponding discriminal of type. Within the body of a task retrieve
13054 -- the renamed discriminant by simple visibility, using its generated
13055 -- name. Within a protected object, find the original discriminant and
13056 -- replace it with the discriminal of the current protected operation.
13058 ------------------------------
13059 -- Convert_Discriminant_Ref --
13060 ------------------------------
13062 function Convert_Discriminant_Ref
(Bound
: Node_Id
) return Node_Id
is
13063 Loc
: constant Source_Ptr
:= Sloc
(Bound
);
13068 if Is_Entity_Name
(Bound
)
13069 and then Ekind
(Entity
(Bound
)) = E_Discriminant
13071 if Is_Task_Type
(Ttyp
) and then Has_Completion
(Ttyp
) then
13072 B
:= Make_Identifier
(Loc
, Chars
(Entity
(Bound
)));
13073 Find_Direct_Name
(B
);
13075 elsif Is_Protected_Type
(Ttyp
) then
13076 D
:= First_Discriminant
(Ttyp
);
13077 while Chars
(D
) /= Chars
(Entity
(Bound
)) loop
13078 Next_Discriminant
(D
);
13081 B
:= New_Occurrence_Of
(Discriminal
(D
), Loc
);
13084 B
:= New_Occurrence_Of
(Discriminal
(Entity
(Bound
)), Loc
);
13087 elsif Nkind
(Bound
) = N_Attribute_Reference
then
13091 B
:= New_Copy_Tree
(Bound
);
13095 Make_Attribute_Reference
(Loc
,
13096 Attribute_Name
=> Name_Pos
,
13097 Prefix
=> New_Occurrence_Of
(Etype
(Bound
), Loc
),
13098 Expressions
=> New_List
(B
));
13099 end Convert_Discriminant_Ref
;
13101 -- Start of processing for Family_Offset
13104 Real_Hi
:= Convert_Discriminant_Ref
(Hi
);
13105 Real_Lo
:= Convert_Discriminant_Ref
(Lo
);
13108 if Is_Task_Type
(Ttyp
) then
13109 Ityp
:= RTE
(RE_Task_Entry_Index
);
13111 Ityp
:= RTE
(RE_Protected_Entry_Index
);
13115 Make_Attribute_Reference
(Loc
,
13116 Prefix
=> New_Occurrence_Of
(Ityp
, Loc
),
13117 Attribute_Name
=> Name_Min
,
13118 Expressions
=> New_List
(
13120 Make_Integer_Literal
(Loc
, Entry_Family_Bound
- 1)));
13123 Make_Attribute_Reference
(Loc
,
13124 Prefix
=> New_Occurrence_Of
(Ityp
, Loc
),
13125 Attribute_Name
=> Name_Max
,
13126 Expressions
=> New_List
(
13128 Make_Integer_Literal
(Loc
, -Entry_Family_Bound
)));
13131 return Make_Op_Subtract
(Loc
, Real_Hi
, Real_Lo
);
13138 function Family_Size
13143 Cap
: Boolean) return Node_Id
13148 if Is_Task_Type
(Ttyp
) then
13149 Ityp
:= RTE
(RE_Task_Entry_Index
);
13151 Ityp
:= RTE
(RE_Protected_Entry_Index
);
13155 Make_Attribute_Reference
(Loc
,
13156 Prefix
=> New_Occurrence_Of
(Ityp
, Loc
),
13157 Attribute_Name
=> Name_Max
,
13158 Expressions
=> New_List
(
13160 Left_Opnd
=> Family_Offset
(Loc
, Hi
, Lo
, Ttyp
, Cap
),
13161 Right_Opnd
=> Make_Integer_Literal
(Loc
, 1)),
13162 Make_Integer_Literal
(Loc
, 0)));
13165 ----------------------------
13166 -- Find_Enclosing_Context --
13167 ----------------------------
13169 procedure Find_Enclosing_Context
13171 Context
: out Node_Id
;
13172 Context_Id
: out Entity_Id
;
13173 Context_Decls
: out List_Id
)
13176 -- Traverse the parent chain looking for an enclosing body, block,
13177 -- package or return statement.
13179 Context
:= Parent
(N
);
13180 while Present
(Context
) loop
13181 if Nkind
(Context
) in N_Entry_Body
13182 | N_Extended_Return_Statement
13184 | N_Package_Declaration
13185 | N_Subprogram_Body
13190 -- Do not consider block created to protect a list of statements with
13191 -- an Abort_Defer / Abort_Undefer_Direct pair.
13193 elsif Nkind
(Context
) = N_Block_Statement
13194 and then not Is_Abort_Block
(Context
)
13199 Context
:= Parent
(Context
);
13202 pragma Assert
(Present
(Context
));
13204 -- Extract the constituents of the context
13206 if Nkind
(Context
) = N_Extended_Return_Statement
then
13207 Context_Decls
:= Return_Object_Declarations
(Context
);
13208 Context_Id
:= Return_Statement_Entity
(Context
);
13210 -- Package declarations and bodies use a common library-level activation
13211 -- chain or task master, therefore return the package declaration as the
13212 -- proper carrier for the appropriate flag.
13214 elsif Nkind
(Context
) = N_Package_Body
then
13215 Context_Decls
:= Declarations
(Context
);
13216 Context_Id
:= Corresponding_Spec
(Context
);
13217 Context
:= Parent
(Context_Id
);
13219 if Nkind
(Context
) = N_Defining_Program_Unit_Name
then
13220 Context
:= Parent
(Parent
(Context
));
13222 Context
:= Parent
(Context
);
13225 elsif Nkind
(Context
) = N_Package_Declaration
then
13226 Context_Decls
:= Visible_Declarations
(Specification
(Context
));
13227 Context_Id
:= Defining_Unit_Name
(Specification
(Context
));
13229 if Nkind
(Context_Id
) = N_Defining_Program_Unit_Name
then
13230 Context_Id
:= Defining_Identifier
(Context_Id
);
13234 if Nkind
(Context
) = N_Block_Statement
then
13235 Context_Id
:= Entity
(Identifier
(Context
));
13237 if No
(Declarations
(Context
)) then
13238 Set_Declarations
(Context
, New_List
);
13241 elsif Nkind
(Context
) = N_Entry_Body
then
13242 Context_Id
:= Defining_Identifier
(Context
);
13244 elsif Nkind
(Context
) = N_Subprogram_Body
then
13245 if Present
(Corresponding_Spec
(Context
)) then
13246 Context_Id
:= Corresponding_Spec
(Context
);
13248 Context_Id
:= Defining_Unit_Name
(Specification
(Context
));
13250 if Nkind
(Context_Id
) = N_Defining_Program_Unit_Name
then
13251 Context_Id
:= Defining_Identifier
(Context_Id
);
13255 elsif Nkind
(Context
) = N_Task_Body
then
13256 Context_Id
:= Corresponding_Spec
(Context
);
13259 raise Program_Error
;
13262 Context_Decls
:= Declarations
(Context
);
13265 pragma Assert
(Present
(Context_Id
));
13266 pragma Assert
(Present
(Context_Decls
));
13267 end Find_Enclosing_Context
;
13269 -----------------------
13270 -- Find_Master_Scope --
13271 -----------------------
13273 function Find_Master_Scope
(E
: Entity_Id
) return Entity_Id
is
13277 -- In Ada 2005, the master is the innermost enclosing scope that is not
13278 -- transient. If the enclosing block is the rewriting of a call or the
13279 -- scope is an extended return statement this is valid master. The
13280 -- master in an extended return is only used within the return, and is
13281 -- subsequently overwritten in Move_Activation_Chain, but it must exist
13282 -- now before that overwriting occurs.
13286 if Ada_Version
>= Ada_2005
then
13287 while Is_Internal
(S
) loop
13288 if Nkind
(Parent
(S
)) = N_Block_Statement
13289 and then Has_Master_Entity
(S
)
13293 elsif Ekind
(S
) = E_Return_Statement
then
13303 end Find_Master_Scope
;
13305 -------------------------------
13306 -- First_Protected_Operation --
13307 -------------------------------
13309 function First_Protected_Operation
(D
: List_Id
) return Node_Id
is
13310 First_Op
: Node_Id
;
13313 First_Op
:= First
(D
);
13314 while Present
(First_Op
)
13315 and then Nkind
(First_Op
) not in N_Subprogram_Body | N_Entry_Body
13321 end First_Protected_Operation
;
13323 ---------------------------------------
13324 -- Install_Private_Data_Declarations --
13325 ---------------------------------------
13327 procedure Install_Private_Data_Declarations
13329 Spec_Id
: Entity_Id
;
13330 Conc_Typ
: Entity_Id
;
13331 Body_Nod
: Node_Id
;
13333 Barrier
: Boolean := False;
13334 Family
: Boolean := False)
13336 Is_Protected
: constant Boolean := Is_Protected_Type
(Conc_Typ
);
13339 Insert_Node
: Node_Id
:= Empty
;
13340 Obj_Ent
: Entity_Id
;
13342 procedure Add
(Decl
: Node_Id
);
13343 -- Add a single declaration after Insert_Node. If this is the first
13344 -- addition, Decl is added to the front of Decls and it becomes the
13347 function Replace_Bound
(Bound
: Node_Id
) return Node_Id
;
13348 -- The bounds of an entry index may depend on discriminants, create a
13349 -- reference to the corresponding prival. Otherwise return a duplicate
13350 -- of the original bound.
13356 procedure Add
(Decl
: Node_Id
) is
13358 if No
(Insert_Node
) then
13359 Prepend_To
(Decls
, Decl
);
13361 Insert_After
(Insert_Node
, Decl
);
13364 Insert_Node
:= Decl
;
13367 -------------------
13368 -- Replace_Bound --
13369 -------------------
13371 function Replace_Bound
(Bound
: Node_Id
) return Node_Id
is
13373 if Nkind
(Bound
) = N_Identifier
13374 and then Is_Discriminal
(Entity
(Bound
))
13376 return Make_Identifier
(Loc
, Chars
(Entity
(Bound
)));
13378 return Duplicate_Subexpr
(Bound
);
13382 -- Start of processing for Install_Private_Data_Declarations
13385 -- Step 1: Retrieve the concurrent object entity. Obj_Ent can denote
13386 -- formal parameter _O, _object or _task depending on the context.
13388 Obj_Ent
:= Concurrent_Object
(Spec_Id
, Conc_Typ
);
13390 -- Special processing of _O for barrier functions, protected entries
13397 (Ekind
(Spec_Id
) = E_Entry
13398 or else Ekind
(Spec_Id
) = E_Entry_Family
))
13401 Conc_Rec
: constant Entity_Id
:=
13402 Corresponding_Record_Type
(Conc_Typ
);
13403 Typ_Id
: constant Entity_Id
:=
13404 Make_Defining_Identifier
(Loc
,
13405 New_External_Name
(Chars
(Conc_Rec
), 'P'));
13408 -- type prot_typVP is access prot_typV;
13411 Make_Full_Type_Declaration
(Loc
,
13412 Defining_Identifier
=> Typ_Id
,
13414 Make_Access_To_Object_Definition
(Loc
,
13415 Subtype_Indication
=>
13416 New_Occurrence_Of
(Conc_Rec
, Loc
)));
13420 -- _object : prot_typVP := prot_typV (_O);
13423 Make_Object_Declaration
(Loc
,
13424 Defining_Identifier
=>
13425 Make_Defining_Identifier
(Loc
, Name_uObject
),
13426 Object_Definition
=> New_Occurrence_Of
(Typ_Id
, Loc
),
13428 Unchecked_Convert_To
(Typ_Id
,
13429 New_Occurrence_Of
(Obj_Ent
, Loc
)));
13432 -- Set the reference to the concurrent object
13434 Obj_Ent
:= Defining_Identifier
(Decl
);
13438 -- Step 2: Create the Protection object and build its declaration for
13439 -- any protected entry (family) of subprogram. Note for the lock-free
13440 -- implementation, the Protection object is not needed anymore.
13442 if Is_Protected
and then not Uses_Lock_Free
(Conc_Typ
) then
13444 Prot_Ent
: constant Entity_Id
:= Make_Temporary
(Loc
, 'R');
13448 Set_Protection_Object
(Spec_Id
, Prot_Ent
);
13450 -- Determine the proper protection type
13452 if Has_Attach_Handler
(Conc_Typ
)
13453 and then not Restricted_Profile
13455 Prot_Typ
:= RE_Static_Interrupt_Protection
;
13457 elsif Has_Interrupt_Handler
(Conc_Typ
)
13458 and then not Restriction_Active
(No_Dynamic_Attachment
)
13460 Prot_Typ
:= RE_Dynamic_Interrupt_Protection
;
13463 case Corresponding_Runtime_Package
(Conc_Typ
) is
13464 when System_Tasking_Protected_Objects_Entries
=>
13465 Prot_Typ
:= RE_Protection_Entries
;
13467 when System_Tasking_Protected_Objects_Single_Entry
=>
13468 Prot_Typ
:= RE_Protection_Entry
;
13470 when System_Tasking_Protected_Objects
=>
13471 Prot_Typ
:= RE_Protection
;
13474 raise Program_Error
;
13479 -- conc_typR : protection_typ renames _object._object;
13482 Make_Object_Renaming_Declaration
(Loc
,
13483 Defining_Identifier
=> Prot_Ent
,
13485 New_Occurrence_Of
(RTE
(Prot_Typ
), Loc
),
13487 Make_Selected_Component
(Loc
,
13488 Prefix
=> New_Occurrence_Of
(Obj_Ent
, Loc
),
13489 Selector_Name
=> Make_Identifier
(Loc
, Name_uObject
)));
13495 -- Step 3: Add discriminant renamings (if any)
13497 if Has_Discriminants
(Conc_Typ
) then
13502 D
:= First_Discriminant
(Conc_Typ
);
13503 while Present
(D
) loop
13505 -- Adjust the source location
13507 Set_Sloc
(Discriminal
(D
), Loc
);
13510 -- discr_name : discr_typ renames _object.discr_name;
13512 -- discr_name : discr_typ renames _task.discr_name;
13515 Make_Object_Renaming_Declaration
(Loc
,
13516 Defining_Identifier
=> Discriminal
(D
),
13517 Subtype_Mark
=> New_Occurrence_Of
(Etype
(D
), Loc
),
13519 Make_Selected_Component
(Loc
,
13520 Prefix
=> New_Occurrence_Of
(Obj_Ent
, Loc
),
13521 Selector_Name
=> Make_Identifier
(Loc
, Chars
(D
))));
13525 -- Set debug info needed on this renaming declaration even
13526 -- though it does not come from source, so that the debugger
13527 -- will get the right information for these generated names.
13529 Set_Debug_Info_Needed
(Discriminal
(D
));
13531 Next_Discriminant
(D
);
13536 -- Step 4: Add private component renamings (if any)
13538 if Is_Protected
then
13539 Def
:= Protected_Definition
(Parent
(Conc_Typ
));
13541 if Present
(Private_Declarations
(Def
)) then
13544 Comp_Id
: Entity_Id
;
13545 Decl_Id
: Entity_Id
;
13549 Comp
:= First
(Private_Declarations
(Def
));
13550 while Present
(Comp
) loop
13551 if Nkind
(Comp
) = N_Component_Declaration
then
13552 Comp_Id
:= Defining_Identifier
(Comp
);
13553 Nam
:= Chars
(Comp_Id
);
13554 Decl_Id
:= Make_Defining_Identifier
(Sloc
(Comp_Id
), Nam
);
13556 -- Minimal decoration
13558 if Ekind
(Spec_Id
) = E_Function
then
13559 Mutate_Ekind
(Decl_Id
, E_Constant
);
13561 Mutate_Ekind
(Decl_Id
, E_Variable
);
13564 Set_Prival
(Comp_Id
, Decl_Id
);
13565 Set_Prival_Link
(Decl_Id
, Comp_Id
);
13566 Set_Is_Aliased
(Decl_Id
, Is_Aliased
(Comp_Id
));
13567 Set_Is_Independent
(Decl_Id
, Is_Independent
(Comp_Id
));
13569 -- Copy the Comes_From_Source flag of the component, as
13570 -- the renaming may be the only entity directly seen by
13571 -- the user in the context, but do not warn for it.
13573 Set_Comes_From_Source
13574 (Decl_Id
, Comes_From_Source
(Comp_Id
));
13575 Set_Warnings_Off
(Decl_Id
);
13578 -- comp_name : comp_typ renames _object.comp_name;
13581 Make_Object_Renaming_Declaration
(Loc
,
13582 Defining_Identifier
=> Decl_Id
,
13584 New_Occurrence_Of
(Etype
(Comp_Id
), Loc
),
13586 Make_Selected_Component
(Loc
,
13587 Prefix
=> New_Occurrence_Of
(Obj_Ent
, Loc
),
13588 Selector_Name
=> Make_Identifier
(Loc
, Nam
)));
13599 -- Step 5: Add the declaration of the entry index and the associated
13600 -- type for barrier functions and entry families.
13602 if (Barrier
and Family
) or else Ekind
(Spec_Id
) = E_Entry_Family
then
13604 E
: constant Entity_Id
:= Index_Object
(Spec_Id
);
13605 Index
: constant Entity_Id
:=
13606 Defining_Identifier
13607 (Entry_Index_Specification
13608 (Entry_Body_Formal_Part
(Body_Nod
)));
13609 Index_Con
: constant Entity_Id
:=
13610 Make_Defining_Identifier
(Loc
, Chars
(Index
));
13612 Index_Typ
: Entity_Id
;
13616 -- Minimal decoration
13618 Mutate_Ekind
(Index_Con
, E_Constant
);
13619 Set_Entry_Index_Constant
(Index
, Index_Con
);
13620 Set_Discriminal_Link
(Index_Con
, Index
);
13622 -- Retrieve the bounds of the entry family
13624 High
:= Type_High_Bound
(Etype
(Index
));
13625 Low
:= Type_Low_Bound
(Etype
(Index
));
13627 -- In the simple case the entry family is given by a subtype mark
13628 -- and the index constant has the same type.
13630 if Is_Entity_Name
(Original_Node
(
13631 Discrete_Subtype_Definition
(Parent
(Index
))))
13633 Index_Typ
:= Etype
(Index
);
13635 -- Otherwise a new subtype declaration is required
13638 High
:= Replace_Bound
(High
);
13639 Low
:= Replace_Bound
(Low
);
13641 Index_Typ
:= Make_Temporary
(Loc
, 'J');
13644 -- subtype Jnn is <Etype of Index> range Low .. High;
13647 Make_Subtype_Declaration
(Loc
,
13648 Defining_Identifier
=> Index_Typ
,
13649 Subtype_Indication
=>
13650 Make_Subtype_Indication
(Loc
,
13652 New_Occurrence_Of
(Base_Type
(Etype
(Index
)), Loc
),
13654 Make_Range_Constraint
(Loc
,
13655 Range_Expression
=>
13656 Make_Range
(Loc
, Low
, High
))));
13660 Set_Etype
(Index_Con
, Index_Typ
);
13662 -- Create the object which designates the index:
13663 -- J : constant Jnn :=
13664 -- Jnn'Val (_E - <index expr> + Jnn'Pos (Jnn'First));
13666 -- where Jnn is the subtype created above or the original type of
13667 -- the index, _E is a formal of the protected body subprogram and
13668 -- <index expr> is the index of the first family member.
13671 Make_Object_Declaration
(Loc
,
13672 Defining_Identifier
=> Index_Con
,
13673 Constant_Present
=> True,
13674 Object_Definition
=>
13675 New_Occurrence_Of
(Index_Typ
, Loc
),
13678 Make_Attribute_Reference
(Loc
,
13680 New_Occurrence_Of
(Index_Typ
, Loc
),
13681 Attribute_Name
=> Name_Val
,
13683 Expressions
=> New_List
(
13687 Make_Op_Subtract
(Loc
,
13688 Left_Opnd
=> New_Occurrence_Of
(E
, Loc
),
13690 Entry_Index_Expression
(Loc
,
13691 Defining_Identifier
(Body_Nod
),
13695 Make_Attribute_Reference
(Loc
,
13697 New_Occurrence_Of
(Index_Typ
, Loc
),
13698 Attribute_Name
=> Name_Pos
,
13699 Expressions
=> New_List
(
13700 Make_Attribute_Reference
(Loc
,
13702 New_Occurrence_Of
(Index_Typ
, Loc
),
13703 Attribute_Name
=> Name_First
)))))));
13707 end Install_Private_Data_Declarations
;
13709 ---------------------------------
13710 -- Is_Potentially_Large_Family --
13711 ---------------------------------
13713 function Is_Potentially_Large_Family
13714 (Base_Index
: Entity_Id
;
13715 Conctyp
: Entity_Id
;
13717 Hi
: Node_Id
) return Boolean
13720 return Scope
(Base_Index
) = Standard_Standard
13721 and then Base_Index
= Base_Type
(Standard_Integer
)
13722 and then Has_Defaulted_Discriminants
(Conctyp
)
13724 (Denotes_Discriminant
(Lo
, True)
13726 Denotes_Discriminant
(Hi
, True));
13727 end Is_Potentially_Large_Family
;
13729 -------------------------------------
13730 -- Is_Private_Primitive_Subprogram --
13731 -------------------------------------
13733 function Is_Private_Primitive_Subprogram
(Id
: Entity_Id
) return Boolean is
13736 (Ekind
(Id
) = E_Function
or else Ekind
(Id
) = E_Procedure
)
13737 and then Is_Private_Primitive
(Id
);
13738 end Is_Private_Primitive_Subprogram
;
13744 function Index_Object
(Spec_Id
: Entity_Id
) return Entity_Id
is
13745 Bod_Subp
: constant Entity_Id
:= Protected_Body_Subprogram
(Spec_Id
);
13746 Formal
: Entity_Id
;
13749 Formal
:= First_Formal
(Bod_Subp
);
13750 while Present
(Formal
) loop
13752 -- Look for formal parameter _E
13754 if Chars
(Formal
) = Name_uE
then
13758 Next_Formal
(Formal
);
13761 -- A protected body subprogram should always have the parameter in
13764 raise Program_Error
;
13767 --------------------------------
13768 -- Make_Initialize_Protection --
13769 --------------------------------
13771 function Make_Initialize_Protection
13772 (Protect_Rec
: Entity_Id
) return List_Id
13774 Loc
: constant Source_Ptr
:= Sloc
(Protect_Rec
);
13777 Ptyp
: constant Node_Id
:=
13778 Corresponding_Concurrent_Type
(Protect_Rec
);
13780 L
: constant List_Id
:= New_List
;
13781 Has_Entry
: constant Boolean := Has_Entries
(Ptyp
);
13782 Prio_Type
: Entity_Id
;
13783 Prio_Var
: Entity_Id
:= Empty
;
13784 Restricted
: constant Boolean := Restricted_Profile
;
13787 -- We may need two calls to properly initialize the object, one to
13788 -- Initialize_Protection, and possibly one to Install_Handlers if we
13789 -- have a pragma Attach_Handler.
13791 -- Get protected declaration. In the case of a task type declaration,
13792 -- this is simply the parent of the protected type entity. In the single
13793 -- protected object declaration, this parent will be the implicit type,
13794 -- and we can find the corresponding single protected object declaration
13795 -- by searching forward in the declaration list in the tree.
13797 -- Is the test for N_Single_Protected_Declaration needed here??? Nodes
13798 -- of this type should have been removed during semantic analysis.
13800 Pdec
:= Parent
(Ptyp
);
13801 while Nkind
(Pdec
) not in
13802 N_Protected_Type_Declaration | N_Single_Protected_Declaration
13807 -- Build the parameter list for the call. Note that _Init is the name
13808 -- of the formal for the object to be initialized, which is the task
13809 -- value record itself.
13813 -- For lock-free implementation, skip initializations of the Protection
13816 if not Uses_Lock_Free
(Defining_Identifier
(Pdec
)) then
13818 -- Object parameter. This is a pointer to the object of type
13819 -- Protection used by the GNARL to control the protected object.
13822 Make_Attribute_Reference
(Loc
,
13824 Make_Selected_Component
(Loc
,
13825 Prefix
=> Make_Identifier
(Loc
, Name_uInit
),
13826 Selector_Name
=> Make_Identifier
(Loc
, Name_uObject
)),
13827 Attribute_Name
=> Name_Unchecked_Access
));
13829 -- Priority parameter. Set to Unspecified_Priority unless there is a
13830 -- Priority rep item, in which case we take the value from the pragma
13831 -- or attribute definition clause, or there is an Interrupt_Priority
13832 -- rep item and no Priority rep item, and we set the ceiling to
13833 -- Interrupt_Priority'Last, an implementation-defined value, see
13836 if Has_Rep_Item
(Ptyp
, Name_Priority
, Check_Parents
=> False) then
13838 Prio_Clause
: constant Node_Id
:=
13840 (Ptyp
, Name_Priority
, Check_Parents
=> False);
13847 if Nkind
(Prio_Clause
) = N_Pragma
then
13850 (First
(Pragma_Argument_Associations
(Prio_Clause
)));
13852 -- Get_Rep_Item returns either priority pragma
13854 if Pragma_Name
(Prio_Clause
) = Name_Priority
then
13855 Prio_Type
:= RTE
(RE_Any_Priority
);
13857 Prio_Type
:= RTE
(RE_Interrupt_Priority
);
13860 -- Attribute definition clause Priority
13863 if Chars
(Prio_Clause
) = Name_Priority
then
13864 Prio_Type
:= RTE
(RE_Any_Priority
);
13866 Prio_Type
:= RTE
(RE_Interrupt_Priority
);
13869 Prio
:= Expression
(Prio_Clause
);
13872 -- Always create a locale variable to capture the priority.
13873 -- The priority is also passed to Install_Restriced_Handlers.
13874 -- Note that it is really necessary to create this variable
13875 -- explicitly. It might be thought that removing side effects
13876 -- would the appropriate approach, but that could generate
13877 -- declarations improperly placed in the enclosing scope.
13879 Prio_Var
:= Make_Temporary
(Loc
, 'R', Prio
);
13881 Make_Object_Declaration
(Loc
,
13882 Defining_Identifier
=> Prio_Var
,
13883 Object_Definition
=> New_Occurrence_Of
(Prio_Type
, Loc
),
13884 Expression
=> Relocate_Node
(Prio
)));
13886 Append_To
(Args
, New_Occurrence_Of
(Prio_Var
, Loc
));
13889 -- When no priority is specified but an xx_Handler pragma is, we
13890 -- default to System.Interrupts.Default_Interrupt_Priority, see
13893 elsif Has_Attach_Handler
(Ptyp
)
13894 or else Has_Interrupt_Handler
(Ptyp
)
13897 New_Occurrence_Of
(RTE
(RE_Default_Interrupt_Priority
), Loc
));
13899 -- Normal case, no priority or xx_Handler specified, default priority
13903 New_Occurrence_Of
(RTE
(RE_Unspecified_Priority
), Loc
));
13906 -- Deadline_Floor parameter for GNAT_Ravenscar_EDF runtimes
13908 if Restricted_Profile
and Task_Dispatching_Policy
= 'E' then
13909 Deadline_Floor
: declare
13910 Item
: constant Node_Id
:=
13912 (Ptyp
, Name_Deadline_Floor
, Check_Parents
=> False);
13914 Deadline
: Node_Id
;
13917 if Present
(Item
) then
13919 -- Pragma Deadline_Floor
13921 if Nkind
(Item
) = N_Pragma
then
13924 (First
(Pragma_Argument_Associations
(Item
)));
13926 -- Attribute definition clause Deadline_Floor
13930 (Nkind
(Item
) = N_Attribute_Definition_Clause
);
13932 Deadline
:= Expression
(Item
);
13935 Append_To
(Args
, Deadline
);
13937 -- Unusual case: default deadline
13941 New_Occurrence_Of
(RTE
(RE_Time_Span_Zero
), Loc
));
13943 end Deadline_Floor
;
13946 -- Test for Compiler_Info parameter. This parameter allows entry body
13947 -- procedures and barrier functions to be called from the runtime. It
13948 -- is a pointer to the record generated by the compiler to represent
13949 -- the protected object.
13951 -- A protected type without entries that covers an interface and
13952 -- overrides the abstract routines with protected procedures is
13953 -- considered equivalent to a protected type with entries in the
13954 -- context of dispatching select statements.
13956 -- Protected types with interrupt handlers (when not using a
13957 -- restricted profile) are also considered equivalent to protected
13958 -- types with entries.
13960 -- The types which are used (Static_Interrupt_Protection and
13961 -- Dynamic_Interrupt_Protection) are derived from Protection_Entries.
13964 Pkg_Id
: constant RTU_Id
:= Corresponding_Runtime_Package
(Ptyp
);
13966 Called_Subp
: RE_Id
;
13970 when System_Tasking_Protected_Objects_Entries
=>
13971 Called_Subp
:= RE_Initialize_Protection_Entries
;
13973 -- Argument Compiler_Info
13976 Make_Attribute_Reference
(Loc
,
13977 Prefix
=> Make_Identifier
(Loc
, Name_uInit
),
13978 Attribute_Name
=> Name_Address
));
13980 when System_Tasking_Protected_Objects_Single_Entry
=>
13981 Called_Subp
:= RE_Initialize_Protection_Entry
;
13983 -- Argument Compiler_Info
13986 Make_Attribute_Reference
(Loc
,
13987 Prefix
=> Make_Identifier
(Loc
, Name_uInit
),
13988 Attribute_Name
=> Name_Address
));
13990 when System_Tasking_Protected_Objects
=>
13991 Called_Subp
:= RE_Initialize_Protection
;
13994 raise Program_Error
;
13997 -- Entry_Queue_Maxes parameter. This is an access to an array of
13998 -- naturals representing the entry queue maximums for each entry
13999 -- in the protected type. Zero represents no max. The access is
14000 -- null if there is no limit for all entries (usual case).
14003 and then Pkg_Id
= System_Tasking_Protected_Objects_Entries
14005 if Present
(Entry_Max_Queue_Lengths_Array
(Ptyp
)) then
14007 Make_Attribute_Reference
(Loc
,
14010 (Entry_Max_Queue_Lengths_Array
(Ptyp
), Loc
),
14011 Attribute_Name
=> Name_Unrestricted_Access
));
14013 Append_To
(Args
, Make_Null
(Loc
));
14016 -- Edge cases exist where entry initialization functions are
14017 -- called, but no entries exist, so null is appended.
14019 elsif Pkg_Id
= System_Tasking_Protected_Objects_Entries
then
14020 Append_To
(Args
, Make_Null
(Loc
));
14023 -- Entry_Bodies parameter. This is a pointer to an array of
14024 -- pointers to the entry body procedures and barrier functions of
14025 -- the object. If the protected type has no entries this object
14026 -- will not exist, in this case, pass a null (it can happen when
14027 -- there are protected interrupt handlers or interfaces).
14030 P_Arr
:= Entry_Bodies_Array
(Ptyp
);
14032 -- Argument Entry_Body (for single entry) or Entry_Bodies (for
14033 -- multiple entries).
14036 Make_Attribute_Reference
(Loc
,
14037 Prefix
=> New_Occurrence_Of
(P_Arr
, Loc
),
14038 Attribute_Name
=> Name_Unrestricted_Access
));
14040 if Pkg_Id
= System_Tasking_Protected_Objects_Entries
then
14042 -- Find index mapping function (clumsy but ok for now)
14044 while Ekind
(P_Arr
) /= E_Function
loop
14045 Next_Entity
(P_Arr
);
14049 Make_Attribute_Reference
(Loc
,
14050 Prefix
=> New_Occurrence_Of
(P_Arr
, Loc
),
14051 Attribute_Name
=> Name_Unrestricted_Access
));
14054 elsif Pkg_Id
= System_Tasking_Protected_Objects_Single_Entry
then
14056 -- This is the case where we have a protected object with
14057 -- interfaces and no entries, and the single entry restriction
14058 -- is in effect. We pass a null pointer for the entry
14059 -- parameter because there is no actual entry.
14061 Append_To
(Args
, Make_Null
(Loc
));
14063 elsif Pkg_Id
= System_Tasking_Protected_Objects_Entries
then
14065 -- This is the case where we have a protected object with no
14067 -- - either interrupt handlers with non restricted profile,
14069 -- Note that the types which are used for interrupt handlers
14070 -- (Static/Dynamic_Interrupt_Protection) are derived from
14071 -- Protection_Entries. We pass two null pointers because there
14072 -- is no actual entry, and the initialization procedure needs
14073 -- both Entry_Bodies and Find_Body_Index.
14075 Append_To
(Args
, Make_Null
(Loc
));
14076 Append_To
(Args
, Make_Null
(Loc
));
14080 Make_Procedure_Call_Statement
(Loc
,
14082 New_Occurrence_Of
(RTE
(Called_Subp
), Loc
),
14083 Parameter_Associations
=> Args
));
14087 if Has_Attach_Handler
(Ptyp
) then
14089 -- We have a list of N Attach_Handler (ProcI, ExprI), and we have to
14090 -- make the following call:
14092 -- Install_Handlers (_object,
14093 -- ((Expr1, Proc1'access), ...., (ExprN, ProcN'access));
14095 -- or, in the case of Ravenscar:
14097 -- Install_Restricted_Handlers
14098 -- (Prio, ((Expr1, Proc1'access), ...., (ExprN, ProcN'access)));
14101 Args
: constant List_Id
:= New_List
;
14102 Table
: constant List_Id
:= New_List
;
14103 Ritem
: Node_Id
:= First_Rep_Item
(Ptyp
);
14106 -- Build the Priority parameter (only for ravenscar)
14110 -- Priority comes from a pragma
14112 if Present
(Prio_Var
) then
14113 Append_To
(Args
, New_Occurrence_Of
(Prio_Var
, Loc
));
14115 -- Priority is the default one
14120 (RTE
(RE_Default_Interrupt_Priority
), Loc
));
14124 -- Build the Attach_Handler table argument
14126 while Present
(Ritem
) loop
14127 if Nkind
(Ritem
) = N_Pragma
14128 and then Pragma_Name
(Ritem
) = Name_Attach_Handler
14131 Handler
: constant Node_Id
:=
14132 First
(Pragma_Argument_Associations
(Ritem
));
14134 Interrupt
: constant Node_Id
:= Next
(Handler
);
14135 Expr
: constant Node_Id
:= Expression
(Interrupt
);
14139 Make_Aggregate
(Loc
, Expressions
=> New_List
(
14140 Unchecked_Convert_To
14141 (RTE
(RE_System_Interrupt_Id
), Expr
),
14142 Make_Attribute_Reference
(Loc
,
14144 Make_Selected_Component
(Loc
,
14146 Make_Identifier
(Loc
, Name_uInit
),
14148 Duplicate_Subexpr_No_Checks
14149 (Expression
(Handler
))),
14150 Attribute_Name
=> Name_Access
))));
14154 Next_Rep_Item
(Ritem
);
14157 -- Append the table argument we just built
14159 Append_To
(Args
, Make_Aggregate
(Loc
, Table
));
14161 -- Append the Install_Handlers (or Install_Restricted_Handlers)
14162 -- call to the statements.
14165 -- Call a simplified version of Install_Handlers to be used
14166 -- when the Ravenscar restrictions are in effect
14167 -- (Install_Restricted_Handlers).
14170 Make_Procedure_Call_Statement
(Loc
,
14173 (RTE
(RE_Install_Restricted_Handlers
), Loc
),
14174 Parameter_Associations
=> Args
));
14177 if not Uses_Lock_Free
(Defining_Identifier
(Pdec
)) then
14179 -- First, prepends the _object argument
14182 Make_Attribute_Reference
(Loc
,
14184 Make_Selected_Component
(Loc
,
14185 Prefix
=> Make_Identifier
(Loc
, Name_uInit
),
14187 Make_Identifier
(Loc
, Name_uObject
)),
14188 Attribute_Name
=> Name_Unchecked_Access
));
14191 -- Then, insert call to Install_Handlers
14194 Make_Procedure_Call_Statement
(Loc
,
14196 New_Occurrence_Of
(RTE
(RE_Install_Handlers
), Loc
),
14197 Parameter_Associations
=> Args
));
14203 end Make_Initialize_Protection
;
14205 ---------------------------
14206 -- Make_Task_Create_Call --
14207 ---------------------------
14209 function Make_Task_Create_Call
(Task_Rec
: Entity_Id
) return Node_Id
is
14210 Loc
: constant Source_Ptr
:= Sloc
(Task_Rec
);
14220 Ttyp
:= Corresponding_Concurrent_Type
(Task_Rec
);
14221 Tnam
:= Chars
(Ttyp
);
14223 -- Get task declaration. In the case of a task type declaration, this is
14224 -- simply the parent of the task type entity. In the single task
14225 -- declaration, this parent will be the implicit type, and we can find
14226 -- the corresponding single task declaration by searching forward in the
14227 -- declaration list in the tree.
14229 -- Is the test for N_Single_Task_Declaration needed here??? Nodes of
14230 -- this type should have been removed during semantic analysis.
14232 Tdec
:= Parent
(Ttyp
);
14233 while Nkind
(Tdec
) not in
14234 N_Task_Type_Declaration | N_Single_Task_Declaration
14239 -- Now we can find the task definition from this declaration
14241 Tdef
:= Task_Definition
(Tdec
);
14243 -- Build the parameter list for the call. Note that _Init is the name
14244 -- of the formal for the object to be initialized, which is the task
14245 -- value record itself.
14249 -- Priority parameter. Set to Unspecified_Priority unless there is a
14250 -- Priority rep item, in which case we take the value from the rep item.
14251 -- Not used on Ravenscar_EDF profile.
14253 if not (Restricted_Profile
and then Task_Dispatching_Policy
= 'E') then
14254 if Has_Rep_Item
(Ttyp
, Name_Priority
, Check_Parents
=> False) then
14256 Make_Selected_Component
(Loc
,
14257 Prefix
=> Make_Identifier
(Loc
, Name_uInit
),
14258 Selector_Name
=> Make_Identifier
(Loc
, Name_uPriority
)));
14261 New_Occurrence_Of
(RTE
(RE_Unspecified_Priority
), Loc
));
14265 -- Optional Stack parameter
14267 if Restricted_Profile
then
14269 -- If the stack has been preallocated by the expander then
14270 -- pass its address. Otherwise, pass a null address.
14272 if Preallocated_Stacks_On_Target
then
14274 Make_Attribute_Reference
(Loc
,
14276 Make_Selected_Component
(Loc
,
14277 Prefix
=> Make_Identifier
(Loc
, Name_uInit
),
14278 Selector_Name
=> Make_Identifier
(Loc
, Name_uStack
)),
14279 Attribute_Name
=> Name_Address
));
14283 New_Occurrence_Of
(RTE
(RE_Null_Address
), Loc
));
14287 -- Size parameter. If no Storage_Size pragma is present, then
14288 -- the size is taken from the taskZ variable for the type, which
14289 -- is either Unspecified_Size, or has been reset by the use of
14290 -- a Storage_Size attribute definition clause. If a pragma is
14291 -- present, then the size is taken from the _Size field of the
14292 -- task value record, which was set from the pragma value.
14294 if Present
(Tdef
) and then Has_Storage_Size_Pragma
(Tdef
) then
14296 Make_Selected_Component
(Loc
,
14297 Prefix
=> Make_Identifier
(Loc
, Name_uInit
),
14298 Selector_Name
=> Make_Identifier
(Loc
, Name_uSize
)));
14302 New_Occurrence_Of
(Storage_Size_Variable
(Ttyp
), Loc
));
14305 -- Secondary_Stack parameter used for restricted profiles
14307 if Restricted_Profile
then
14309 -- If the secondary stack has been allocated by the expander then
14310 -- pass its access pointer. Otherwise, pass null.
14312 if Create_Secondary_Stack_For_Task
(Ttyp
) then
14314 Make_Attribute_Reference
(Loc
,
14316 Make_Selected_Component
(Loc
,
14317 Prefix
=> Make_Identifier
(Loc
, Name_uInit
),
14319 Make_Identifier
(Loc
, Name_uSecondary_Stack
)),
14320 Attribute_Name
=> Name_Unrestricted_Access
));
14323 Append_To
(Args
, Make_Null
(Loc
));
14327 -- Secondary_Stack_Size parameter. Set RE_Unspecified_Size unless there
14328 -- is a Secondary_Stack_Size pragma, in which case take the value from
14329 -- the pragma. If the restriction No_Secondary_Stack is active then a
14330 -- size of 0 is passed regardless to prevent the allocation of the
14333 if Restriction_Active
(No_Secondary_Stack
) then
14334 Append_To
(Args
, Make_Integer_Literal
(Loc
, 0));
14336 elsif Has_Rep_Pragma
14337 (Ttyp
, Name_Secondary_Stack_Size
, Check_Parents
=> False)
14340 Make_Selected_Component
(Loc
,
14341 Prefix
=> Make_Identifier
(Loc
, Name_uInit
),
14343 Make_Identifier
(Loc
, Name_uSecondary_Stack_Size
)));
14347 New_Occurrence_Of
(RTE
(RE_Unspecified_Size
), Loc
));
14350 -- Task_Info parameter. Set to Unspecified_Task_Info unless there is a
14351 -- Task_Info pragma, in which case we take the value from the pragma.
14353 if Has_Rep_Pragma
(Ttyp
, Name_Task_Info
, Check_Parents
=> False) then
14355 Make_Selected_Component
(Loc
,
14356 Prefix
=> Make_Identifier
(Loc
, Name_uInit
),
14357 Selector_Name
=> Make_Identifier
(Loc
, Name_uTask_Info
)));
14361 New_Occurrence_Of
(RTE
(RE_Unspecified_Task_Info
), Loc
));
14364 -- CPU parameter. Set to Unspecified_CPU unless there is a CPU rep item,
14365 -- in which case we take the value from the rep item. The parameter is
14366 -- passed as an Integer because in the case of unspecified CPU the
14367 -- value is not in the range of CPU_Range.
14369 if Has_Rep_Item
(Ttyp
, Name_CPU
, Check_Parents
=> False) then
14371 Convert_To
(Standard_Integer
,
14372 Make_Selected_Component
(Loc
,
14373 Prefix
=> Make_Identifier
(Loc
, Name_uInit
),
14374 Selector_Name
=> Make_Identifier
(Loc
, Name_uCPU
))));
14377 New_Occurrence_Of
(RTE
(RE_Unspecified_CPU
), Loc
));
14380 if not Restricted_Profile
or else Task_Dispatching_Policy
= 'E' then
14382 -- Deadline parameter. If no Relative_Deadline pragma is present,
14383 -- then the deadline is Time_Span_Zero. If a pragma is present, then
14384 -- the deadline is taken from the _Relative_Deadline field of the
14385 -- task value record, which was set from the pragma value. Note that
14386 -- this parameter must not be generated for the restricted profiles
14387 -- since Ravenscar does not allow deadlines.
14389 -- Case where pragma Relative_Deadline applies: use given value
14391 if Present
(Tdef
) and then Has_Relative_Deadline_Pragma
(Tdef
) then
14393 Make_Selected_Component
(Loc
,
14394 Prefix
=> Make_Identifier
(Loc
, Name_uInit
),
14396 Make_Identifier
(Loc
, Name_uRelative_Deadline
)));
14398 -- No pragma Relative_Deadline apply to the task
14402 New_Occurrence_Of
(RTE
(RE_Time_Span_Zero
), Loc
));
14406 if not Restricted_Profile
then
14408 -- Dispatching_Domain parameter. If no Dispatching_Domain rep item is
14409 -- present, then the dispatching domain is null. If a rep item is
14410 -- present, then the dispatching domain is taken from the
14411 -- _Dispatching_Domain field of the task value record, which was set
14412 -- from the rep item value.
14414 -- Case where Dispatching_Domain rep item applies: use given value
14417 (Ttyp
, Name_Dispatching_Domain
, Check_Parents
=> False)
14420 Make_Selected_Component
(Loc
,
14422 Make_Identifier
(Loc
, Name_uInit
),
14424 Make_Identifier
(Loc
, Name_uDispatching_Domain
)));
14426 -- No pragma or aspect Dispatching_Domain applies to the task
14429 Append_To
(Args
, Make_Null
(Loc
));
14432 -- Number of entries. This is an expression of the form:
14434 -- n + _Init.a'Length + _Init.a'B'Length + ...
14436 -- where a,b... are the entry family names for the task definition
14438 Ecount
:= Build_Entry_Count_Expression
(Ttyp
, Loc
);
14439 Append_To
(Args
, Ecount
);
14441 -- Master parameter. This is a reference to the _Master parameter of
14442 -- the initialization procedure, except in the case of the pragma
14443 -- Restrictions (No_Task_Hierarchy) where the value is fixed to
14444 -- System.Tasking.Library_Task_Level.
14446 if Restriction_Active
(No_Task_Hierarchy
) = False then
14447 Append_To
(Args
, Make_Identifier
(Loc
, Name_uMaster
));
14449 Append_To
(Args
, Make_Integer_Literal
(Loc
, Library_Task_Level
));
14453 -- State parameter. This is a pointer to the task body procedure. The
14454 -- required value is obtained by taking 'Unrestricted_Access of the task
14455 -- body procedure and converting it (with an unchecked conversion) to
14456 -- the type required by the task kernel. For further details, see the
14457 -- description of Expand_N_Task_Body. We use 'Unrestricted_Access rather
14458 -- than 'Address in order to avoid creating trampolines.
14461 Body_Proc
: constant Node_Id
:= Get_Task_Body_Procedure
(Ttyp
);
14462 Subp_Ptr_Typ
: constant Node_Id
:=
14463 Create_Itype
(E_Access_Subprogram_Type
, Tdec
);
14464 Ref
: constant Node_Id
:= Make_Itype_Reference
(Loc
);
14467 Set_Directly_Designated_Type
(Subp_Ptr_Typ
, Body_Proc
);
14468 Set_Etype
(Subp_Ptr_Typ
, Subp_Ptr_Typ
);
14470 -- Be sure to freeze a reference to the access-to-subprogram type,
14471 -- otherwise gigi will complain that it's in the wrong scope, because
14472 -- it's actually inside the init procedure for the record type that
14473 -- corresponds to the task type.
14475 Set_Itype
(Ref
, Subp_Ptr_Typ
);
14476 Append_Freeze_Action
(Task_Rec
, Ref
);
14479 Unchecked_Convert_To
(RTE
(RE_Task_Procedure_Access
),
14480 Make_Qualified_Expression
(Loc
,
14481 Subtype_Mark
=> New_Occurrence_Of
(Subp_Ptr_Typ
, Loc
),
14483 Make_Attribute_Reference
(Loc
,
14484 Prefix
=> New_Occurrence_Of
(Body_Proc
, Loc
),
14485 Attribute_Name
=> Name_Unrestricted_Access
))));
14488 -- Discriminants parameter. This is just the address of the task
14489 -- value record itself (which contains the discriminant values
14492 Make_Attribute_Reference
(Loc
,
14493 Prefix
=> Make_Identifier
(Loc
, Name_uInit
),
14494 Attribute_Name
=> Name_Address
));
14496 -- Elaborated parameter. This is an access to the elaboration Boolean
14499 Make_Attribute_Reference
(Loc
,
14500 Prefix
=> Make_Identifier
(Loc
, New_External_Name
(Tnam
, 'E')),
14501 Attribute_Name
=> Name_Unchecked_Access
));
14503 -- Add Chain parameter (not done for sequential elaboration policy, see
14504 -- comment for Create_Restricted_Task_Sequential in s-tarest.ads).
14506 if Partition_Elaboration_Policy
/= 'S' then
14507 Append_To
(Args
, Make_Identifier
(Loc
, Name_uChain
));
14510 -- Task name parameter. Take this from the _Task_Id parameter to the
14511 -- init call unless there is a Task_Name pragma, in which case we take
14512 -- the value from the pragma.
14514 if Has_Rep_Pragma
(Ttyp
, Name_Task_Name
, Check_Parents
=> False) then
14515 -- Copy expression in full, because it may be dynamic and have
14522 (Pragma_Argument_Associations
14524 (Ttyp
, Name_Task_Name
, Check_Parents
=> False))))));
14527 Append_To
(Args
, Make_Identifier
(Loc
, Name_uTask_Name
));
14530 -- Created_Task parameter. This is the _Task_Id field of the task
14534 Make_Selected_Component
(Loc
,
14535 Prefix
=> Make_Identifier
(Loc
, Name_uInit
),
14536 Selector_Name
=> Make_Identifier
(Loc
, Name_uTask_Id
)));
14542 if Restricted_Profile
then
14543 if Partition_Elaboration_Policy
= 'S' then
14544 Create_RE
:= RE_Create_Restricted_Task_Sequential
;
14546 Create_RE
:= RE_Create_Restricted_Task
;
14549 Create_RE
:= RE_Create_Task
;
14552 Name
:= New_Occurrence_Of
(RTE
(Create_RE
), Loc
);
14556 Make_Procedure_Call_Statement
(Loc
,
14558 Parameter_Associations
=> Args
);
14559 end Make_Task_Create_Call
;
14561 ------------------------------
14562 -- Next_Protected_Operation --
14563 ------------------------------
14565 function Next_Protected_Operation
(N
: Node_Id
) return Node_Id
is
14569 -- Check whether there is a subsequent body for a protected operation
14570 -- in the current protected body. In Ada2012 that includes expression
14571 -- functions that are completions.
14573 Next_Op
:= Next
(N
);
14574 while Present
(Next_Op
)
14575 and then Nkind
(Next_Op
) not in
14576 N_Subprogram_Body | N_Entry_Body | N_Expression_Function
14582 end Next_Protected_Operation
;
14584 ---------------------
14585 -- Null_Statements --
14586 ---------------------
14588 function Null_Statements
(Stats
: List_Id
) return Boolean is
14592 Stmt
:= First
(Stats
);
14593 while Nkind
(Stmt
) /= N_Empty
14594 and then (Nkind
(Stmt
) in N_Null_Statement | N_Label
14596 (Nkind
(Stmt
) = N_Pragma
14598 Pragma_Name_Unmapped
(Stmt
) in Name_Unreferenced
14605 return Nkind
(Stmt
) = N_Empty
;
14606 end Null_Statements
;
14608 --------------------------
14609 -- Parameter_Block_Pack --
14610 --------------------------
14612 function Parameter_Block_Pack
14614 Blk_Typ
: Entity_Id
;
14618 Stmts
: List_Id
) return Entity_Id
14620 Actual
: Entity_Id
;
14621 Expr
: Node_Id
:= Empty
;
14622 Formal
: Entity_Id
;
14623 Has_Param
: Boolean := False;
14626 Temp_Asn
: Node_Id
;
14627 Temp_Nam
: Node_Id
;
14630 Actual
:= First
(Actuals
);
14631 Formal
:= Defining_Identifier
(First
(Formals
));
14632 Params
:= New_List
;
14633 while Present
(Actual
) loop
14634 if Is_By_Copy_Type
(Etype
(Actual
)) then
14636 -- Jnn : aliased <formal-type>
14638 Temp_Nam
:= Make_Temporary
(Loc
, 'J');
14641 Make_Object_Declaration
(Loc
,
14642 Aliased_Present
=> True,
14643 Defining_Identifier
=> Temp_Nam
,
14644 Object_Definition
=>
14645 New_Occurrence_Of
(Etype
(Formal
), Loc
)));
14647 -- The object is initialized with an explicit assignment
14648 -- later. Indicate that it does not need an initialization
14649 -- to prevent spurious warnings if the type excludes null.
14651 Set_No_Initialization
(Last
(Decls
));
14653 if Ekind
(Formal
) /= E_Out_Parameter
then
14659 New_Occurrence_Of
(Temp_Nam
, Loc
);
14661 Set_Assignment_OK
(Temp_Asn
);
14664 Make_Assignment_Statement
(Loc
,
14666 Expression
=> New_Copy_Tree
(Actual
)));
14669 -- If the actual is not controlling, generate:
14671 -- Jnn'unchecked_access
14673 -- and add it to aggegate for access to formals. Note that the
14674 -- actual may be by-copy but still be a controlling actual if it
14675 -- is an access to class-wide interface.
14677 if not Is_Controlling_Actual
(Actual
) then
14679 Make_Attribute_Reference
(Loc
,
14680 Attribute_Name
=> Name_Unchecked_Access
,
14681 Prefix
=> New_Occurrence_Of
(Temp_Nam
, Loc
)));
14686 -- The controlling parameter is omitted
14689 if not Is_Controlling_Actual
(Actual
) then
14691 Make_Reference
(Loc
, New_Copy_Tree
(Actual
)));
14697 Next_Actual
(Actual
);
14698 Next_Formal_With_Extras
(Formal
);
14702 Expr
:= Make_Aggregate
(Loc
, Params
);
14707 -- J1'unchecked_access;
14708 -- <actual2>'reference;
14711 P
:= Make_Temporary
(Loc
, 'P');
14714 Make_Object_Declaration
(Loc
,
14715 Defining_Identifier
=> P
,
14716 Object_Definition
=> New_Occurrence_Of
(Blk_Typ
, Loc
),
14717 Expression
=> Expr
));
14720 end Parameter_Block_Pack
;
14722 ----------------------------
14723 -- Parameter_Block_Unpack --
14724 ----------------------------
14726 function Parameter_Block_Unpack
14730 Formals
: List_Id
) return List_Id
14732 Actual
: Entity_Id
;
14734 Formal
: Entity_Id
;
14735 Has_Asnmt
: Boolean := False;
14736 Result
: constant List_Id
:= New_List
;
14739 Actual
:= First
(Actuals
);
14740 Formal
:= Defining_Identifier
(First
(Formals
));
14741 while Present
(Actual
) loop
14742 if Is_By_Copy_Type
(Etype
(Actual
))
14743 and then Ekind
(Formal
) /= E_In_Parameter
14746 -- <actual> := P.<formal>;
14749 Make_Assignment_Statement
(Loc
,
14753 Make_Explicit_Dereference
(Loc
,
14754 Make_Selected_Component
(Loc
,
14756 New_Occurrence_Of
(P
, Loc
),
14758 Make_Identifier
(Loc
, Chars
(Formal
)))));
14760 Set_Assignment_OK
(Name
(Asnmt
));
14761 Append_To
(Result
, Asnmt
);
14766 Next_Actual
(Actual
);
14767 Next_Formal_With_Extras
(Formal
);
14773 return New_List
(Make_Null_Statement
(Loc
));
14775 end Parameter_Block_Unpack
;
14777 ---------------------
14778 -- Reset_Scopes_To --
14779 ---------------------
14781 procedure Reset_Scopes_To
(Bod
: Node_Id
; E
: Entity_Id
) is
14782 function Reset_Scope
(N
: Node_Id
) return Traverse_Result
;
14783 -- Temporaries may have been declared during expansion of the procedure
14784 -- created for an entry body or an accept alternative. Indicate that
14785 -- their scope is the new body, to ensure proper generation of uplevel
14786 -- references where needed during unnesting.
14788 procedure Reset_Scopes
is new Traverse_Proc
(Reset_Scope
);
14794 function Reset_Scope
(N
: Node_Id
) return Traverse_Result
is
14798 -- If this is a block statement with an Identifier, it forms a scope,
14799 -- so we want to reset its scope but not look inside.
14802 and then Nkind
(N
) = N_Block_Statement
14803 and then Present
(Identifier
(N
))
14805 Set_Scope
(Entity
(Identifier
(N
)), E
);
14808 -- Ditto for a package declaration or a full type declaration, etc.
14810 elsif (Nkind
(N
) = N_Package_Declaration
14811 and then N
/= Specification
(N
))
14812 or else Nkind
(N
) in N_Declaration
14813 or else Nkind
(N
) in N_Renaming_Declaration
14815 Set_Scope
(Defining_Entity
(N
), E
);
14820 -- Scan declarations in new body. Declarations in the statement
14821 -- part will be handled during later traversal.
14823 Decl
:= First
(Declarations
(N
));
14824 while Present
(Decl
) loop
14825 Reset_Scopes
(Decl
);
14829 elsif Nkind
(N
) = N_Freeze_Entity
then
14831 -- Scan the actions associated with a freeze node, which may
14832 -- actually be declarations with entities that need to have
14833 -- their scopes reset.
14835 Decl
:= First
(Actions
(N
));
14836 while Present
(Decl
) loop
14837 Reset_Scopes
(Decl
);
14841 elsif N
/= Bod
and then Nkind
(N
) in N_Proper_Body
then
14843 -- A subprogram without a separate declaration may be encountered,
14844 -- and we need to reset the subprogram's entity's scope.
14846 if Nkind
(N
) = N_Subprogram_Body
then
14847 Set_Scope
(Defining_Entity
(Specification
(N
)), E
);
14856 -- Start of processing for Reset_Scopes_To
14859 Reset_Scopes
(Bod
);
14860 end Reset_Scopes_To
;
14862 ----------------------
14863 -- Set_Discriminals --
14864 ----------------------
14866 procedure Set_Discriminals
(Dec
: Node_Id
) is
14869 D_Minal
: Entity_Id
;
14872 pragma Assert
(Nkind
(Dec
) = N_Protected_Type_Declaration
);
14873 Pdef
:= Defining_Identifier
(Dec
);
14875 if Has_Discriminants
(Pdef
) then
14876 D
:= First_Discriminant
(Pdef
);
14877 while Present
(D
) loop
14879 Make_Defining_Identifier
(Sloc
(D
),
14880 Chars
=> New_External_Name
(Chars
(D
), 'D'));
14882 Mutate_Ekind
(D_Minal
, E_Constant
);
14883 Set_Etype
(D_Minal
, Etype
(D
));
14884 Set_Scope
(D_Minal
, Pdef
);
14885 Set_Discriminal
(D
, D_Minal
);
14886 Set_Discriminal_Link
(D_Minal
, D
);
14888 Next_Discriminant
(D
);
14891 end Set_Discriminals
;
14893 -----------------------
14894 -- Trivial_Accept_OK --
14895 -----------------------
14897 function Trivial_Accept_OK
return Boolean is
14899 case Opt
.Task_Dispatching_Policy
is
14901 -- If we have the default task dispatching policy in effect, we can
14902 -- definitely do the optimization (one way of looking at this is to
14903 -- think of the formal definition of the default policy being allowed
14904 -- to run any task it likes after a rendezvous, so even if notionally
14905 -- a full rescheduling occurs, we can say that our dispatching policy
14906 -- (i.e. the default dispatching policy) reorders the queue to be the
14907 -- same as just before the call.
14912 -- FIFO_Within_Priorities certainly does not permit this
14913 -- optimization since the Rendezvous is a scheduling action that may
14914 -- require some other task to be run.
14919 -- For now, disallow the optimization for all other policies. This
14920 -- may be over-conservative, but it is certainly not incorrect.
14925 end Trivial_Accept_OK
;