1 ------------------------------------------------------------------------------
3 -- GNAT COMPILER COMPONENTS --
9 -- Copyright (C) 1992-2002, 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 2, or (at your option) any later ver- --
14 -- sion. GNAT is distributed in the hope that it will be useful, but WITH- --
15 -- OUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY --
16 -- or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License --
17 -- for more details. You should have received a copy of the GNU General --
18 -- Public License distributed with GNAT; see file COPYING. If not, write --
19 -- to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, --
20 -- MA 02111-1307, USA. --
22 -- GNAT was originally developed by the GNAT team at New York University. --
23 -- Extensive contributions were provided by Ada Core Technologies Inc. --
25 ------------------------------------------------------------------------------
27 with Atree; use Atree;
28 with Checks; use Checks;
29 with Einfo; use Einfo;
30 with Elists; use Elists;
31 with Errout; use Errout;
32 with Exp_Ch3; use Exp_Ch3;
33 with Exp_Ch11; use Exp_Ch11;
34 with Exp_Ch6; use Exp_Ch6;
35 with Exp_Dbug; use Exp_Dbug;
36 with Exp_Smem; use Exp_Smem;
37 with Exp_Tss; use Exp_Tss;
38 with Exp_Util; use Exp_Util;
39 with Freeze; use Freeze;
41 with Namet; use Namet;
42 with Nlists; use Nlists;
43 with Nmake; use Nmake;
45 with Restrict; use Restrict;
46 with Rtsfind; use Rtsfind;
49 with Sem_Ch8; use Sem_Ch8;
50 with Sem_Ch11; use Sem_Ch11;
51 with Sem_Elab; use Sem_Elab;
52 with Sem_Res; use Sem_Res;
53 with Sem_Util; use Sem_Util;
54 with Sinfo; use Sinfo;
55 with Snames; use Snames;
56 with Stand; use Stand;
57 with Tbuild; use Tbuild;
58 with Types; use Types;
59 with Uintp; use Uintp;
62 package body Exp_Ch9 is
64 -----------------------
65 -- Local Subprograms --
66 -----------------------
68 function Actual_Index_Expression
74 -- Compute the index position for an entry call. Tsk is the target
75 -- task. If the bounds of some entry family depend on discriminants,
76 -- the expression computed by this function uses the discriminants
77 -- of the target task.
79 function Index_Constant_Declaration
84 -- For an entry family and its barrier function, we define a local entity
85 -- that maps the index in the call into the entry index into the object:
87 -- I : constant Index_Type := Index_Type'Val (
88 -- E - <<index of first family member>> +
89 -- Protected_Entry_Index (Index_Type'Pos (Index_Type'First)));
91 procedure Add_Object_Pointer
95 -- Prepend an object pointer declaration to the declaration list
96 -- Decls. This object pointer is initialized to a type conversion
97 -- of the System.Address pointer passed to entry barrier functions
98 -- and entry body procedures.
100 function Build_Accept_Body (Astat : Node_Id) return Node_Id;
101 -- Transform accept statement into a block with added exception handler.
102 -- Used both for simple accept statements and for accept alternatives in
103 -- select statements. Astat is the accept statement.
105 function Build_Barrier_Function
110 -- Build the function body returning the value of the barrier expression
111 -- for the specified entry body.
113 function Build_Barrier_Function_Specification
117 -- Build a specification for a function implementing
118 -- the protected entry barrier of the specified entry body.
120 function Build_Corresponding_Record
125 -- Common to tasks and protected types. Copy discriminant specifications,
126 -- build record declaration. N is the type declaration, Ctyp is the
127 -- concurrent entity (task type or protected type).
129 function Build_Entry_Count_Expression
130 (Concurrent_Type : Node_Id;
131 Component_List : List_Id;
134 -- Compute number of entries for concurrent object. This is a count of
135 -- simple entries, followed by an expression that computes the length
136 -- of the range of each entry family. A single array with that size is
137 -- allocated for each concurrent object of the type.
139 function Build_Find_Body_Index
142 -- Build the function that translates the entry index in the call
143 -- (which depends on the size of entry families) into an index into the
144 -- Entry_Bodies_Array, to determine the body and barrier function used
145 -- in a protected entry call. A pointer to this function appears in every
148 function Build_Find_Body_Index_Spec
151 -- Build subprogram declaration for previous one.
153 function Build_Protected_Entry
158 -- Build the procedure implementing the statement sequence of
159 -- the specified entry body.
161 function Build_Protected_Entry_Specification
166 -- Build a specification for a procedure implementing
167 -- the statement sequence of the specified entry body.
168 -- Add attributes associating it with the entry defining identifier
171 function Build_Protected_Subprogram_Body
176 -- This function is used to construct the protected version of a protected
177 -- subprogram. Its statement sequence first defers abortion, then locks
178 -- the associated protected object, and then enters a block that contains
179 -- a call to the unprotected version of the subprogram (for details, see
180 -- Build_Unprotected_Subprogram_Body). This block statement requires
181 -- a cleanup handler that unlocks the object in all cases.
182 -- (see Exp_Ch7.Expand_Cleanup_Actions).
184 function Build_Protected_Spec
186 Obj_Type : Entity_Id;
187 Unprotected : Boolean := False;
190 -- Utility shared by Build_Protected_Sub_Spec and Expand_Access_Protected_
191 -- Subprogram_Type. Builds signature of protected subprogram, adding the
192 -- formal that corresponds to the object itself. For an access to protected
193 -- subprogram, there is no object type to specify, so the additional
194 -- parameter has type Address and mode In. An indirect call through such
195 -- a pointer converts the address to a reference to the actual object.
196 -- The object is a limited record and therefore a by_reference type.
198 function Build_Selected_Name
199 (Prefix, Selector : Name_Id;
200 Append_Char : Character := ' ')
202 -- Build a name in the form of Prefix__Selector, with an optional
203 -- character appended. This is used for internal subprograms generated
204 -- for operations of protected types, including barrier functions. In
205 -- order to simplify the work of the debugger, the prefix includes the
208 procedure Build_Simple_Entry_Call
213 -- Some comments here would be useful ???
215 function Build_Task_Proc_Specification (T : Entity_Id) return Node_Id;
216 -- This routine constructs a specification for the procedure that we will
217 -- build for the task body for task type T. The spec has the form:
219 -- procedure tnameB (_Task : access tnameV);
221 -- where name is the character name taken from the task type entity that
222 -- is passed as the argument to the procedure, and tnameV is the task
223 -- value type that is associated with the task type.
225 function Build_Unprotected_Subprogram_Body
229 -- This routine constructs the unprotected version of a protected
230 -- subprogram body, which is contains all of the code in the
231 -- original, unexpanded body. This is the version of the protected
232 -- subprogram that is called from all protected operations on the same
233 -- object, including the protected version of the same subprogram.
235 procedure Collect_Entry_Families
238 Current_Node : in out Node_Id;
239 Conctyp : Entity_Id);
240 -- For each entry family in a concurrent type, create an anonymous array
241 -- type of the right size, and add a component to the corresponding_record.
243 function Family_Offset
249 -- Compute (Hi - Lo) for two entry family indices. Hi is the index in
250 -- an accept statement, or the upper bound in the discrete subtype of
251 -- an entry declaration. Lo is the corresponding lower bound. Ttyp is
252 -- the concurrent type of the entry.
260 -- Compute (Hi - Lo) + 1 Max 0, to determine the number of entries in
261 -- a family, and handle properly the superflat case. This is equivalent
262 -- to the use of 'Length on the index type, but must use Family_Offset
263 -- to handle properly the case of bounds that depend on discriminants.
265 procedure Extract_Entry
267 Concval : out Node_Id;
269 Index : out Node_Id);
270 -- Given an entry call, returns the associated concurrent object,
271 -- the entry name, and the entry family index.
273 function Find_Task_Or_Protected_Pragma
277 -- Searches the task or protected definition T for the first occurrence
278 -- of the pragma whose name is given by P. The caller has ensured that
279 -- the pragma is present in the task definition. A special case is that
280 -- when P is Name_uPriority, the call will also find Interrupt_Priority.
281 -- ??? Should be implemented with the rep item chain mechanism.
283 procedure Update_Prival_Subtypes (N : Node_Id);
284 -- The actual subtypes of the privals will differ from the type of the
285 -- private declaration in the original protected type, if the protected
286 -- type has discriminants or if the prival has constrained components.
287 -- This is because the privals are generated out of sequence w.r.t. the
288 -- analysis of a protected body. After generating the bodies for protected
289 -- operations, we set correctly the type of all references to privals, by
290 -- means of a recursive tree traversal, which is heavy-handed but
293 -----------------------------
294 -- Actual_Index_Expression --
295 -----------------------------
297 function Actual_Index_Expression
310 Ttyp : Entity_Id := Etype (Tsk);
312 --------------------------
313 -- Actual_Family_Offset --
314 --------------------------
316 function Actual_Family_Offset (Hi, Lo : Node_Id) return Node_Id;
317 -- Compute difference between bounds of entry family.
319 function Actual_Family_Offset (Hi, Lo : Node_Id) return Node_Id is
321 function Actual_Discriminant_Ref (Bound : Node_Id) return Node_Id;
322 -- Replace a reference to a discriminant with a selected component
323 -- denoting the discriminant of the target task.
325 function Actual_Discriminant_Ref (Bound : Node_Id) return Node_Id is
326 Typ : Entity_Id := Etype (Bound);
330 if not Is_Entity_Name (Bound)
331 or else Ekind (Entity (Bound)) /= E_Discriminant
333 if Nkind (Bound) = N_Attribute_Reference then
336 B := New_Copy_Tree (Bound);
341 Make_Selected_Component (Sloc,
342 Prefix => New_Copy_Tree (Tsk),
343 Selector_Name => New_Occurrence_Of (Entity (Bound), Sloc));
345 Analyze_And_Resolve (B, Typ);
349 Make_Attribute_Reference (Sloc,
350 Attribute_Name => Name_Pos,
351 Prefix => New_Occurrence_Of (Etype (Bound), Sloc),
352 Expressions => New_List (B));
353 end Actual_Discriminant_Ref;
357 Make_Op_Subtract (Sloc,
358 Left_Opnd => Actual_Discriminant_Ref (Hi),
359 Right_Opnd => Actual_Discriminant_Ref (Lo));
360 end Actual_Family_Offset;
363 -- The queues of entries and entry families appear in textual
364 -- order in the associated record. The entry index is computed as
365 -- the sum of the number of queues for all entries that precede the
366 -- designated one, to which is added the index expression, if this
367 -- expression denotes a member of a family.
369 -- The following is a place holder for the count of simple entries.
371 Num := Make_Integer_Literal (Sloc, 1);
373 -- We construct an expression which is a series of addition
374 -- operations. See comments in Entry_Index_Expression, which is
375 -- identical in structure.
377 if Present (Index) then
378 S := Etype (Discrete_Subtype_Definition (Declaration_Node (Ent)));
385 Actual_Family_Offset (
386 Make_Attribute_Reference (Sloc,
387 Attribute_Name => Name_Pos,
388 Prefix => New_Reference_To (Base_Type (S), Sloc),
389 Expressions => New_List (Relocate_Node (Index))),
390 Type_Low_Bound (S)));
395 -- Now add lengths of preceding entries and entry families.
397 Prev := First_Entity (Ttyp);
399 while Chars (Prev) /= Chars (Ent)
400 or else (Ekind (Prev) /= Ekind (Ent))
401 or else not Sem_Ch6.Type_Conformant (Ent, Prev)
403 if Ekind (Prev) = E_Entry then
404 Set_Intval (Num, Intval (Num) + 1);
406 elsif Ekind (Prev) = E_Entry_Family then
408 Etype (Discrete_Subtype_Definition (Declaration_Node (Prev)));
409 Lo := Type_Low_Bound (S);
410 Hi := Type_High_Bound (S);
418 Actual_Family_Offset (Hi, Lo),
420 Make_Integer_Literal (Sloc, 1)));
422 -- Other components are anonymous types to be ignored.
432 end Actual_Index_Expression;
434 ----------------------------------
435 -- Add_Discriminal_Declarations --
436 ----------------------------------
438 procedure Add_Discriminal_Declarations
447 if Has_Discriminants (Typ) then
448 D := First_Discriminant (Typ);
450 while Present (D) loop
453 Make_Object_Renaming_Declaration (Loc,
454 Defining_Identifier => Discriminal (D),
455 Subtype_Mark => New_Reference_To (Etype (D), Loc),
457 Make_Selected_Component (Loc,
458 Prefix => Make_Identifier (Loc, Name),
459 Selector_Name => Make_Identifier (Loc, Chars (D)))));
461 Next_Discriminant (D);
464 end Add_Discriminal_Declarations;
466 ------------------------
467 -- Add_Object_Pointer --
468 ------------------------
470 procedure Add_Object_Pointer
478 -- Prepend the declaration of _object. This must be first in the
479 -- declaration list, since it is used by the discriminal and
480 -- prival declarations.
481 -- ??? An attempt to make this a renaming was unsuccessful.
483 -- type poVP is access poV;
484 -- _object : poVP := poVP!O;
487 Make_Defining_Identifier (Loc,
490 (Chars (Corresponding_Record_Type (Pid)), 'P'));
493 Make_Object_Declaration (Loc,
494 Defining_Identifier =>
495 Make_Defining_Identifier (Loc, Name_uObject),
496 Object_Definition => New_Reference_To (Obj_Ptr, Loc),
498 Unchecked_Convert_To (Obj_Ptr,
499 Make_Identifier (Loc, Name_uO))));
502 Make_Full_Type_Declaration (Loc,
503 Defining_Identifier => Obj_Ptr,
504 Type_Definition => Make_Access_To_Object_Definition (Loc,
505 Subtype_Indication =>
506 New_Reference_To (Corresponding_Record_Type (Pid), Loc))));
508 end Add_Object_Pointer;
510 ------------------------------
511 -- Add_Private_Declarations --
512 ------------------------------
514 procedure Add_Private_Declarations
522 Def : Node_Id := Protected_Definition (Parent (Typ));
523 Body_Ent : constant Entity_Id := Corresponding_Body (Parent (Typ));
526 pragma Assert (Nkind (Def) = N_Protected_Definition);
528 if Present (Private_Declarations (Def)) then
529 P := First (Private_Declarations (Def));
531 while Present (P) loop
532 if Nkind (P) = N_Component_Declaration then
533 Pdef := Defining_Identifier (P);
535 Make_Object_Renaming_Declaration (Loc,
536 Defining_Identifier => Prival (Pdef),
537 Subtype_Mark => New_Reference_To (Etype (Pdef), Loc),
539 Make_Selected_Component (Loc,
540 Prefix => Make_Identifier (Loc, Name),
541 Selector_Name => Make_Identifier (Loc, Chars (Pdef)))));
547 -- One more "prival" for the object itself, with the right protection
551 Protection_Type : RE_Id;
553 if Has_Attach_Handler (Typ) then
554 if Restricted_Profile then
555 Protection_Type := RE_Protection_Entry;
557 Protection_Type := RE_Static_Interrupt_Protection;
560 elsif Has_Interrupt_Handler (Typ) then
561 Protection_Type := RE_Dynamic_Interrupt_Protection;
563 elsif Has_Entries (Typ) then
565 or else Restrictions (No_Entry_Queue) = False
566 or else Number_Entries (Typ) > 1
568 Protection_Type := RE_Protection_Entries;
570 Protection_Type := RE_Protection_Entry;
574 Protection_Type := RE_Protection;
578 Make_Object_Renaming_Declaration (Loc,
579 Defining_Identifier => Object_Ref (Body_Ent),
580 Subtype_Mark => New_Reference_To (RTE (Protection_Type), Loc),
582 Make_Selected_Component (Loc,
583 Prefix => Make_Identifier (Loc, Name),
584 Selector_Name => Make_Identifier (Loc, Name_uObject))));
587 end Add_Private_Declarations;
589 -----------------------
590 -- Build_Accept_Body --
591 -----------------------
593 function Build_Accept_Body (Astat : Node_Id) return Node_Id is
594 Loc : constant Source_Ptr := Sloc (Astat);
595 Stats : constant Node_Id := Handled_Statement_Sequence (Astat);
602 -- At the end of the statement sequence, Complete_Rendezvous is called.
603 -- A label skipping the Complete_Rendezvous, and all other
604 -- accept processing, has already been added for the expansion
605 -- of requeue statements.
607 Call := Build_Runtime_Call (Loc, RE_Complete_Rendezvous);
608 Insert_Before (Last (Statements (Stats)), Call);
611 -- If exception handlers are present, then append Complete_Rendezvous
612 -- calls to the handlers, and construct the required outer block.
614 if Present (Exception_Handlers (Stats)) then
615 Hand := First (Exception_Handlers (Stats));
617 while Present (Hand) loop
618 Call := Build_Runtime_Call (Loc, RE_Complete_Rendezvous);
619 Append (Call, Statements (Hand));
625 Make_Handled_Sequence_Of_Statements (Loc,
626 Statements => New_List (
627 Make_Block_Statement (Loc,
628 Handled_Statement_Sequence => Stats)));
634 -- At this stage we know that the new statement sequence does not
635 -- have an exception handler part, so we supply one to call
636 -- Exceptional_Complete_Rendezvous. This handler is
638 -- when all others =>
639 -- Exceptional_Complete_Rendezvous (Get_GNAT_Exception);
641 -- We handle Abort_Signal to make sure that we properly catch the abort
642 -- case and wake up the caller.
644 Ohandle := Make_Others_Choice (Loc);
645 Set_All_Others (Ohandle);
647 Set_Exception_Handlers (New_S,
649 Make_Exception_Handler (Loc,
650 Exception_Choices => New_List (Ohandle),
652 Statements => New_List (
653 Make_Procedure_Call_Statement (Loc,
654 Name => New_Reference_To (
655 RTE (RE_Exceptional_Complete_Rendezvous), Loc),
656 Parameter_Associations => New_List (
657 Make_Function_Call (Loc,
658 Name => New_Reference_To (
659 RTE (RE_Get_GNAT_Exception), Loc))))))));
661 Set_Parent (New_S, Astat); -- temp parent for Analyze call
662 Analyze_Exception_Handlers (Exception_Handlers (New_S));
663 Expand_Exception_Handlers (New_S);
665 -- Exceptional_Complete_Rendezvous must be called with abort
666 -- still deferred, which is the case for a "when all others" handler.
670 end Build_Accept_Body;
672 -----------------------------------
673 -- Build_Activation_Chain_Entity --
674 -----------------------------------
676 procedure Build_Activation_Chain_Entity (N : Node_Id) is
682 -- Loop to find enclosing construct containing activation chain variable
686 while Nkind (P) /= N_Subprogram_Body
687 and then Nkind (P) /= N_Package_Declaration
688 and then Nkind (P) /= N_Package_Body
689 and then Nkind (P) /= N_Block_Statement
690 and then Nkind (P) /= N_Task_Body
695 -- If we are in a package body, the activation chain variable is
696 -- allocated in the corresponding spec. First, we save the package
697 -- body node because we enter the new entity in its Declarations list.
701 if Nkind (P) = N_Package_Body then
702 P := Unit_Declaration_Node (Corresponding_Spec (P));
703 Decls := Declarations (B);
705 elsif Nkind (P) = N_Package_Declaration then
706 Decls := Visible_Declarations (Specification (B));
709 Decls := Declarations (B);
712 -- If activation chain entity not already declared, declare it
714 if No (Activation_Chain_Entity (P)) then
715 Set_Activation_Chain_Entity
716 (P, Make_Defining_Identifier (Sloc (N), Name_uChain));
719 Make_Object_Declaration (Sloc (P),
720 Defining_Identifier => Activation_Chain_Entity (P),
721 Aliased_Present => True,
723 New_Reference_To (RTE (RE_Activation_Chain), Sloc (P))));
725 Analyze (First (Decls));
728 end Build_Activation_Chain_Entity;
730 ----------------------------
731 -- Build_Barrier_Function --
732 ----------------------------
734 function Build_Barrier_Function
740 Loc : constant Source_Ptr := Sloc (N);
741 Ent_Formals : constant Node_Id := Entry_Body_Formal_Part (N);
742 Index_Spec : constant Node_Id := Entry_Index_Specification
746 Op_Decls : List_Id := New_List;
750 Make_Defining_Identifier (Loc, Chars (Barrier_Function (Ent)));
751 Bspec := Build_Barrier_Function_Specification (Bdef, Loc);
753 -- <object pointer declaration>
754 -- <discriminant renamings>
755 -- <private object renamings>
756 -- Add discriminal and private renamings. These names have
757 -- already been used to expand references to discriminants
760 Add_Discriminal_Declarations (Op_Decls, Pid, Name_uObject, Loc);
761 Add_Private_Declarations (Op_Decls, Pid, Name_uObject, Loc);
762 Add_Object_Pointer (Op_Decls, Pid, Loc);
764 -- If this is the barrier for an entry family, the entry index is
765 -- visible in the body of the barrier. Create a local variable that
766 -- converts the entry index (which is the last formal of the barrier
767 -- function) into the appropriate offset into the entry array. The
768 -- entry index constant must be set, as for the entry body, so that
769 -- local references to the entry index are correctly replaced with
770 -- the local variable. This parallels what is done for entry bodies.
772 if Present (Index_Spec) then
774 Index_Id : constant Entity_Id := Defining_Identifier (Index_Spec);
775 Index_Con : constant Entity_Id :=
776 Make_Defining_Identifier (Loc, New_Internal_Name ('I'));
779 Set_Entry_Index_Constant (Index_Id, Index_Con);
780 Append_List_To (Op_Decls,
781 Index_Constant_Declaration (N, Index_Id, Pid));
785 -- Note: the condition in the barrier function needs to be properly
786 -- processed for the C/Fortran boolean possibility, but this happens
787 -- automatically since the return statement does this normalization.
790 Make_Subprogram_Body (Loc,
791 Specification => Bspec,
792 Declarations => Op_Decls,
793 Handled_Statement_Sequence =>
794 Make_Handled_Sequence_Of_Statements (Loc,
795 Statements => New_List (
796 Make_Return_Statement (Loc,
797 Expression => Condition (Ent_Formals)))));
798 end Build_Barrier_Function;
800 ------------------------------------------
801 -- Build_Barrier_Function_Specification --
802 ------------------------------------------
804 function Build_Barrier_Function_Specification
810 return Make_Function_Specification (Loc,
811 Defining_Unit_Name => Def_Id,
812 Parameter_Specifications => New_List (
813 Make_Parameter_Specification (Loc,
814 Defining_Identifier => Make_Defining_Identifier (Loc, Name_uO),
816 New_Reference_To (RTE (RE_Address), Loc)),
818 Make_Parameter_Specification (Loc,
819 Defining_Identifier => Make_Defining_Identifier (Loc, Name_uE),
821 New_Reference_To (RTE (RE_Protected_Entry_Index), Loc))),
823 Subtype_Mark => New_Reference_To (Standard_Boolean, Loc));
824 end Build_Barrier_Function_Specification;
826 --------------------------
827 -- Build_Call_With_Task --
828 --------------------------
830 function Build_Call_With_Task
835 Loc : constant Source_Ptr := Sloc (N);
839 Make_Function_Call (Loc,
840 Name => New_Reference_To (E, Loc),
841 Parameter_Associations => New_List (Concurrent_Ref (N)));
842 end Build_Call_With_Task;
844 --------------------------------
845 -- Build_Corresponding_Record --
846 --------------------------------
848 function Build_Corresponding_Record
854 Rec_Ent : constant Entity_Id :=
855 Make_Defining_Identifier
856 (Loc, New_External_Name (Chars (Ctyp), 'V'));
859 New_Disc : Entity_Id;
863 Set_Corresponding_Record_Type (Ctyp, Rec_Ent);
864 Set_Ekind (Rec_Ent, E_Record_Type);
865 Set_Has_Delayed_Freeze (Rec_Ent, Has_Delayed_Freeze (Ctyp));
866 Set_Is_Concurrent_Record_Type (Rec_Ent, True);
867 Set_Corresponding_Concurrent_Type (Rec_Ent, Ctyp);
868 Set_Girder_Constraint (Rec_Ent, No_Elist);
871 -- Use discriminals to create list of discriminants for record, and
872 -- create new discriminals for use in default expressions, etc. It is
873 -- worth noting that a task discriminant gives rise to 5 entities;
875 -- a) The original discriminant.
876 -- b) The discriminal for use in the task.
877 -- c) The discriminant of the corresponding record.
878 -- d) The discriminal for the init_proc of the corresponding record.
879 -- e) The local variable that renames the discriminant in the procedure
880 -- for the task body.
882 -- In fact the discriminals b) are used in the renaming declarations
883 -- for e). See details in einfo (Handling of Discriminants).
885 if Present (Discriminant_Specifications (N)) then
887 Disc := First_Discriminant (Ctyp);
889 while Present (Disc) loop
890 New_Disc := CR_Discriminant (Disc);
893 Make_Discriminant_Specification (Loc,
894 Defining_Identifier => New_Disc,
896 New_Occurrence_Of (Etype (Disc), Loc),
898 New_Copy (Discriminant_Default_Value (Disc))));
900 Next_Discriminant (Disc);
907 -- Now we can construct the record type declaration. Note that this
908 -- record is limited, reflecting the underlying limitedness of the
909 -- task or protected object that it represents, and ensuring for
910 -- example that it is properly passed by reference.
913 Make_Full_Type_Declaration (Loc,
914 Defining_Identifier => Rec_Ent,
915 Discriminant_Specifications => Dlist,
917 Make_Record_Definition (Loc,
919 Make_Component_List (Loc,
920 Component_Items => Cdecls),
921 Limited_Present => True));
922 end Build_Corresponding_Record;
924 ----------------------------------
925 -- Build_Entry_Count_Expression --
926 ----------------------------------
928 function Build_Entry_Count_Expression
929 (Concurrent_Type : Node_Id;
930 Component_List : List_Id;
943 Ent := First_Entity (Concurrent_Type);
946 -- Count number of non-family entries
948 while Present (Ent) loop
949 if Ekind (Ent) = E_Entry then
956 Ecount := Make_Integer_Literal (Loc, Eindx);
958 -- Loop through entry families building the addition nodes
960 Ent := First_Entity (Concurrent_Type);
961 Comp := First (Component_List);
963 while Present (Ent) loop
964 if Ekind (Ent) = E_Entry_Family then
965 while Chars (Ent) /= Chars (Defining_Identifier (Comp)) loop
969 Typ := Etype (Discrete_Subtype_Definition (Parent (Ent)));
970 Hi := Type_High_Bound (Typ);
971 Lo := Type_Low_Bound (Typ);
976 Right_Opnd => Family_Size (Loc, Hi, Lo, Concurrent_Type));
983 end Build_Entry_Count_Expression;
985 ---------------------------
986 -- Build_Find_Body_Index --
987 ---------------------------
989 function Build_Find_Body_Index
993 Loc : constant Source_Ptr := Sloc (Typ);
996 Has_F : Boolean := False;
998 If_St : Node_Id := Empty;
1001 Decls : List_Id := New_List;
1004 Siz : Node_Id := Empty;
1006 procedure Add_If_Clause (Expr : Node_Id);
1007 -- Add test for range of current entry.
1009 function Convert_Discriminant_Ref (Bound : Node_Id) return Node_Id;
1010 -- If a bound of an entry is given by a discriminant, retrieve the
1011 -- actual value of the discriminant from the enclosing object.
1017 procedure Add_If_Clause (Expr : Node_Id) is
1019 Stats : constant List_Id :=
1021 Make_Return_Statement (Loc,
1022 Expression => Make_Integer_Literal (Loc, Index + 1)));
1025 -- Index for current entry body.
1029 -- Compute total length of entry queues so far.
1037 Right_Opnd => Expr);
1042 Left_Opnd => Make_Identifier (Loc, Name_uE),
1045 -- Map entry queue indices in the range of the current family
1046 -- into the current index, that designates the entry body.
1050 Make_Implicit_If_Statement (Typ,
1052 Then_Statements => Stats,
1053 Elsif_Parts => New_List);
1059 Make_Elsif_Part (Loc,
1061 Then_Statements => Stats),
1062 Elsif_Parts (If_St));
1067 ------------------------------
1068 -- Convert_Discriminant_Ref --
1069 ------------------------------
1071 function Convert_Discriminant_Ref (Bound : Node_Id) return Node_Id is
1075 if Is_Entity_Name (Bound)
1076 and then Ekind (Entity (Bound)) = E_Discriminant
1079 Make_Selected_Component (Loc,
1081 Unchecked_Convert_To (Corresponding_Record_Type (Typ),
1082 Make_Explicit_Dereference (Loc,
1083 Make_Identifier (Loc, Name_uObject))),
1084 Selector_Name => Make_Identifier (Loc, Chars (Bound)));
1085 Set_Etype (B, Etype (Entity (Bound)));
1087 B := New_Copy_Tree (Bound);
1091 end Convert_Discriminant_Ref;
1093 -- Start of processing for Build_Find_Body_Index
1096 Spec := Build_Find_Body_Index_Spec (Typ);
1098 Ent := First_Entity (Typ);
1100 while Present (Ent) loop
1102 if Ekind (Ent) = E_Entry_Family then
1112 -- If the protected type has no entry families, there is a one-one
1113 -- correspondence between entry queue and entry body.
1116 Make_Return_Statement (Loc,
1117 Expression => Make_Identifier (Loc, Name_uE));
1120 -- Suppose entries e1, e2, ... have size l1, l2, ... we generate
1123 -- if E <= l1 then return 1;
1124 -- elsif E <= l1 + l2 then return 2;
1129 Ent := First_Entity (Typ);
1131 Add_Object_Pointer (Decls, Typ, Loc);
1133 while Present (Ent) loop
1135 if Ekind (Ent) = E_Entry then
1136 Add_If_Clause (Make_Integer_Literal (Loc, 1));
1138 elsif Ekind (Ent) = E_Entry_Family then
1140 E_Typ := Etype (Discrete_Subtype_Definition (Parent (Ent)));
1141 Hi := Convert_Discriminant_Ref (Type_High_Bound (E_Typ));
1142 Lo := Convert_Discriminant_Ref (Type_Low_Bound (E_Typ));
1143 Add_If_Clause (Family_Size (Loc, Hi, Lo, Typ));
1152 Make_Return_Statement (Loc,
1153 Expression => Make_Integer_Literal (Loc, 1));
1155 elsif Nkind (Ret) = N_If_Statement then
1157 -- Ranges are in increasing order, so last one doesn't need a
1161 Nod : constant Node_Id := Last (Elsif_Parts (Ret));
1165 Set_Else_Statements (Ret, Then_Statements (Nod));
1171 Make_Subprogram_Body (Loc,
1172 Specification => Spec,
1173 Declarations => Decls,
1174 Handled_Statement_Sequence =>
1175 Make_Handled_Sequence_Of_Statements (Loc,
1176 Statements => New_List (Ret)));
1178 end Build_Find_Body_Index;
1180 --------------------------------
1181 -- Build_Find_Body_Index_Spec --
1182 --------------------------------
1184 function Build_Find_Body_Index_Spec
1188 Loc : constant Source_Ptr := Sloc (Typ);
1189 Id : constant Entity_Id :=
1190 Make_Defining_Identifier (Loc,
1191 Chars => New_External_Name (Chars (Typ), 'F'));
1192 Parm1 : constant Entity_Id := Make_Defining_Identifier (Loc, Name_uO);
1193 Parm2 : constant Entity_Id := Make_Defining_Identifier (Loc, Name_uE);
1197 Make_Function_Specification (Loc,
1198 Defining_Unit_Name => Id,
1199 Parameter_Specifications => New_List (
1200 Make_Parameter_Specification (Loc,
1201 Defining_Identifier => Parm1,
1203 New_Reference_To (RTE (RE_Address), Loc)),
1205 Make_Parameter_Specification (Loc,
1206 Defining_Identifier => Parm2,
1208 New_Reference_To (RTE (RE_Protected_Entry_Index), Loc))),
1209 Subtype_Mark => New_Occurrence_Of (
1210 RTE (RE_Protected_Entry_Index), Loc));
1212 end Build_Find_Body_Index_Spec;
1214 -------------------------
1215 -- Build_Master_Entity --
1216 -------------------------
1218 procedure Build_Master_Entity (E : Entity_Id) is
1219 Loc : constant Source_Ptr := Sloc (E);
1224 -- Nothing to do if we already built a master entity for this scope
1225 -- or if there is no task hierarchy.
1227 if Has_Master_Entity (Scope (E))
1228 or else Restrictions (No_Task_Hierarchy)
1233 -- Otherwise first build the master entity
1234 -- _Master : constant Master_Id := Current_Master.all;
1235 -- and insert it just before the current declaration
1238 Make_Object_Declaration (Loc,
1239 Defining_Identifier =>
1240 Make_Defining_Identifier (Loc, Name_uMaster),
1241 Constant_Present => True,
1242 Object_Definition => New_Reference_To (RTE (RE_Master_Id), Loc),
1244 Make_Explicit_Dereference (Loc,
1245 New_Reference_To (RTE (RE_Current_Master), Loc)));
1248 Insert_Before (P, Decl);
1250 Set_Has_Master_Entity (Scope (E));
1252 -- Now mark the containing scope as a task master
1254 while Nkind (P) /= N_Compilation_Unit loop
1257 -- If we fall off the top, we are at the outer level, and the
1258 -- environment task is our effective master, so nothing to mark.
1260 if Nkind (P) = N_Task_Body
1261 or else Nkind (P) = N_Block_Statement
1262 or else Nkind (P) = N_Subprogram_Body
1264 Set_Is_Task_Master (P, True);
1267 elsif Nkind (Parent (P)) = N_Subunit then
1268 P := Corresponding_Stub (Parent (P));
1271 end Build_Master_Entity;
1273 ---------------------------
1274 -- Build_Protected_Entry --
1275 ---------------------------
1277 function Build_Protected_Entry
1283 Loc : constant Source_Ptr := Sloc (N);
1286 Op_Decls : List_Id := New_List;
1293 Make_Defining_Identifier (Loc,
1294 Chars => Chars (Protected_Body_Subprogram (Ent)));
1295 Espec := Build_Protected_Entry_Specification (Edef, Empty, Loc);
1297 -- <object pointer declaration>
1298 -- Add object pointer declaration. This is needed by the
1299 -- discriminal and prival renamings, which should already
1300 -- have been inserted into the declaration list.
1302 Add_Object_Pointer (Op_Decls, Pid, Loc);
1305 or else Restrictions (No_Entry_Queue) = False
1306 or else Number_Entries (Pid) > 1
1308 Complete := New_Reference_To (RTE (RE_Complete_Entry_Body), Loc);
1311 New_Reference_To (RTE (RE_Complete_Single_Entry_Body), Loc);
1314 Op_Stats := New_List (
1315 Make_Block_Statement (Loc,
1316 Declarations => Declarations (N),
1317 Handled_Statement_Sequence =>
1318 Handled_Statement_Sequence (N)),
1320 Make_Procedure_Call_Statement (Loc,
1322 Parameter_Associations => New_List (
1323 Make_Attribute_Reference (Loc,
1325 Make_Selected_Component (Loc,
1327 Make_Identifier (Loc, Name_uObject),
1330 Make_Identifier (Loc, Name_uObject)),
1331 Attribute_Name => Name_Unchecked_Access))));
1333 if Restrictions (No_Exception_Handlers) then
1335 Make_Subprogram_Body (Loc,
1336 Specification => Espec,
1337 Declarations => Op_Decls,
1338 Handled_Statement_Sequence =>
1339 Make_Handled_Sequence_Of_Statements (Loc, Op_Stats));
1342 Ohandle := Make_Others_Choice (Loc);
1343 Set_All_Others (Ohandle);
1346 or else Restrictions (No_Entry_Queue) = False
1347 or else Number_Entries (Pid) > 1
1350 New_Reference_To (RTE (RE_Exceptional_Complete_Entry_Body), Loc);
1353 Complete := New_Reference_To (
1354 RTE (RE_Exceptional_Complete_Single_Entry_Body), Loc);
1358 Make_Subprogram_Body (Loc,
1359 Specification => Espec,
1360 Declarations => Op_Decls,
1361 Handled_Statement_Sequence =>
1362 Make_Handled_Sequence_Of_Statements (Loc,
1363 Statements => Op_Stats,
1364 Exception_Handlers => New_List (
1365 Make_Exception_Handler (Loc,
1366 Exception_Choices => New_List (Ohandle),
1368 Statements => New_List (
1369 Make_Procedure_Call_Statement (Loc,
1371 Parameter_Associations => New_List (
1372 Make_Attribute_Reference (Loc,
1374 Make_Selected_Component (Loc,
1376 Make_Identifier (Loc, Name_uObject),
1378 Make_Identifier (Loc, Name_uObject)),
1379 Attribute_Name => Name_Unchecked_Access),
1381 Make_Function_Call (Loc,
1382 Name => New_Reference_To (
1383 RTE (RE_Get_GNAT_Exception), Loc)))))))));
1385 end Build_Protected_Entry;
1387 -----------------------------------------
1388 -- Build_Protected_Entry_Specification --
1389 -----------------------------------------
1391 function Build_Protected_Entry_Specification
1392 (Def_Id : Entity_Id;
1400 P := Make_Defining_Identifier (Loc, Name_uP);
1402 if Present (Ent_Id) then
1403 Append_Elmt (P, Accept_Address (Ent_Id));
1406 return Make_Procedure_Specification (Loc,
1407 Defining_Unit_Name => Def_Id,
1408 Parameter_Specifications => New_List (
1409 Make_Parameter_Specification (Loc,
1410 Defining_Identifier => Make_Defining_Identifier (Loc, Name_uO),
1412 New_Reference_To (RTE (RE_Address), Loc)),
1414 Make_Parameter_Specification (Loc,
1415 Defining_Identifier => P,
1417 New_Reference_To (RTE (RE_Address), Loc)),
1419 Make_Parameter_Specification (Loc,
1420 Defining_Identifier => Make_Defining_Identifier (Loc, Name_uE),
1422 New_Reference_To (RTE (RE_Protected_Entry_Index), Loc))));
1423 end Build_Protected_Entry_Specification;
1425 --------------------------
1426 -- Build_Protected_Spec --
1427 --------------------------
1429 function Build_Protected_Spec
1431 Obj_Type : Entity_Id;
1432 Unprotected : Boolean := False;
1436 Loc : constant Source_Ptr := Sloc (N);
1438 New_Plist : List_Id;
1439 New_Param : Node_Id;
1442 New_Plist := New_List;
1443 Formal := First_Formal (Ident);
1445 while Present (Formal) loop
1447 Make_Parameter_Specification (Loc,
1448 Defining_Identifier =>
1449 Make_Defining_Identifier (Sloc (Formal), Chars (Formal)),
1450 In_Present => In_Present (Parent (Formal)),
1451 Out_Present => Out_Present (Parent (Formal)),
1453 New_Reference_To (Etype (Formal), Loc));
1456 Set_Protected_Formal (Formal, Defining_Identifier (New_Param));
1459 Append (New_Param, New_Plist);
1460 Next_Formal (Formal);
1463 -- If the subprogram is a procedure and the context is not an access
1464 -- to protected subprogram, the parameter is in-out. Otherwise it is
1467 Prepend_To (New_Plist,
1468 Make_Parameter_Specification (Loc,
1469 Defining_Identifier =>
1470 Make_Defining_Identifier (Loc, Name_uObject),
1473 (Etype (Ident) = Standard_Void_Type
1474 and then not Is_RTE (Obj_Type, RE_Address)),
1475 Parameter_Type => New_Reference_To (Obj_Type, Loc)));
1478 end Build_Protected_Spec;
1480 ---------------------------------------
1481 -- Build_Protected_Sub_Specification --
1482 ---------------------------------------
1484 function Build_Protected_Sub_Specification
1486 Prottyp : Entity_Id;
1487 Unprotected : Boolean := False)
1490 Loc : constant Source_Ptr := Sloc (N);
1492 Protnm : constant Name_Id := Chars (Prottyp);
1495 New_Plist : List_Id;
1496 Append_Char : Character;
1501 (Defining_Unit_Name (Specification (N))) = E_Subprogram_Body
1503 Decl := Unit_Declaration_Node (Corresponding_Spec (N));
1508 Ident := Defining_Unit_Name (Specification (Decl));
1509 Nam := Chars (Ident);
1511 New_Plist := Build_Protected_Spec
1512 (Decl, Corresponding_Record_Type (Prottyp),
1513 Unprotected, Ident);
1521 if Nkind (Specification (Decl)) = N_Procedure_Specification then
1523 Make_Procedure_Specification (Loc,
1524 Defining_Unit_Name =>
1525 Make_Defining_Identifier (Loc,
1526 Chars => Build_Selected_Name (Protnm, Nam, Append_Char)),
1527 Parameter_Specifications => New_Plist);
1531 Make_Function_Specification (Loc,
1532 Defining_Unit_Name =>
1533 Make_Defining_Identifier (Loc,
1534 Chars => Build_Selected_Name (Protnm, Nam, Append_Char)),
1535 Parameter_Specifications => New_Plist,
1536 Subtype_Mark => New_Copy (Subtype_Mark (Specification (Decl))));
1537 Set_Return_Present (Defining_Unit_Name (New_Spec));
1540 end Build_Protected_Sub_Specification;
1542 -------------------------------------
1543 -- Build_Protected_Subprogram_Body --
1544 -------------------------------------
1546 function Build_Protected_Subprogram_Body
1549 N_Op_Spec : Node_Id)
1552 Loc : constant Source_Ptr := Sloc (N);
1556 P_Op_Spec : Node_Id;
1559 Unprot_Call : Node_Id;
1561 Lock_Name : Node_Id;
1562 Lock_Stmt : Node_Id;
1563 Unlock_Name : Node_Id;
1564 Unlock_Stmt : Node_Id;
1565 Service_Name : Node_Id;
1566 Service_Stmt : Node_Id;
1568 Return_Stmt : Node_Id := Empty;
1569 Pre_Stmts : List_Id := No_List;
1570 -- Initializations to avoid spurious warnings from GCC3.
1572 Object_Parm : Node_Id;
1575 function Is_Exception_Safe (Subprogram : Node_Id) return Boolean;
1576 -- Tell whether a given subprogram cannot raise an exception
1578 -----------------------
1579 -- Is_Exception_Safe --
1580 -----------------------
1582 function Is_Exception_Safe (Subprogram : Node_Id) return Boolean is
1584 function Has_Side_Effect (N : Node_Id) return Boolean;
1585 -- Return True whenever encountering a subprogram call or a
1586 -- raise statement of any kind in the sequence of statements N
1588 ---------------------
1589 -- Has_Side_Effect --
1590 ---------------------
1592 -- What is this doing buried two levels down in exp_ch9. It
1593 -- seems like a generally useful function, and indeed there
1594 -- may be code duplication going on here ???
1596 function Has_Side_Effect (N : Node_Id) return Boolean is
1597 Stmt : Node_Id := N;
1600 function Is_Call_Or_Raise (N : Node_Id) return Boolean;
1601 -- Indicate whether N is a subprogram call or a raise statement
1603 function Is_Call_Or_Raise (N : Node_Id) return Boolean is
1605 return Nkind (N) = N_Procedure_Call_Statement
1606 or else Nkind (N) = N_Function_Call
1607 or else Nkind (N) = N_Raise_Statement
1608 or else Nkind (N) = N_Raise_Constraint_Error
1609 or else Nkind (N) = N_Raise_Program_Error
1610 or else Nkind (N) = N_Raise_Storage_Error;
1611 end Is_Call_Or_Raise;
1613 -- Start of processing for Has_Side_Effect
1616 while Present (Stmt) loop
1617 if Is_Call_Or_Raise (Stmt) then
1621 -- An object declaration can also contain a function call
1622 -- or a raise statement
1624 if Nkind (Stmt) = N_Object_Declaration then
1625 Expr := Expression (Stmt);
1627 if Present (Expr) and then Is_Call_Or_Raise (Expr) then
1636 end Has_Side_Effect;
1638 -- Start of processing for Is_Exception_Safe
1641 -- If the checks handled by the back end are not disabled, we cannot
1642 -- ensure that no exception will be raised.
1644 if not Access_Checks_Suppressed (Empty)
1645 or else not Discriminant_Checks_Suppressed (Empty)
1646 or else not Range_Checks_Suppressed (Empty)
1647 or else not Index_Checks_Suppressed (Empty)
1648 or else Opt.Stack_Checking_Enabled
1653 if Has_Side_Effect (First (Declarations (Subprogram)))
1656 First (Statements (Handled_Statement_Sequence (Subprogram))))
1662 end Is_Exception_Safe;
1664 -- Start of processing for Build_Protected_Subprogram_Body
1667 Op_Spec := Specification (N);
1668 Op_Def := Defining_Unit_Name (Op_Spec);
1669 Exc_Safe := Is_Exception_Safe (N);
1671 Sub_Name := Chars (Defining_Unit_Name (Specification (N)));
1674 Build_Protected_Sub_Specification (N,
1675 Pid, Unprotected => False);
1677 -- Build a list of the formal parameters of the protected
1678 -- version of the subprogram to use as the actual parameters
1679 -- of the unprotected version.
1681 Uactuals := New_List;
1682 Pformal := First (Parameter_Specifications (P_Op_Spec));
1684 while Present (Pformal) loop
1686 Make_Identifier (Loc, Chars (Defining_Identifier (Pformal))),
1691 -- Make a call to the unprotected version of the subprogram
1692 -- built above for use by the protected version built below.
1694 if Nkind (Op_Spec) = N_Function_Specification then
1696 R := Make_Defining_Identifier (Loc, New_Internal_Name ('R'));
1698 Make_Object_Declaration (Loc,
1699 Defining_Identifier => R,
1700 Constant_Present => True,
1701 Object_Definition => New_Copy (Subtype_Mark (N_Op_Spec)),
1703 Make_Function_Call (Loc,
1704 Name => Make_Identifier (Loc,
1705 Chars (Defining_Unit_Name (N_Op_Spec))),
1706 Parameter_Associations => Uactuals));
1707 Return_Stmt := Make_Return_Statement (Loc,
1708 Expression => New_Reference_To (R, Loc));
1711 Unprot_Call := Make_Return_Statement (Loc,
1712 Expression => Make_Function_Call (Loc,
1714 Make_Identifier (Loc,
1715 Chars (Defining_Unit_Name (N_Op_Spec))),
1716 Parameter_Associations => Uactuals));
1720 Unprot_Call := Make_Procedure_Call_Statement (Loc,
1722 Make_Identifier (Loc,
1723 Chars (Defining_Unit_Name (N_Op_Spec))),
1724 Parameter_Associations => Uactuals);
1727 -- Wrap call in block that will be covered by an at_end handler.
1729 if not Exc_Safe then
1730 Unprot_Call := Make_Block_Statement (Loc,
1731 Handled_Statement_Sequence =>
1732 Make_Handled_Sequence_Of_Statements (Loc,
1733 Statements => New_List (Unprot_Call)));
1736 -- Make the protected subprogram body. This locks the protected
1737 -- object and calls the unprotected version of the subprogram.
1739 -- If the protected object is controlled (i.e it has entries or
1740 -- needs finalization for interrupt handling), call Lock_Entries,
1741 -- except if the protected object follows the Ravenscar profile, in
1742 -- which case call Lock_Entry, otherwise call the simplified version,
1745 if Has_Entries (Pid)
1746 or else Has_Interrupt_Handler (Pid)
1747 or else Has_Attach_Handler (Pid)
1750 or else Restrictions (No_Entry_Queue) = False
1751 or else Number_Entries (Pid) > 1
1753 Lock_Name := New_Reference_To (RTE (RE_Lock_Entries), Loc);
1754 Unlock_Name := New_Reference_To (RTE (RE_Unlock_Entries), Loc);
1755 Service_Name := New_Reference_To (RTE (RE_Service_Entries), Loc);
1758 Lock_Name := New_Reference_To (RTE (RE_Lock_Entry), Loc);
1759 Unlock_Name := New_Reference_To (RTE (RE_Unlock_Entry), Loc);
1760 Service_Name := New_Reference_To (RTE (RE_Service_Entry), Loc);
1764 Lock_Name := New_Reference_To (RTE (RE_Lock), Loc);
1765 Unlock_Name := New_Reference_To (RTE (RE_Unlock), Loc);
1766 Service_Name := Empty;
1770 Make_Attribute_Reference (Loc,
1772 Make_Selected_Component (Loc,
1774 Make_Identifier (Loc, Name_uObject),
1776 Make_Identifier (Loc, Name_uObject)),
1777 Attribute_Name => Name_Unchecked_Access);
1779 Lock_Stmt := Make_Procedure_Call_Statement (Loc,
1781 Parameter_Associations => New_List (Object_Parm));
1783 if Abort_Allowed then
1785 Make_Procedure_Call_Statement (Loc,
1786 Name => New_Reference_To (RTE (RE_Abort_Defer), Loc),
1787 Parameter_Associations => Empty_List),
1791 Stmts := New_List (Lock_Stmt);
1794 if not Exc_Safe then
1795 Append (Unprot_Call, Stmts);
1797 if Nkind (Op_Spec) = N_Function_Specification then
1799 Stmts := Empty_List;
1801 Append (Unprot_Call, Stmts);
1804 if Service_Name /= Empty then
1805 Service_Stmt := Make_Procedure_Call_Statement (Loc,
1806 Name => Service_Name,
1807 Parameter_Associations =>
1808 New_List (New_Copy_Tree (Object_Parm)));
1809 Append (Service_Stmt, Stmts);
1813 Make_Procedure_Call_Statement (Loc,
1814 Name => Unlock_Name,
1815 Parameter_Associations => New_List (
1816 New_Copy_Tree (Object_Parm)));
1817 Append (Unlock_Stmt, Stmts);
1819 if Abort_Allowed then
1821 Make_Procedure_Call_Statement (Loc,
1822 Name => New_Reference_To (RTE (RE_Abort_Undefer), Loc),
1823 Parameter_Associations => Empty_List),
1827 if Nkind (Op_Spec) = N_Function_Specification then
1828 Append (Return_Stmt, Stmts);
1829 Append (Make_Block_Statement (Loc,
1830 Declarations => New_List (Unprot_Call),
1831 Handled_Statement_Sequence =>
1832 Make_Handled_Sequence_Of_Statements (Loc,
1833 Statements => Stmts)), Pre_Stmts);
1839 Make_Subprogram_Body (Loc,
1840 Declarations => Empty_List,
1841 Specification => P_Op_Spec,
1842 Handled_Statement_Sequence =>
1843 Make_Handled_Sequence_Of_Statements (Loc, Statements => Stmts));
1845 if not Exc_Safe then
1846 Set_Is_Protected_Subprogram_Body (Sub_Body);
1850 end Build_Protected_Subprogram_Body;
1852 -------------------------------------
1853 -- Build_Protected_Subprogram_Call --
1854 -------------------------------------
1856 procedure Build_Protected_Subprogram_Call
1860 External : Boolean := True)
1862 Loc : constant Source_Ptr := Sloc (N);
1863 Sub : Entity_Id := Entity (Name);
1869 New_Sub := New_Occurrence_Of (External_Subprogram (Sub), Loc);
1872 New_Occurrence_Of (Protected_Body_Subprogram (Sub), Loc);
1875 if Present (Parameter_Associations (N)) then
1876 Params := New_Copy_List_Tree (Parameter_Associations (N));
1881 Prepend (Rec, Params);
1883 if Ekind (Sub) = E_Procedure then
1885 Make_Procedure_Call_Statement (Loc,
1887 Parameter_Associations => Params));
1890 pragma Assert (Ekind (Sub) = E_Function);
1892 Make_Function_Call (Loc,
1894 Parameter_Associations => Params));
1898 and then Nkind (Rec) = N_Unchecked_Type_Conversion
1899 and then Is_Entity_Name (Expression (Rec))
1900 and then Is_Shared_Passive (Entity (Expression (Rec)))
1902 Add_Shared_Var_Lock_Procs (N);
1905 end Build_Protected_Subprogram_Call;
1907 -------------------------
1908 -- Build_Selected_Name --
1909 -------------------------
1911 function Build_Selected_Name
1912 (Prefix, Selector : Name_Id;
1913 Append_Char : Character := ' ')
1916 Select_Buffer : String (1 .. Hostparm.Max_Name_Length);
1917 Select_Len : Natural;
1920 Get_Name_String (Selector);
1921 Select_Len := Name_Len;
1922 Select_Buffer (1 .. Select_Len) := Name_Buffer (1 .. Name_Len);
1923 Get_Name_String (Prefix);
1925 -- If scope is anonymous type, discard suffix to recover name of
1926 -- single protected object. Otherwise use protected type name.
1928 if Name_Buffer (Name_Len) = 'T' then
1929 Name_Len := Name_Len - 1;
1932 Name_Buffer (Name_Len + 1) := 'P';
1933 Name_Buffer (Name_Len + 2) := 'T';
1934 Name_Buffer (Name_Len + 3) := '_';
1935 Name_Buffer (Name_Len + 4) := '_';
1937 Name_Len := Name_Len + 4;
1938 for J in 1 .. Select_Len loop
1939 Name_Len := Name_Len + 1;
1940 Name_Buffer (Name_Len) := Select_Buffer (J);
1943 if Append_Char /= ' ' then
1944 Name_Len := Name_Len + 1;
1945 Name_Buffer (Name_Len) := Append_Char;
1949 end Build_Selected_Name;
1951 -----------------------------
1952 -- Build_Simple_Entry_Call --
1953 -----------------------------
1955 -- A task entry call is converted to a call to Call_Simple
1958 -- P : parms := (parm, parm, parm);
1960 -- Call_Simple (acceptor-task, entry-index, P'Address);
1966 -- Here Pnn is an aggregate of the type constructed for the entry to hold
1967 -- the parameters, and the constructed aggregate value contains either the
1968 -- parameters or, in the case of non-elementary types, references to these
1969 -- parameters. Then the address of this aggregate is passed to the runtime
1970 -- routine, along with the task id value and the task entry index value.
1971 -- Pnn is only required if parameters are present.
1973 -- The assignments after the call are present only in the case of in-out
1974 -- or out parameters for elementary types, and are used to assign back the
1975 -- resulting values of such parameters.
1977 -- Note: the reason that we insert a block here is that in the context
1978 -- of selects, conditional entry calls etc. the entry call statement
1979 -- appears on its own, not as an element of a list.
1981 -- A protected entry call is converted to a Protected_Entry_Call:
1984 -- P : E1_Params := (param, param, param);
1986 -- Bnn : Communications_Block;
1989 -- P : E1_Params := (param, param, param);
1990 -- Bnn : Communications_Block;
1993 -- Protected_Entry_Call (
1994 -- Object => po._object'Access,
1995 -- E => <entry index>;
1996 -- Uninterpreted_Data => P'Address;
1997 -- Mode => Simple_Call;
2004 procedure Build_Simple_Entry_Call
2013 -- Convert entry call to Call_Simple call
2016 Loc : constant Source_Ptr := Sloc (N);
2017 Parms : constant List_Id := Parameter_Associations (N);
2023 Ent_Acc : Entity_Id;
2035 Stats : List_Id := New_List;
2036 Comm_Name : Entity_Id;
2039 -- Simple entry and entry family cases merge here
2041 Ent := Entity (Ename);
2042 Ent_Acc := Entry_Parameters_Type (Ent);
2043 Conctyp := Etype (Concval);
2045 -- If prefix is an access type, dereference to obtain the task type
2047 if Is_Access_Type (Conctyp) then
2048 Conctyp := Designated_Type (Conctyp);
2051 -- Special case for protected subprogram calls.
2053 if Is_Protected_Type (Conctyp)
2054 and then Is_Subprogram (Entity (Ename))
2056 Build_Protected_Subprogram_Call
2057 (N, Ename, Convert_Concurrent (Concval, Conctyp));
2062 -- First parameter is the Task_Id value from the task value or the
2063 -- Object from the protected object value, obtained by selecting
2064 -- the _Task_Id or _Object from the result of doing an unchecked
2065 -- conversion to convert the value to the corresponding record type.
2067 Parm1 := Concurrent_Ref (Concval);
2069 -- Second parameter is the entry index, computed by the routine
2070 -- provided for this purpose. The value of this expression is
2071 -- assigned to an intermediate variable to assure that any entry
2072 -- family index expressions are evaluated before the entry
2076 or else Restrictions (No_Entry_Queue) = False
2077 or else not Is_Protected_Type (Conctyp)
2078 or else Number_Entries (Conctyp) > 1
2080 X := Make_Defining_Identifier (Loc, Name_uX);
2083 Make_Object_Declaration (Loc,
2084 Defining_Identifier => X,
2085 Object_Definition =>
2086 New_Reference_To (RTE (RE_Task_Entry_Index), Loc),
2087 Expression => Actual_Index_Expression (
2088 Loc, Entity (Ename), Index, Concval));
2090 Decls := New_List (Xdecl);
2091 Parm2 := New_Reference_To (X, Loc);
2099 -- The third parameter is the packaged parameters. If there are
2100 -- none, then it is just the null address, since nothing is passed
2103 Parm3 := New_Reference_To (RTE (RE_Null_Address), Loc);
2106 -- Case of parameters present, where third argument is the address
2107 -- of a packaged record containing the required parameter values.
2110 -- First build a list of parameter values, which are
2111 -- references to objects of the parameter types.
2115 Actual := First_Actual (N);
2116 Formal := First_Formal (Ent);
2118 while Present (Actual) loop
2120 -- If it is a by_copy_type, copy it to a new variable. The
2121 -- packaged record has a field that points to this variable.
2123 if Is_By_Copy_Type (Etype (Actual)) then
2125 Make_Object_Declaration (Loc,
2126 Defining_Identifier =>
2127 Make_Defining_Identifier (Loc,
2128 Chars => New_Internal_Name ('I')),
2129 Aliased_Present => True,
2130 Object_Definition =>
2131 New_Reference_To (Etype (Formal), Loc));
2133 -- We have to make an assignment statement separate for
2134 -- the case of limited type. We can not assign it unless
2135 -- the Assignment_OK flag is set first.
2137 if Ekind (Formal) /= E_Out_Parameter then
2139 New_Reference_To (Defining_Identifier (N_Node), Loc);
2140 Set_Assignment_OK (N_Var);
2142 Make_Assignment_Statement (Loc,
2144 Expression => Relocate_Node (Actual)));
2147 Append (N_Node, Decls);
2150 Make_Attribute_Reference (Loc,
2151 Attribute_Name => Name_Unchecked_Access,
2153 New_Reference_To (Defining_Identifier (N_Node), Loc)));
2156 Make_Reference (Loc, Prefix => Relocate_Node (Actual)));
2159 Next_Actual (Actual);
2160 Next_Formal_With_Extras (Formal);
2163 -- Now build the declaration of parameters initialized with the
2164 -- aggregate containing this constructed parameter list.
2166 P := Make_Defining_Identifier (Loc, Name_uP);
2169 Make_Object_Declaration (Loc,
2170 Defining_Identifier => P,
2171 Object_Definition =>
2172 New_Reference_To (Designated_Type (Ent_Acc), Loc),
2174 Make_Aggregate (Loc, Expressions => Plist));
2177 Make_Attribute_Reference (Loc,
2178 Attribute_Name => Name_Address,
2179 Prefix => New_Reference_To (P, Loc));
2181 Append (Pdecl, Decls);
2184 -- Now we can create the call, case of protected type
2186 if Is_Protected_Type (Conctyp) then
2188 or else Restrictions (No_Entry_Queue) = False
2189 or else Number_Entries (Conctyp) > 1
2191 -- Change the type of the index declaration
2193 Set_Object_Definition (Xdecl,
2194 New_Reference_To (RTE (RE_Protected_Entry_Index), Loc));
2196 -- Some additional declarations for protected entry calls
2202 -- Bnn : Communications_Block;
2205 Make_Defining_Identifier (Loc, New_Internal_Name ('B'));
2208 Make_Object_Declaration (Loc,
2209 Defining_Identifier => Comm_Name,
2210 Object_Definition =>
2211 New_Reference_To (RTE (RE_Communication_Block), Loc)));
2213 -- Some additional statements for protected entry calls
2215 -- Protected_Entry_Call (
2216 -- Object => po._object'Access,
2217 -- E => <entry index>;
2218 -- Uninterpreted_Data => P'Address;
2219 -- Mode => Simple_Call;
2223 Make_Procedure_Call_Statement (Loc,
2225 New_Reference_To (RTE (RE_Protected_Entry_Call), Loc),
2227 Parameter_Associations => New_List (
2228 Make_Attribute_Reference (Loc,
2229 Attribute_Name => Name_Unchecked_Access,
2233 New_Reference_To (RTE (RE_Simple_Call), Loc),
2234 New_Occurrence_Of (Comm_Name, Loc)));
2237 -- Protected_Single_Entry_Call (
2238 -- Object => po._object'Access,
2239 -- Uninterpreted_Data => P'Address;
2240 -- Mode => Simple_Call);
2243 Make_Procedure_Call_Statement (Loc,
2244 Name => New_Reference_To (
2245 RTE (RE_Protected_Single_Entry_Call), Loc),
2247 Parameter_Associations => New_List (
2248 Make_Attribute_Reference (Loc,
2249 Attribute_Name => Name_Unchecked_Access,
2252 New_Reference_To (RTE (RE_Simple_Call), Loc)));
2255 -- Case of task type
2259 Make_Procedure_Call_Statement (Loc,
2260 Name => New_Reference_To (RTE (RE_Call_Simple), Loc),
2261 Parameter_Associations => New_List (Parm1, Parm2, Parm3));
2265 Append_To (Stats, Call);
2267 -- If there are out or in/out parameters by copy
2268 -- add assignment statements for the result values.
2270 if Present (Parms) then
2271 Actual := First_Actual (N);
2272 Formal := First_Formal (Ent);
2274 Set_Assignment_OK (Actual);
2275 while Present (Actual) loop
2276 if Is_By_Copy_Type (Etype (Actual))
2277 and then Ekind (Formal) /= E_In_Parameter
2280 Make_Assignment_Statement (Loc,
2281 Name => New_Copy (Actual),
2283 Make_Explicit_Dereference (Loc,
2284 Make_Selected_Component (Loc,
2285 Prefix => New_Reference_To (P, Loc),
2287 Make_Identifier (Loc, Chars (Formal)))));
2289 -- In all cases (including limited private types) we
2290 -- want the assignment to be valid.
2292 Set_Assignment_OK (Name (N_Node));
2294 -- If the call is the triggering alternative in an
2295 -- asynchronous select, or the entry_call alternative
2296 -- of a conditional entry call, the assignments for in-out
2297 -- parameters are incorporated into the statement list
2298 -- that follows, so that there are executed only if the
2299 -- entry call succeeds.
2301 if (Nkind (Parent (N)) = N_Triggering_Alternative
2302 and then N = Triggering_Statement (Parent (N)))
2304 (Nkind (Parent (N)) = N_Entry_Call_Alternative
2305 and then N = Entry_Call_Statement (Parent (N)))
2307 if No (Statements (Parent (N))) then
2308 Set_Statements (Parent (N), New_List);
2311 Prepend (N_Node, Statements (Parent (N)));
2314 Insert_After (Call, N_Node);
2318 Next_Actual (Actual);
2319 Next_Formal_With_Extras (Formal);
2323 -- Finally, create block and analyze it
2326 Make_Block_Statement (Loc,
2327 Declarations => Decls,
2328 Handled_Statement_Sequence =>
2329 Make_Handled_Sequence_Of_Statements (Loc,
2330 Statements => Stats)));
2335 end Build_Simple_Entry_Call;
2337 --------------------------------
2338 -- Build_Task_Activation_Call --
2339 --------------------------------
2341 procedure Build_Task_Activation_Call (N : Node_Id) is
2342 Loc : constant Source_Ptr := Sloc (N);
2349 -- Get the activation chain entity. Except in the case of a package
2350 -- body, this is in the node that was passed. For a package body, we
2351 -- have to find the corresponding package declaration node.
2353 if Nkind (N) = N_Package_Body then
2354 P := Corresponding_Spec (N);
2358 exit when Nkind (P) = N_Package_Declaration;
2361 Chain := Activation_Chain_Entity (P);
2364 Chain := Activation_Chain_Entity (N);
2367 if Present (Chain) then
2368 if Restricted_Profile then
2369 Name := New_Reference_To (RTE (RE_Activate_Restricted_Tasks), Loc);
2371 Name := New_Reference_To (RTE (RE_Activate_Tasks), Loc);
2375 Make_Procedure_Call_Statement (Loc,
2377 Parameter_Associations =>
2378 New_List (Make_Attribute_Reference (Loc,
2379 Prefix => New_Occurrence_Of (Chain, Loc),
2380 Attribute_Name => Name_Unchecked_Access)));
2382 if Nkind (N) = N_Package_Declaration then
2383 if Present (Corresponding_Body (N)) then
2386 elsif Present (Private_Declarations (Specification (N))) then
2387 Append (Call, Private_Declarations (Specification (N)));
2390 Append (Call, Visible_Declarations (Specification (N)));
2394 if Present (Handled_Statement_Sequence (N)) then
2396 -- The call goes at the start of the statement sequence, but
2397 -- after the start of exception range label if one is present.
2403 Stm := First (Statements (Handled_Statement_Sequence (N)));
2405 if Nkind (Stm) = N_Label and then Exception_Junk (Stm) then
2409 Insert_Before (Stm, Call);
2413 Set_Handled_Statement_Sequence (N,
2414 Make_Handled_Sequence_Of_Statements (Loc,
2415 Statements => New_List (Call)));
2420 Check_Task_Activation (N);
2423 end Build_Task_Activation_Call;
2425 -------------------------------
2426 -- Build_Task_Allocate_Block --
2427 -------------------------------
2429 procedure Build_Task_Allocate_Block
2434 T : constant Entity_Id := Entity (Expression (N));
2435 Init : constant Entity_Id := Base_Init_Proc (T);
2436 Loc : constant Source_Ptr := Sloc (N);
2438 Chain : Entity_Id := Make_Defining_Identifier (Loc, Name_uChain);
2443 Blkent := Make_Defining_Identifier (Loc, New_Internal_Name ('A'));
2446 Make_Block_Statement (Loc,
2447 Identifier => New_Reference_To (Blkent, Loc),
2448 Declarations => New_List (
2450 -- _Chain : Activation_Chain;
2452 Make_Object_Declaration (Loc,
2453 Defining_Identifier => Chain,
2454 Aliased_Present => True,
2455 Object_Definition =>
2456 New_Reference_To (RTE (RE_Activation_Chain), Loc))),
2458 Handled_Statement_Sequence =>
2459 Make_Handled_Sequence_Of_Statements (Loc,
2461 Statements => New_List (
2465 Make_Procedure_Call_Statement (Loc,
2466 Name => New_Reference_To (Init, Loc),
2467 Parameter_Associations => Args),
2469 -- Activate_Tasks (_Chain);
2471 Make_Procedure_Call_Statement (Loc,
2472 Name => New_Reference_To (RTE (RE_Activate_Tasks), Loc),
2473 Parameter_Associations => New_List (
2474 Make_Attribute_Reference (Loc,
2475 Prefix => New_Reference_To (Chain, Loc),
2476 Attribute_Name => Name_Unchecked_Access))))),
2478 Has_Created_Identifier => True,
2479 Is_Task_Allocation_Block => True);
2482 Make_Implicit_Label_Declaration (Loc,
2483 Defining_Identifier => Blkent,
2484 Label_Construct => Block));
2486 Append_To (Actions, Block);
2488 Set_Activation_Chain_Entity (Block, Chain);
2490 end Build_Task_Allocate_Block;
2492 -----------------------------------
2493 -- Build_Task_Proc_Specification --
2494 -----------------------------------
2496 function Build_Task_Proc_Specification (T : Entity_Id) return Node_Id is
2497 Loc : constant Source_Ptr := Sloc (T);
2498 Nam : constant Name_Id := Chars (T);
2499 Tdec : constant Node_Id := Declaration_Node (T);
2504 Make_Defining_Identifier (Loc,
2505 Chars => New_External_Name (Nam, 'B'));
2506 Set_Is_Internal (Ent);
2508 -- Associate the procedure with the task, if this is the declaration
2509 -- (and not the body) of the procedure.
2511 if No (Task_Body_Procedure (Tdec)) then
2512 Set_Task_Body_Procedure (Tdec, Ent);
2516 Make_Procedure_Specification (Loc,
2517 Defining_Unit_Name => Ent,
2518 Parameter_Specifications =>
2520 Make_Parameter_Specification (Loc,
2521 Defining_Identifier =>
2522 Make_Defining_Identifier (Loc, Name_uTask),
2524 Make_Access_Definition (Loc,
2527 (Corresponding_Record_Type (T), Loc)))));
2529 end Build_Task_Proc_Specification;
2531 ---------------------------------------
2532 -- Build_Unprotected_Subprogram_Body --
2533 ---------------------------------------
2535 function Build_Unprotected_Subprogram_Body
2540 Loc : constant Source_Ptr := Sloc (N);
2542 N_Op_Spec : Node_Id;
2546 -- Make an unprotected version of the subprogram for use
2547 -- within the same object, with a new name and an additional
2548 -- parameter representing the object.
2550 Op_Decls := Declarations (N);
2551 Sub_Name := Chars (Defining_Unit_Name (Specification (N)));
2554 Build_Protected_Sub_Specification
2555 (N, Pid, Unprotected => True);
2558 Make_Subprogram_Body (Loc,
2559 Specification => N_Op_Spec,
2560 Declarations => Op_Decls,
2561 Handled_Statement_Sequence =>
2562 Handled_Statement_Sequence (N));
2564 end Build_Unprotected_Subprogram_Body;
2566 ----------------------------
2567 -- Collect_Entry_Families --
2568 ----------------------------
2570 procedure Collect_Entry_Families
2573 Current_Node : in out Node_Id;
2574 Conctyp : Entity_Id)
2577 Efam_Decl : Node_Id;
2578 Efam_Type : Entity_Id;
2581 Efam := First_Entity (Conctyp);
2583 while Present (Efam) loop
2585 if Ekind (Efam) = E_Entry_Family then
2587 Make_Defining_Identifier (Loc,
2588 Chars => New_Internal_Name ('F'));
2591 Make_Full_Type_Declaration (Loc,
2592 Defining_Identifier => Efam_Type,
2594 Make_Unconstrained_Array_Definition (Loc,
2595 Subtype_Marks => (New_List (
2598 (Etype (Discrete_Subtype_Definition
2599 (Parent (Efam)))), Loc))),
2601 Subtype_Indication =>
2602 New_Reference_To (Standard_Character, Loc)));
2604 Insert_After (Current_Node, Efam_Decl);
2605 Current_Node := Efam_Decl;
2606 Analyze (Efam_Decl);
2609 Make_Component_Declaration (Loc,
2610 Defining_Identifier =>
2611 Make_Defining_Identifier (Loc, Chars (Efam)),
2613 Subtype_Indication =>
2614 Make_Subtype_Indication (Loc,
2616 New_Occurrence_Of (Efam_Type, Loc),
2619 Make_Index_Or_Discriminant_Constraint (Loc,
2620 Constraints => New_List (
2622 (Etype (Discrete_Subtype_Definition
2623 (Parent (Efam))), Loc))))));
2628 end Collect_Entry_Families;
2630 --------------------
2631 -- Concurrent_Ref --
2632 --------------------
2634 -- The expression returned for a reference to a concurrent
2635 -- object has the form:
2637 -- taskV!(name)._Task_Id
2641 -- objectV!(name)._Object
2643 -- for a protected object.
2645 -- For the case of an access to a concurrent object,
2646 -- there is an extra explicit dereference:
2648 -- taskV!(name.all)._Task_Id
2649 -- objectV!(name.all)._Object
2651 -- here taskV and objectV are the types for the associated records, which
2652 -- contain the required _Task_Id and _Object fields for tasks and
2653 -- protected objects, respectively.
2655 -- For the case of a task type name, the expression is
2659 -- i.e. a call to the Self function which returns precisely this Task_Id
2661 -- For the case of a protected type name, the expression is
2665 -- which is a renaming of the _object field of the current object
2666 -- object record, passed into protected operations as a parameter.
2668 function Concurrent_Ref (N : Node_Id) return Node_Id is
2669 Loc : constant Source_Ptr := Sloc (N);
2670 Ntyp : constant Entity_Id := Etype (N);
2674 function Is_Current_Task (T : Entity_Id) return Boolean;
2675 -- Check whether the reference is to the immediately enclosing task
2676 -- type, or to an outer one (rare but legal).
2678 ---------------------
2679 -- Is_Current_Task --
2680 ---------------------
2682 function Is_Current_Task (T : Entity_Id) return Boolean is
2686 Scop := Current_Scope;
2687 while Present (Scop)
2688 and then Scop /= Standard_Standard
2694 elsif Is_Task_Type (Scop) then
2697 -- If this is a procedure nested within the task type, we must
2698 -- assume that it can be called from an inner task, and therefore
2699 -- cannot treat it as a local reference.
2701 elsif Is_Overloadable (Scop)
2702 and then In_Open_Scopes (T)
2707 Scop := Scope (Scop);
2711 -- We know that we are within the task body, so should have
2712 -- found it in scope.
2714 raise Program_Error;
2715 end Is_Current_Task;
2717 -- Start of processing for Concurrent_Ref
2720 if Is_Access_Type (Ntyp) then
2721 Dtyp := Designated_Type (Ntyp);
2723 if Is_Protected_Type (Dtyp) then
2724 Sel := Name_uObject;
2726 Sel := Name_uTask_Id;
2730 Make_Selected_Component (Loc,
2732 Unchecked_Convert_To (Corresponding_Record_Type (Dtyp),
2733 Make_Explicit_Dereference (Loc, N)),
2734 Selector_Name => Make_Identifier (Loc, Sel));
2736 elsif Is_Entity_Name (N)
2737 and then Is_Concurrent_Type (Entity (N))
2739 if Is_Task_Type (Entity (N)) then
2741 if Is_Current_Task (Entity (N)) then
2743 Make_Function_Call (Loc,
2744 Name => New_Reference_To (RTE (RE_Self), Loc));
2749 T_Self : constant Entity_Id
2750 := Make_Defining_Identifier (Loc, New_Internal_Name ('T'));
2751 T_Body : constant Node_Id
2752 := Parent (Corresponding_Body (Parent (Entity (N))));
2755 Decl := Make_Object_Declaration (Loc,
2756 Defining_Identifier => T_Self,
2757 Object_Definition =>
2758 New_Occurrence_Of (RTE (RO_ST_Task_ID), Loc),
2760 Make_Function_Call (Loc,
2761 Name => New_Reference_To (RTE (RE_Self), Loc)));
2762 Prepend (Decl, Declarations (T_Body));
2764 Set_Scope (T_Self, Entity (N));
2765 return New_Occurrence_Of (T_Self, Loc);
2770 pragma Assert (Is_Protected_Type (Entity (N)));
2773 Object_Ref (Corresponding_Body (Parent (Base_Type (Ntyp)))),
2778 pragma Assert (Is_Concurrent_Type (Ntyp));
2780 if Is_Protected_Type (Ntyp) then
2781 Sel := Name_uObject;
2783 Sel := Name_uTask_Id;
2787 Make_Selected_Component (Loc,
2789 Unchecked_Convert_To (Corresponding_Record_Type (Ntyp),
2791 Selector_Name => Make_Identifier (Loc, Sel));
2795 ------------------------
2796 -- Convert_Concurrent --
2797 ------------------------
2799 function Convert_Concurrent
2805 if not Is_Concurrent_Type (Typ) then
2809 Unchecked_Convert_To (Corresponding_Record_Type (Typ),
2812 end Convert_Concurrent;
2814 ----------------------------
2815 -- Entry_Index_Expression --
2816 ----------------------------
2818 function Entry_Index_Expression
2833 -- The queues of entries and entry families appear in textual
2834 -- order in the associated record. The entry index is computed as
2835 -- the sum of the number of queues for all entries that precede the
2836 -- designated one, to which is added the index expression, if this
2837 -- expression denotes a member of a family.
2839 -- The following is a place holder for the count of simple entries.
2841 Num := Make_Integer_Literal (Sloc, 1);
2843 -- We construct an expression which is a series of addition
2844 -- operations. The first operand is the number of single entries that
2845 -- precede this one, the second operand is the index value relative
2846 -- to the start of the referenced family, and the remaining operands
2847 -- are the lengths of the entry families that precede this entry, i.e.
2848 -- the constructed expression is:
2850 -- number_simple_entries +
2851 -- (s'pos (index-value) - s'pos (family'first)) + 1 +
2852 -- family'length + ...
2854 -- where index-value is the given index value, and s is the index
2855 -- subtype (we have to use pos because the subtype might be an
2856 -- enumeration type preventing direct subtraction).
2857 -- Note that the task entry array is one-indexed.
2859 -- The upper bound of the entry family may be a discriminant, so we
2860 -- retrieve the lower bound explicitly to compute offset, rather than
2861 -- using the index subtype which may mention a discriminant.
2863 if Present (Index) then
2864 S := Etype (Discrete_Subtype_Definition (Declaration_Node (Ent)));
2873 Make_Attribute_Reference (Sloc,
2874 Attribute_Name => Name_Pos,
2875 Prefix => New_Reference_To (Base_Type (S), Sloc),
2876 Expressions => New_List (Relocate_Node (Index))),
2883 -- Now add lengths of preceding entries and entry families.
2885 Prev := First_Entity (Ttyp);
2887 while Chars (Prev) /= Chars (Ent)
2888 or else (Ekind (Prev) /= Ekind (Ent))
2889 or else not Sem_Ch6.Type_Conformant (Ent, Prev)
2891 if Ekind (Prev) = E_Entry then
2892 Set_Intval (Num, Intval (Num) + 1);
2894 elsif Ekind (Prev) = E_Entry_Family then
2896 Etype (Discrete_Subtype_Definition (Declaration_Node (Prev)));
2897 Lo := Type_Low_Bound (S);
2898 Hi := Type_High_Bound (S);
2903 Right_Opnd => Family_Size (Sloc, Hi, Lo, Ttyp));
2905 -- Other components are anonymous types to be ignored.
2915 end Entry_Index_Expression;
2917 ---------------------------
2918 -- Establish_Task_Master --
2919 ---------------------------
2921 procedure Establish_Task_Master (N : Node_Id) is
2925 if Restrictions (No_Task_Hierarchy) = False then
2926 Call := Build_Runtime_Call (Sloc (N), RE_Enter_Master);
2927 Prepend_To (Declarations (N), Call);
2930 end Establish_Task_Master;
2932 --------------------------------
2933 -- Expand_Accept_Declarations --
2934 --------------------------------
2936 -- Part of the expansion of an accept statement involves the creation of
2937 -- a declaration that can be referenced from the statement sequence of
2942 -- This declaration is inserted immediately before the accept statement
2943 -- and it is important that it be inserted before the statements of the
2944 -- statement sequence are analyzed. Thus it would be too late to create
2945 -- this declaration in the Expand_N_Accept_Statement routine, which is
2946 -- why there is a separate procedure to be called directly from Sem_Ch9.
2948 -- Ann is used to hold the address of the record containing the parameters
2949 -- (see Expand_N_Entry_Call for more details on how this record is built).
2950 -- References to the parameters do an unchecked conversion of this address
2951 -- to a pointer to the required record type, and then access the field that
2952 -- holds the value of the required parameter. The entity for the address
2953 -- variable is held as the top stack element (i.e. the last element) of the
2954 -- Accept_Address stack in the corresponding entry entity, and this element
2955 -- must be set in place before the statements are processed.
2957 -- The above description applies to the case of a stand alone accept
2958 -- statement, i.e. one not appearing as part of a select alternative.
2960 -- For the case of an accept that appears as part of a select alternative
2961 -- of a selective accept, we must still create the declaration right away,
2962 -- since Ann is needed immediately, but there is an important difference:
2964 -- The declaration is inserted before the selective accept, not before
2965 -- the accept statement (which is not part of a list anyway, and so would
2966 -- not accommodate inserted declarations)
2968 -- We only need one address variable for the entire selective accept. So
2969 -- the Ann declaration is created only for the first accept alternative,
2970 -- and subsequent accept alternatives reference the same Ann variable.
2972 -- We can distinguish the two cases by seeing whether the accept statement
2973 -- is part of a list. If not, then it must be in an accept alternative.
2975 -- To expand the requeue statement, a label is provided at the end of
2976 -- the accept statement or alternative of which it is a part, so that
2977 -- the statement can be skipped after the requeue is complete.
2978 -- This label is created here rather than during the expansion of the
2979 -- accept statement, because it will be needed by any requeue
2980 -- statements within the accept, which are expanded before the
2983 procedure Expand_Accept_Declarations (N : Node_Id; Ent : Entity_Id) is
2984 Loc : constant Source_Ptr := Sloc (N);
2985 Ann : Entity_Id := Empty;
2993 if Expander_Active then
2995 -- If we have no handled statement sequence, then build a dummy
2996 -- sequence consisting of a null statement. This is only done if
2997 -- pragma FIFO_Within_Priorities is specified. The issue here is
2998 -- that even a null accept body has an effect on the called task
2999 -- in terms of its position in the queue, so we cannot optimize
3000 -- the context switch away. However, if FIFO_Within_Priorities
3001 -- is not active, the optimization is legitimate, since we can
3002 -- say that our dispatching policy (i.e. the default dispatching
3003 -- policy) reorders the queue to be the same as just before the
3004 -- call. In the absence of a specified dispatching policy, we are
3005 -- allowed to modify queue orders for a given priority at will!
3007 if Opt.Task_Dispatching_Policy = 'F' and then
3008 not Present (Handled_Statement_Sequence (N))
3010 Set_Handled_Statement_Sequence (N,
3011 Make_Handled_Sequence_Of_Statements (Loc,
3012 New_List (Make_Null_Statement (Loc))));
3015 -- Create and declare two labels to be placed at the end of the
3016 -- accept statement. The first label is used to allow requeues to
3017 -- skip the remainder of entry processing. The second label is
3018 -- used to skip the remainder of entry processing if the rendezvous
3019 -- completes in the middle of the accept body.
3021 if Present (Handled_Statement_Sequence (N)) then
3022 Lab_Id := Make_Identifier (Loc, New_Internal_Name ('L'));
3024 Make_Defining_Identifier (Loc, Chars (Lab_Id)));
3025 Lab := Make_Label (Loc, Lab_Id);
3027 Make_Implicit_Label_Declaration (Loc,
3028 Defining_Identifier => Entity (Lab_Id),
3029 Label_Construct => Lab);
3030 Append (Lab, Statements (Handled_Statement_Sequence (N)));
3032 Lab_Id := Make_Identifier (Loc, New_Internal_Name ('L'));
3034 Make_Defining_Identifier (Loc, Chars (Lab_Id)));
3035 Lab := Make_Label (Loc, Lab_Id);
3037 Make_Implicit_Label_Declaration (Loc,
3038 Defining_Identifier => Entity (Lab_Id),
3039 Label_Construct => Lab);
3040 Append (Lab, Statements (Handled_Statement_Sequence (N)));
3047 -- Case of stand alone accept statement
3049 if Is_List_Member (N) then
3051 if Present (Handled_Statement_Sequence (N)) then
3053 Make_Defining_Identifier (Loc,
3054 Chars => New_Internal_Name ('A'));
3057 Make_Object_Declaration (Loc,
3058 Defining_Identifier => Ann,
3059 Object_Definition =>
3060 New_Reference_To (RTE (RE_Address), Loc));
3062 Insert_Before (N, Adecl);
3065 Insert_Before (N, Ldecl);
3068 Insert_Before (N, Ldecl2);
3072 -- Case of accept statement which is in an accept alternative
3076 Acc_Alt : constant Node_Id := Parent (N);
3077 Sel_Acc : constant Node_Id := Parent (Acc_Alt);
3081 pragma Assert (Nkind (Acc_Alt) = N_Accept_Alternative);
3082 pragma Assert (Nkind (Sel_Acc) = N_Selective_Accept);
3084 -- ??? Consider a single label for select statements.
3086 if Present (Handled_Statement_Sequence (N)) then
3088 Statements (Handled_Statement_Sequence (N)));
3092 Statements (Handled_Statement_Sequence (N)));
3096 -- Find first accept alternative of the selective accept. A
3097 -- valid selective accept must have at least one accept in it.
3099 Alt := First (Select_Alternatives (Sel_Acc));
3101 while Nkind (Alt) /= N_Accept_Alternative loop
3105 -- If we are the first accept statement, then we have to
3106 -- create the Ann variable, as for the stand alone case,
3107 -- except that it is inserted before the selective accept.
3108 -- Similarly, a label for requeue expansion must be
3111 if N = Accept_Statement (Alt) then
3113 Make_Defining_Identifier (Loc, New_Internal_Name ('A'));
3116 Make_Object_Declaration (Loc,
3117 Defining_Identifier => Ann,
3118 Object_Definition =>
3119 New_Reference_To (RTE (RE_Address), Loc));
3121 Insert_Before (Sel_Acc, Adecl);
3124 -- If we are not the first accept statement, then find the
3125 -- Ann variable allocated by the first accept and use it.
3129 Node (Last_Elmt (Accept_Address
3130 (Entity (Entry_Direct_Name (Accept_Statement (Alt))))));
3135 -- Merge here with Ann either created or referenced, and Adecl
3136 -- pointing to the corresponding declaration. Remaining processing
3137 -- is the same for the two cases.
3139 if Present (Ann) then
3140 Append_Elmt (Ann, Accept_Address (Ent));
3143 end Expand_Accept_Declarations;
3145 ---------------------------------------------
3146 -- Expand_Access_Protected_Subprogram_Type --
3147 ---------------------------------------------
3149 procedure Expand_Access_Protected_Subprogram_Type (N : Node_Id) is
3150 Loc : constant Source_Ptr := Sloc (N);
3152 T : constant Entity_Id := Defining_Identifier (N);
3153 D_T : constant Entity_Id := Designated_Type (T);
3154 D_T2 : constant Entity_Id := Make_Defining_Identifier
3155 (Loc, New_Internal_Name ('D'));
3156 E_T : constant Entity_Id := Make_Defining_Identifier
3157 (Loc, New_Internal_Name ('E'));
3158 P_List : constant List_Id := Build_Protected_Spec
3159 (N, RTE (RE_Address), False, D_T);
3165 -- Create access to protected subprogram with full signature.
3167 if Nkind (Type_Definition (N)) = N_Access_Function_Definition then
3169 Make_Access_Function_Definition (Loc,
3170 Parameter_Specifications => P_List,
3171 Subtype_Mark => New_Copy (Subtype_Mark (Type_Definition (N))));
3175 Make_Access_Procedure_Definition (Loc,
3176 Parameter_Specifications => P_List);
3180 Make_Full_Type_Declaration (Loc,
3181 Defining_Identifier => D_T2,
3182 Type_Definition => Def1);
3184 Insert_After (N, Decl1);
3186 -- Create Equivalent_Type, a record with two components for an
3187 -- an access to object an an access to subprogram.
3190 Make_Component_Declaration (Loc,
3191 Defining_Identifier =>
3192 Make_Defining_Identifier (Loc, New_Internal_Name ('P')),
3193 Subtype_Indication =>
3194 New_Occurrence_Of (RTE (RE_Address), Loc)),
3196 Make_Component_Declaration (Loc,
3197 Defining_Identifier =>
3198 Make_Defining_Identifier (Loc, New_Internal_Name ('S')),
3199 Subtype_Indication =>
3200 New_Occurrence_Of (D_T2, Loc)));
3203 Make_Full_Type_Declaration (Loc,
3204 Defining_Identifier => E_T,
3206 Make_Record_Definition (Loc,
3208 Make_Component_List (Loc,
3209 Component_Items => Comps)));
3211 Insert_After (Decl1, Decl2);
3212 Set_Equivalent_Type (T, E_T);
3214 end Expand_Access_Protected_Subprogram_Type;
3216 --------------------------
3217 -- Expand_Entry_Barrier --
3218 --------------------------
3220 procedure Expand_Entry_Barrier (N : Node_Id; Ent : Entity_Id) is
3221 Loc : constant Source_Ptr := Sloc (N);
3224 Prot : constant Entity_Id := Scope (Ent);
3225 Spec_Decl : Node_Id := Parent (Prot);
3226 Body_Decl : Node_Id;
3227 Cond : Node_Id := Condition (Entry_Body_Formal_Part (N));
3230 -- The body of the entry barrier must be analyzed in the context of
3231 -- the protected object, but its scope is external to it, just as any
3232 -- other unprotected version of a protected operation. The specification
3233 -- has been produced when the protected type declaration was elaborated.
3234 -- We build the body, insert it in the enclosing scope, but analyze it
3235 -- in the current context. A more uniform approach would be to treat a
3236 -- barrier just as a protected function, and discard the protected
3237 -- version of it because it is never called.
3239 if Expander_Active then
3240 B_F := Build_Barrier_Function (N, Ent, Prot);
3241 Func := Barrier_Function (Ent);
3242 Set_Corresponding_Spec (B_F, Func);
3244 Body_Decl := Parent (Corresponding_Body (Spec_Decl));
3246 if Nkind (Parent (Body_Decl)) = N_Subunit then
3247 Body_Decl := Corresponding_Stub (Parent (Body_Decl));
3250 Insert_Before_And_Analyze (Body_Decl, B_F);
3252 Update_Prival_Subtypes (B_F);
3254 Set_Privals (Spec_Decl, N, Loc);
3255 Set_Discriminals (Spec_Decl);
3256 Set_Scope (Func, Scope (Prot));
3261 -- The Ravenscar profile restricts barriers to simple variables
3262 -- declared within the protected object. We also allow Boolean
3263 -- constants, since these appear in several published examples
3264 -- and are also allowed by the Aonix compiler.
3266 -- Note that after analysis variables in this context will be
3267 -- replaced by the corresponding prival, that is to say a renaming
3268 -- of a selected component of the form _Object.Var. If expansion is
3269 -- disabled, as within a generic, we check that the entity appears in
3270 -- the current scope.
3272 if Is_Entity_Name (Cond) then
3274 if Entity (Cond) = Standard_False
3276 Entity (Cond) = Standard_True
3280 elsif not Expander_Active
3281 and then Scope (Entity (Cond)) = Current_Scope
3285 elsif Present (Renamed_Object (Entity (Cond)))
3287 Nkind (Renamed_Object (Entity (Cond))) = N_Selected_Component
3289 Chars (Prefix (Renamed_Object (Entity (Cond)))) = Name_uObject
3295 -- It is not a boolean variable or literal, so check the restriction
3297 Check_Restriction (Boolean_Entry_Barriers, Cond);
3298 end Expand_Entry_Barrier;
3300 ------------------------------------
3301 -- Expand_Entry_Body_Declarations --
3302 ------------------------------------
3304 procedure Expand_Entry_Body_Declarations (N : Node_Id) is
3305 Loc : constant Source_Ptr := Sloc (N);
3306 Index_Spec : Node_Id;
3309 if Expander_Active then
3311 -- Expand entry bodies corresponding to entry families
3312 -- by assigning a placeholder for the constant that will
3313 -- be used to expand references to the entry index parameter.
3316 Entry_Index_Specification (Entry_Body_Formal_Part (N));
3318 if Present (Index_Spec) then
3319 Set_Entry_Index_Constant (
3320 Defining_Identifier (Index_Spec),
3321 Make_Defining_Identifier (Loc, New_Internal_Name ('I')));
3325 end Expand_Entry_Body_Declarations;
3327 ------------------------------
3328 -- Expand_N_Abort_Statement --
3329 ------------------------------
3331 -- Expand abort T1, T2, .. Tn; into:
3332 -- Abort_Tasks (Task_List'(1 => T1.Task_Id, 2 => T2.Task_Id ...))
3334 procedure Expand_N_Abort_Statement (N : Node_Id) is
3335 Loc : constant Source_Ptr := Sloc (N);
3336 Tlist : constant List_Id := Names (N);
3342 Aggr := Make_Aggregate (Loc, Component_Associations => New_List);
3345 Tasknm := First (Tlist);
3347 while Present (Tasknm) loop
3349 Append_To (Component_Associations (Aggr),
3350 Make_Component_Association (Loc,
3351 Choices => New_List (
3352 Make_Integer_Literal (Loc, Count)),
3353 Expression => Concurrent_Ref (Tasknm)));
3358 Make_Procedure_Call_Statement (Loc,
3359 Name => New_Reference_To (RTE (RE_Abort_Tasks), Loc),
3360 Parameter_Associations => New_List (
3361 Make_Qualified_Expression (Loc,
3362 Subtype_Mark => New_Reference_To (RTE (RE_Task_List), Loc),
3363 Expression => Aggr))));
3367 end Expand_N_Abort_Statement;
3369 -------------------------------
3370 -- Expand_N_Accept_Statement --
3371 -------------------------------
3373 -- This procedure handles expansion of accept statements that stand
3374 -- alone, i.e. they are not part of an accept alternative. The expansion
3375 -- of accept statement in accept alternatives is handled by the routines
3376 -- Expand_N_Accept_Alternative and Expand_N_Selective_Accept. The
3377 -- following description applies only to stand alone accept statements.
3379 -- If there is no handled statement sequence, or only null statements,
3380 -- then this is called a trivial accept, and the expansion is:
3382 -- Accept_Trivial (entry-index)
3384 -- If there is a handled statement sequence, then the expansion is:
3391 -- Accept_Call (entry-index, Ann);
3392 -- <statement sequence from N_Accept_Statement node>
3393 -- Complete_Rendezvous;
3398 -- <exception handler from N_Accept_Statement node>
3399 -- Complete_Rendezvous;
3401 -- <exception handler from N_Accept_Statement node>
3402 -- Complete_Rendezvous;
3407 -- when all others =>
3408 -- Exceptional_Complete_Rendezvous (Get_GNAT_Exception);
3411 -- The first three declarations were already inserted ahead of the
3412 -- accept statement by the Expand_Accept_Declarations procedure, which
3413 -- was called directly from the semantics during analysis of the accept.
3414 -- statement, before analyzing its contained statements.
3416 -- The declarations from the N_Accept_Statement, as noted in Sinfo, come
3417 -- from possible expansion activity (the original source of course does
3418 -- not have any declarations associated with the accept statement, since
3419 -- an accept statement has no declarative part). In particular, if the
3420 -- expander is active, the first such declaration is the declaration of
3421 -- the Accept_Params_Ptr entity (see Sem_Ch9.Analyze_Accept_Statement).
3423 -- The two blocks are merged into a single block if the inner block has
3424 -- no exception handlers, but otherwise two blocks are required, since
3425 -- exceptions might be raised in the exception handlers of the inner
3426 -- block, and Exceptional_Complete_Rendezvous must be called.
3428 procedure Expand_N_Accept_Statement (N : Node_Id) is
3429 Loc : constant Source_Ptr := Sloc (N);
3430 Stats : constant Node_Id := Handled_Statement_Sequence (N);
3431 Ename : constant Node_Id := Entry_Direct_Name (N);
3432 Eindx : constant Node_Id := Entry_Index (N);
3433 Eent : constant Entity_Id := Entity (Ename);
3434 Acstack : constant Elist_Id := Accept_Address (Eent);
3435 Ann : constant Entity_Id := Node (Last_Elmt (Acstack));
3436 Ttyp : constant Entity_Id := Etype (Scope (Eent));
3440 function Null_Statements (Stats : List_Id) return Boolean;
3441 -- Check for null statement sequence (i.e a list of labels and
3444 function Null_Statements (Stats : List_Id) return Boolean is
3448 Stmt := First (Stats);
3449 while Nkind (Stmt) /= N_Empty
3450 and then (Nkind (Stmt) = N_Null_Statement
3452 Nkind (Stmt) = N_Label)
3457 return Nkind (Stmt) = N_Empty;
3458 end Null_Statements;
3460 -- Start of processing for Expand_N_Accept_Statement
3463 -- If accept statement is not part of a list, then its parent must be
3464 -- an accept alternative, and, as described above, we do not do any
3465 -- expansion for such accept statements at this level.
3467 if not Is_List_Member (N) then
3468 pragma Assert (Nkind (Parent (N)) = N_Accept_Alternative);
3471 -- Trivial accept case (no statement sequence, or null statements).
3472 -- If the accept statement has declarations, then just insert them
3473 -- before the procedure call.
3475 -- We avoid this optimization when FIFO_Within_Priorities is active,
3476 -- since it is not correct according to annex D semantics. The problem
3477 -- is that the call is required to reorder the acceptors position on
3478 -- its ready queue, even though there is nothing to be done. However,
3479 -- if no policy is specified, then we decide that our dispatching
3480 -- policy always reorders the queue right after the RV to look the
3481 -- way they were just before the RV. Since we are allowed to freely
3482 -- reorder same-priority queues (this is part of what dispatching
3483 -- policies are all about), the optimization is legitimate.
3485 elsif Opt.Task_Dispatching_Policy /= 'F'
3486 and then (No (Stats) or else Null_Statements (Statements (Stats)))
3488 if Present (Declarations (N)) then
3489 Insert_Actions (N, Declarations (N));
3493 Make_Procedure_Call_Statement (Loc,
3494 Name => New_Reference_To (RTE (RE_Accept_Trivial), Loc),
3495 Parameter_Associations => New_List (
3496 Entry_Index_Expression (Loc, Entity (Ename), Eindx, Ttyp))));
3500 -- Discard Entry_Address that was created for it, so it will not be
3501 -- emitted if this accept statement is in the statement part of a
3502 -- delay alternative.
3504 if Present (Stats) then
3505 Remove_Last_Elmt (Acstack);
3508 -- Case of statement sequence present
3511 -- Construct the block, using the declarations from the accept
3512 -- statement if any to initialize the declarations of the block.
3515 Make_Block_Statement (Loc,
3516 Declarations => Declarations (N),
3517 Handled_Statement_Sequence => Build_Accept_Body (N));
3519 -- Prepend call to Accept_Call to main statement sequence
3522 Make_Procedure_Call_Statement (Loc,
3523 Name => New_Reference_To (RTE (RE_Accept_Call), Loc),
3524 Parameter_Associations => New_List (
3525 Entry_Index_Expression (Loc, Entity (Ename), Eindx, Ttyp),
3526 New_Reference_To (Ann, Loc)));
3528 Prepend (Call, Statements (Stats));
3531 -- Replace the accept statement by the new block
3536 -- Last step is to unstack the Accept_Address value
3538 Remove_Last_Elmt (Acstack);
3541 end Expand_N_Accept_Statement;
3543 ----------------------------------
3544 -- Expand_N_Asynchronous_Select --
3545 ----------------------------------
3547 -- This procedure assumes that the trigger statement is an entry
3548 -- call. A delay alternative should already have been expanded
3549 -- into an entry call to the appropriate delay object Wait entry.
3551 -- If the trigger is a task entry call, the select is implemented
3552 -- with Task_Entry_Call:
3557 -- P : parms := (parm, parm, parm);
3559 -- -- Clean is added by Exp_Ch7.Expand_Cleanup_Actions.
3561 -- procedure _clean is
3564 -- Cancel_Task_Entry_Call (C);
3573 -- Asynchronous_Call,
3580 -- _clean; -- Added by Exp_Ch7.Expand_Cleanup_Actions.
3583 -- when Abort_Signal => Abort_Undefer;
3589 -- triggered-statements
3593 -- Note that Build_Simple_Entry_Call is used to expand the entry
3594 -- of the asynchronous entry call (by the
3595 -- Expand_N_Entry_Call_Statement procedure) as follows:
3598 -- P : parms := (parm, parm, parm);
3600 -- Call_Simple (acceptor-task, entry-index, P'Address);
3606 -- so the task at hand is to convert the latter expansion into the former
3608 -- If the trigger is a protected entry call, the select is
3609 -- implemented with Protected_Entry_Call:
3612 -- P : E1_Params := (param, param, param);
3613 -- Bnn : Communications_Block;
3617 -- -- Clean is added by Exp_Ch7.Expand_Cleanup_Actions.
3619 -- procedure _clean is
3622 -- if Enqueued (Bnn) then
3623 -- Cancel_Protected_Entry_Call (Bnn);
3629 -- Protected_Entry_Call (
3630 -- Object => po._object'Access,
3631 -- E => <entry index>;
3632 -- Uninterpreted_Data => P'Address;
3633 -- Mode => Asynchronous_Call;
3635 -- if Enqueued (Bnn) then
3639 -- _clean; -- Added by Exp_Ch7.Expand_Cleanup_Actions.
3642 -- when Abort_Signal =>
3646 -- if not Cancelled (Bnn) then
3647 -- triggered statements
3651 -- Build_Simple_Entry_Call is used to expand the all to a simple
3652 -- protected entry call:
3655 -- P : E1_Params := (param, param, param);
3656 -- Bnn : Communications_Block;
3659 -- Protected_Entry_Call (
3660 -- Object => po._object'Access,
3661 -- E => <entry index>;
3662 -- Uninterpreted_Data => P'Address;
3663 -- Mode => Simple_Call;
3670 -- The job is to convert this to the asynchronous form.
3672 -- If the trigger is a delay statement, it will have been expanded
3673 -- into a call to one of the GNARL delay procedures. This routine
3674 -- will convert this into a protected entry call on a delay object
3675 -- and then continue processing as for a protected entry call trigger.
3676 -- This requires declaring a Delay_Block object and adding a pointer
3677 -- to this object to the parameter list of the delay procedure to form
3678 -- the parameter list of the entry call. This object is used by
3679 -- the runtime to queue the delay request.
3681 -- For a description of the use of P and the assignments after the
3682 -- call, see Expand_N_Entry_Call_Statement.
3684 procedure Expand_N_Asynchronous_Select (N : Node_Id) is
3685 Loc : constant Source_Ptr := Sloc (N);
3686 Trig : constant Node_Id := Triggering_Alternative (N);
3687 Abrt : constant Node_Id := Abortable_Part (N);
3688 Tstats : constant List_Id := Statements (Trig);
3691 Astats : List_Id := Statements (Abrt);
3702 Enqueue_Call : Node_Id;
3706 Dblock_Ent : Entity_Id;
3708 Abortable_Block : Node_Id;
3709 Cancel_Param : Entity_Id;
3711 Target_Undefer : RE_Id;
3712 Undefer_Args : List_Id := No_List;
3715 Blkent := Make_Defining_Identifier (Loc, New_Internal_Name ('A'));
3716 Ecall := Triggering_Statement (Trig);
3718 -- The arguments in the call may require dynamic allocation, and the
3719 -- call statement may have been transformed into a block. The block
3720 -- may contain additional declarations for internal entities, and the
3721 -- original call is found by sequential search.
3723 if Nkind (Ecall) = N_Block_Statement then
3724 Ecall := First (Statements (Handled_Statement_Sequence (Ecall)));
3726 while Nkind (Ecall) /= N_Procedure_Call_Statement
3727 and then Nkind (Ecall) /= N_Entry_Call_Statement
3733 -- If a delay was used as a trigger, it will have been expanded
3734 -- into a procedure call. Convert it to the appropriate sequence of
3735 -- statements, similar to what is done for a task entry call.
3736 -- Note that this currently supports only Duration, Real_Time.Time,
3737 -- and Calendar.Time.
3739 if Nkind (Ecall) = N_Procedure_Call_Statement then
3741 -- Add a Delay_Block object to the parameter list of the
3742 -- delay procedure to form the parameter list of the Wait
3745 Dblock_Ent := Make_Defining_Identifier (Loc, New_Internal_Name ('D'));
3747 Pdef := Entity (Name (Ecall));
3749 if Is_RTE (Pdef, RO_CA_Delay_For) then
3750 Enqueue_Call := New_Reference_To (RTE (RE_Enqueue_Duration), Loc);
3752 elsif Is_RTE (Pdef, RO_CA_Delay_Until) then
3753 Enqueue_Call := New_Reference_To (RTE (RE_Enqueue_Calendar), Loc);
3755 else pragma Assert (Is_RTE (Pdef, RO_RT_Delay_Until));
3756 Enqueue_Call := New_Reference_To (RTE (RE_Enqueue_RT), Loc);
3759 Append_To (Parameter_Associations (Ecall),
3760 Make_Attribute_Reference (Loc,
3761 Prefix => New_Reference_To (Dblock_Ent, Loc),
3762 Attribute_Name => Name_Unchecked_Access));
3764 -- Create the inner block to protect the abortable part.
3767 Make_Exception_Handler (Loc,
3768 Exception_Choices =>
3769 New_List (New_Reference_To (Stand.Abort_Signal, Loc)),
3770 Statements => New_List (
3771 Make_Procedure_Call_Statement (Loc,
3772 Name => New_Reference_To (RTE (RE_Abort_Undefer), Loc)))));
3775 Make_Procedure_Call_Statement (Loc,
3776 Name => New_Reference_To (RTE (RE_Abort_Undefer), Loc)));
3779 Make_Block_Statement (Loc,
3780 Identifier => New_Reference_To (Blkent, Loc),
3781 Handled_Statement_Sequence =>
3782 Make_Handled_Sequence_Of_Statements (Loc,
3783 Statements => Astats),
3784 Has_Created_Identifier => True,
3785 Is_Asynchronous_Call_Block => True);
3787 -- Append call to if Enqueue (When, DB'Unchecked_Access) then
3790 Make_Implicit_If_Statement (N,
3791 Condition => Make_Function_Call (Loc,
3792 Name => Enqueue_Call,
3793 Parameter_Associations => Parameter_Associations (Ecall)),
3795 New_List (Make_Block_Statement (Loc,
3796 Handled_Statement_Sequence =>
3797 Make_Handled_Sequence_Of_Statements (Loc,
3798 Statements => New_List (
3799 Make_Implicit_Label_Declaration (Loc,
3800 Defining_Identifier => Blkent,
3801 Label_Construct => Abortable_Block),
3803 Exception_Handlers => Hdle)))));
3805 Stmts := New_List (Ecall);
3807 -- Construct statement sequence for new block
3810 Make_Implicit_If_Statement (N,
3811 Condition => Make_Function_Call (Loc,
3812 Name => New_Reference_To (
3813 RTE (RE_Timed_Out), Loc),
3814 Parameter_Associations => New_List (
3815 Make_Attribute_Reference (Loc,
3816 Prefix => New_Reference_To (Dblock_Ent, Loc),
3817 Attribute_Name => Name_Unchecked_Access))),
3818 Then_Statements => Tstats));
3820 -- The result is the new block
3822 Set_Entry_Cancel_Parameter (Blkent, Dblock_Ent);
3825 Make_Block_Statement (Loc,
3826 Declarations => New_List (
3827 Make_Object_Declaration (Loc,
3828 Defining_Identifier => Dblock_Ent,
3829 Aliased_Present => True,
3830 Object_Definition => New_Reference_To (
3831 RTE (RE_Delay_Block), Loc))),
3833 Handled_Statement_Sequence =>
3834 Make_Handled_Sequence_Of_Statements (Loc, Stmts)));
3843 Extract_Entry (Ecall, Concval, Ename, Index);
3844 Build_Simple_Entry_Call (Ecall, Concval, Ename, Index);
3846 Stmts := Statements (Handled_Statement_Sequence (Ecall));
3847 Decls := Declarations (Ecall);
3849 if Is_Protected_Type (Etype (Concval)) then
3851 -- Get the declarations of the block expanded from the entry call
3853 Decl := First (Decls);
3854 while Present (Decl)
3855 and then (Nkind (Decl) /= N_Object_Declaration
3857 (Etype (Object_Definition (Decl)), RE_Communication_Block))
3862 pragma Assert (Present (Decl));
3863 Cancel_Param := Defining_Identifier (Decl);
3865 -- Change the mode of the Protected_Entry_Call call.
3866 -- Protected_Entry_Call (
3867 -- Object => po._object'Access,
3868 -- E => <entry index>;
3869 -- Uninterpreted_Data => P'Address;
3870 -- Mode => Asynchronous_Call;
3873 Stmt := First (Stmts);
3875 -- Skip assignments to temporaries created for in-out parameters.
3876 -- This makes unwarranted assumptions about the shape of the expanded
3877 -- tree for the call, and should be cleaned up ???
3879 while Nkind (Stmt) /= N_Procedure_Call_Statement loop
3885 Parm := First (Parameter_Associations (Call));
3886 while Present (Parm)
3887 and then not Is_RTE (Etype (Parm), RE_Call_Modes)
3892 pragma Assert (Present (Parm));
3893 Rewrite (Parm, New_Reference_To (RTE (RE_Asynchronous_Call), Loc));
3896 -- Append an if statement to execute the abortable part.
3897 -- if Enqueued (Bnn) then
3900 Make_Implicit_If_Statement (N,
3901 Condition => Make_Function_Call (Loc,
3902 Name => New_Reference_To (
3903 RTE (RE_Enqueued), Loc),
3904 Parameter_Associations => New_List (
3905 New_Reference_To (Cancel_Param, Loc))),
3906 Then_Statements => Astats));
3909 Make_Block_Statement (Loc,
3910 Identifier => New_Reference_To (Blkent, Loc),
3911 Handled_Statement_Sequence =>
3912 Make_Handled_Sequence_Of_Statements (Loc,
3913 Statements => Stmts),
3914 Has_Created_Identifier => True,
3915 Is_Asynchronous_Call_Block => True);
3917 -- For the JVM call Update_Exception instead of Abort_Undefer.
3918 -- See 4jexcept.ads for an explanation.
3920 if Hostparm.Java_VM then
3921 Target_Undefer := RE_Update_Exception;
3923 New_List (Make_Function_Call (Loc,
3924 Name => New_Occurrence_Of
3925 (RTE (RE_Current_Target_Exception), Loc)));
3927 Target_Undefer := RE_Abort_Undefer;
3931 Make_Block_Statement (Loc,
3932 Handled_Statement_Sequence =>
3933 Make_Handled_Sequence_Of_Statements (Loc,
3934 Statements => New_List (
3935 Make_Implicit_Label_Declaration (Loc,
3936 Defining_Identifier => Blkent,
3937 Label_Construct => Abortable_Block),
3942 Exception_Handlers => New_List (
3943 Make_Exception_Handler (Loc,
3945 -- when Abort_Signal =>
3946 -- Abort_Undefer.all;
3948 Exception_Choices =>
3949 New_List (New_Reference_To (Stand.Abort_Signal, Loc)),
3950 Statements => New_List (
3951 Make_Procedure_Call_Statement (Loc,
3952 Name => New_Reference_To (
3953 RTE (Target_Undefer), Loc),
3954 Parameter_Associations => Undefer_Args)))))),
3956 -- if not Cancelled (Bnn) then
3957 -- triggered statements
3960 Make_Implicit_If_Statement (N,
3961 Condition => Make_Op_Not (Loc,
3963 Make_Function_Call (Loc,
3964 Name => New_Occurrence_Of (RTE (RE_Cancelled), Loc),
3965 Parameter_Associations => New_List (
3966 New_Occurrence_Of (Cancel_Param, Loc)))),
3967 Then_Statements => Tstats));
3969 -- Asynchronous task entry call
3976 B := Make_Defining_Identifier (Loc, Name_uB);
3978 -- Insert declaration of B in declarations of existing block
3981 Make_Object_Declaration (Loc,
3982 Defining_Identifier => B,
3983 Object_Definition => New_Reference_To (Standard_Boolean, Loc)));
3985 Cancel_Param := Make_Defining_Identifier (Loc, Name_uC);
3987 -- Insert declaration of C in declarations of existing block
3990 Make_Object_Declaration (Loc,
3991 Defining_Identifier => Cancel_Param,
3992 Object_Definition => New_Reference_To (Standard_Boolean, Loc)));
3994 -- Remove and save the call to Call_Simple.
3996 Stmt := First (Stmts);
3998 -- Skip assignments to temporaries created for in-out parameters.
3999 -- This makes unwarranted assumptions about the shape of the expanded
4000 -- tree for the call, and should be cleaned up ???
4002 while Nkind (Stmt) /= N_Procedure_Call_Statement loop
4008 -- Create the inner block to protect the abortable part.
4011 Make_Exception_Handler (Loc,
4012 Exception_Choices =>
4013 New_List (New_Reference_To (Stand.Abort_Signal, Loc)),
4014 Statements => New_List (
4015 Make_Procedure_Call_Statement (Loc,
4016 Name => New_Reference_To (RTE (RE_Abort_Undefer), Loc)))));
4019 Make_Procedure_Call_Statement (Loc,
4020 Name => New_Reference_To (RTE (RE_Abort_Undefer), Loc)));
4023 Make_Block_Statement (Loc,
4024 Identifier => New_Reference_To (Blkent, Loc),
4025 Handled_Statement_Sequence =>
4026 Make_Handled_Sequence_Of_Statements (Loc,
4027 Statements => Astats),
4028 Has_Created_Identifier => True,
4029 Is_Asynchronous_Call_Block => True);
4032 Make_Block_Statement (Loc,
4033 Handled_Statement_Sequence =>
4034 Make_Handled_Sequence_Of_Statements (Loc,
4035 Statements => New_List (
4036 Make_Implicit_Label_Declaration (Loc,
4037 Defining_Identifier => Blkent,
4038 Label_Construct => Abortable_Block),
4040 Exception_Handlers => Hdle)));
4042 -- Create new call statement
4044 Parms := Parameter_Associations (Call);
4045 Append_To (Parms, New_Reference_To (RTE (RE_Asynchronous_Call), Loc));
4046 Append_To (Parms, New_Reference_To (B, Loc));
4048 Make_Procedure_Call_Statement (Loc,
4049 Name => New_Reference_To (RTE (RE_Task_Entry_Call), Loc),
4050 Parameter_Associations => Parms));
4052 -- Construct statement sequence for new block
4055 Make_Implicit_If_Statement (N,
4056 Condition => Make_Op_Not (Loc,
4057 New_Reference_To (Cancel_Param, Loc)),
4058 Then_Statements => Tstats));
4060 -- Protected the call against abortion
4063 Make_Procedure_Call_Statement (Loc,
4064 Name => New_Reference_To (RTE (RE_Abort_Defer), Loc),
4065 Parameter_Associations => Empty_List));
4068 Set_Entry_Cancel_Parameter (Blkent, Cancel_Param);
4070 -- The result is the new block
4073 Make_Block_Statement (Loc,
4074 Declarations => Decls,
4075 Handled_Statement_Sequence =>
4076 Make_Handled_Sequence_Of_Statements (Loc, Stmts)));
4080 end Expand_N_Asynchronous_Select;
4082 -------------------------------------
4083 -- Expand_N_Conditional_Entry_Call --
4084 -------------------------------------
4086 -- The conditional task entry call is converted to a call to
4091 -- P : parms := (parm, parm, parm);
4098 -- Conditional_Call,
4104 -- normal-statements
4110 -- For a description of the use of P and the assignments after the
4111 -- call, see Expand_N_Entry_Call_Statement. Note that the entry call
4112 -- of the conditional entry call has already been expanded (by the
4113 -- Expand_N_Entry_Call_Statement procedure) as follows:
4116 -- P : parms := (parm, parm, parm);
4118 -- ... info for in-out parameters
4119 -- Call_Simple (acceptor-task, entry-index, P'Address);
4125 -- so the task at hand is to convert the latter expansion into the former
4127 -- The conditional protected entry call is converted to a call to
4128 -- Protected_Entry_Call:
4131 -- P : parms := (parm, parm, parm);
4132 -- Bnn : Communications_Block;
4135 -- Protected_Entry_Call (
4136 -- Object => po._object'Access,
4137 -- E => <entry index>;
4138 -- Uninterpreted_Data => P'Address;
4139 -- Mode => Conditional_Call;
4144 -- if Cancelled (Bnn) then
4147 -- normal-statements
4151 -- As for tasks, the entry call of the conditional entry call has
4152 -- already been expanded (by the Expand_N_Entry_Call_Statement procedure)
4156 -- P : E1_Params := (param, param, param);
4157 -- Bnn : Communications_Block;
4160 -- Protected_Entry_Call (
4161 -- Object => po._object'Access,
4162 -- E => <entry index>;
4163 -- Uninterpreted_Data => P'Address;
4164 -- Mode => Simple_Call;
4171 procedure Expand_N_Conditional_Entry_Call (N : Node_Id) is
4172 Loc : constant Source_Ptr := Sloc (N);
4173 Alt : constant Node_Id := Entry_Call_Alternative (N);
4174 Blk : Node_Id := Entry_Call_Statement (Alt);
4175 Transient_Blk : Node_Id;
4186 -- As described above, The entry alternative is transformed into a
4187 -- block that contains the gnulli call, and possibly assignment
4188 -- statements for in-out parameters. The gnulli call may itself be
4189 -- rewritten into a transient block if some unconstrained parameters
4190 -- require it. We need to retrieve the call to complete its parameter
4194 First_Real_Statement (Handled_Statement_Sequence (Blk));
4196 if Present (Transient_Blk)
4198 Nkind (Transient_Blk) = N_Block_Statement
4200 Blk := Transient_Blk;
4203 Stmts := Statements (Handled_Statement_Sequence (Blk));
4205 Stmt := First (Stmts);
4207 while Nkind (Stmt) /= N_Procedure_Call_Statement loop
4213 Parms := Parameter_Associations (Call);
4215 if Is_RTE (Entity (Name (Call)), RE_Protected_Entry_Call) then
4217 -- Substitute Conditional_Entry_Call for Simple_Call
4220 Parm := First (Parms);
4221 while Present (Parm)
4222 and then not Is_RTE (Etype (Parm), RE_Call_Modes)
4227 pragma Assert (Present (Parm));
4228 Rewrite (Parm, New_Reference_To (RTE (RE_Conditional_Call), Loc));
4232 -- Find the Communication_Block parameter for the call
4233 -- to the Cancelled function.
4235 Decl := First (Declarations (Blk));
4236 while Present (Decl)
4238 Is_RTE (Etype (Object_Definition (Decl)), RE_Communication_Block)
4243 -- Add an if statement to execute the else part if the call
4244 -- does not succeed (as indicated by the Cancelled predicate).
4247 Make_Implicit_If_Statement (N,
4248 Condition => Make_Function_Call (Loc,
4249 Name => New_Reference_To (RTE (RE_Cancelled), Loc),
4250 Parameter_Associations => New_List (
4251 New_Reference_To (Defining_Identifier (Decl), Loc))),
4252 Then_Statements => Else_Statements (N),
4253 Else_Statements => Statements (Alt)));
4256 B := Make_Defining_Identifier (Loc, Name_uB);
4258 -- Insert declaration of B in declarations of existing block
4260 if No (Declarations (Blk)) then
4261 Set_Declarations (Blk, New_List);
4264 Prepend_To (Declarations (Blk),
4265 Make_Object_Declaration (Loc,
4266 Defining_Identifier => B,
4267 Object_Definition => New_Reference_To (Standard_Boolean, Loc)));
4269 -- Create new call statement
4271 Append_To (Parms, New_Reference_To (RTE (RE_Conditional_Call), Loc));
4272 Append_To (Parms, New_Reference_To (B, Loc));
4275 Make_Procedure_Call_Statement (Loc,
4276 Name => New_Reference_To (RTE (RE_Task_Entry_Call), Loc),
4277 Parameter_Associations => Parms));
4279 -- Construct statement sequence for new block
4282 Make_Implicit_If_Statement (N,
4283 Condition => New_Reference_To (B, Loc),
4284 Then_Statements => Statements (Alt),
4285 Else_Statements => Else_Statements (N)));
4289 -- The result is the new block
4292 Make_Block_Statement (Loc,
4293 Declarations => Declarations (Blk),
4294 Handled_Statement_Sequence =>
4295 Make_Handled_Sequence_Of_Statements (Loc, Stmts)));
4299 end Expand_N_Conditional_Entry_Call;
4301 ---------------------------------------
4302 -- Expand_N_Delay_Relative_Statement --
4303 ---------------------------------------
4305 -- Delay statement is implemented as a procedure call to Delay_For
4306 -- defined in Ada.Calendar.Delays in order to reduce the overhead of
4307 -- simple delays imposed by the use of Protected Objects.
4309 procedure Expand_N_Delay_Relative_Statement (N : Node_Id) is
4310 Loc : constant Source_Ptr := Sloc (N);
4314 Make_Procedure_Call_Statement (Loc,
4315 Name => New_Reference_To (RTE (RO_CA_Delay_For), Loc),
4316 Parameter_Associations => New_List (Expression (N))));
4318 end Expand_N_Delay_Relative_Statement;
4320 ------------------------------------
4321 -- Expand_N_Delay_Until_Statement --
4322 ------------------------------------
4324 -- Delay Until statement is implemented as a procedure call to
4325 -- Delay_Until defined in Ada.Calendar.Delays and Ada.Real_Time.Delays.
4327 procedure Expand_N_Delay_Until_Statement (N : Node_Id) is
4328 Loc : constant Source_Ptr := Sloc (N);
4332 if Is_RTE (Base_Type (Etype (Expression (N))), RO_CA_Time) then
4333 Typ := RTE (RO_CA_Delay_Until);
4335 Typ := RTE (RO_RT_Delay_Until);
4339 Make_Procedure_Call_Statement (Loc,
4340 Name => New_Reference_To (Typ, Loc),
4341 Parameter_Associations => New_List (Expression (N))));
4344 end Expand_N_Delay_Until_Statement;
4346 -------------------------
4347 -- Expand_N_Entry_Body --
4348 -------------------------
4350 procedure Expand_N_Entry_Body (N : Node_Id) is
4351 Loc : constant Source_Ptr := Sloc (N);
4353 Dec : Node_Id := Parent (Current_Scope);
4354 Ent_Formals : Node_Id := Entry_Body_Formal_Part (N);
4355 Index_Spec : Node_Id := Entry_Index_Specification (Ent_Formals);
4358 -- Add the renamings for private declarations and discriminants.
4360 Add_Discriminal_Declarations
4361 (Declarations (N), Defining_Identifier (Dec), Name_uObject, Loc);
4362 Add_Private_Declarations
4363 (Declarations (N), Defining_Identifier (Dec), Name_uObject, Loc);
4365 if Present (Index_Spec) then
4366 Append_List_To (Declarations (N),
4367 Index_Constant_Declaration
4368 (N, Defining_Identifier (Index_Spec), Defining_Identifier (Dec)));
4371 -- Associate privals and discriminals with the next protected
4372 -- operation body to be expanded. These are used to expand
4373 -- references to private data objects and discriminants,
4376 Next_Op := Next_Protected_Operation (N);
4378 if Present (Next_Op) then
4379 Set_Privals (Dec, Next_Op, Loc);
4380 Set_Discriminals (Dec);
4383 end Expand_N_Entry_Body;
4385 -----------------------------------
4386 -- Expand_N_Entry_Call_Statement --
4387 -----------------------------------
4389 -- An entry call is expanded into GNARLI calls to implement
4390 -- a simple entry call (see Build_Simple_Entry_Call).
4392 procedure Expand_N_Entry_Call_Statement (N : Node_Id) is
4398 -- If this entry call is part of an asynchronous select, don't
4399 -- expand it here; it will be expanded with the select statement.
4400 -- Don't expand timed entry calls either, as they are translated
4401 -- into asynchronous entry calls.
4403 -- ??? This whole approach is questionable; it may be better
4404 -- to go back to allowing the expansion to take place and then
4405 -- attempting to fix it up in Expand_N_Asynchronous_Select.
4406 -- The tricky part is figuring out whether the expanded
4407 -- call is on a task or protected entry.
4409 if (Nkind (Parent (N)) /= N_Triggering_Alternative
4410 or else N /= Triggering_Statement (Parent (N)))
4411 and then (Nkind (Parent (N)) /= N_Entry_Call_Alternative
4412 or else N /= Entry_Call_Statement (Parent (N))
4413 or else Nkind (Parent (Parent (N))) /= N_Timed_Entry_Call)
4415 Extract_Entry (N, Concval, Ename, Index);
4416 Build_Simple_Entry_Call (N, Concval, Ename, Index);
4419 end Expand_N_Entry_Call_Statement;
4421 --------------------------------
4422 -- Expand_N_Entry_Declaration --
4423 --------------------------------
4425 -- If there are parameters, then first, each of the formals is marked
4426 -- by setting Is_Entry_Formal. Next a record type is built which is
4427 -- used to hold the parameter values. The name of this record type is
4428 -- entryP where entry is the name of the entry, with an additional
4429 -- corresponding access type called entryPA. The record type has matching
4430 -- components for each formal (the component names are the same as the
4431 -- formal names). For elementary types, the component type matches the
4432 -- formal type. For composite types, an access type is declared (with
4433 -- the name formalA) which designates the formal type, and the type of
4434 -- the component is this access type. Finally the Entry_Component of
4435 -- each formal is set to reference the corresponding record component.
4437 procedure Expand_N_Entry_Declaration (N : Node_Id) is
4438 Loc : constant Source_Ptr := Sloc (N);
4439 Entry_Ent : constant Entity_Id := Defining_Identifier (N);
4440 Components : List_Id;
4443 Last_Decl : Node_Id;
4444 Component : Entity_Id;
4447 Rec_Ent : Entity_Id;
4448 Acc_Ent : Entity_Id;
4451 Formal := First_Formal (Entry_Ent);
4454 -- Most processing is done only if parameters are present
4456 if Present (Formal) then
4457 Components := New_List;
4459 -- Loop through formals
4461 while Present (Formal) loop
4462 Set_Is_Entry_Formal (Formal);
4464 Make_Defining_Identifier (Sloc (Formal), Chars (Formal));
4465 Set_Entry_Component (Formal, Component);
4466 Set_Entry_Formal (Component, Formal);
4467 Ftype := Etype (Formal);
4469 -- Declare new access type and then append
4472 Make_Defining_Identifier (Loc, New_Internal_Name ('A'));
4475 Make_Full_Type_Declaration (Loc,
4476 Defining_Identifier => Ctype,
4478 Make_Access_To_Object_Definition (Loc,
4479 All_Present => True,
4480 Constant_Present => Ekind (Formal) = E_In_Parameter,
4481 Subtype_Indication => New_Reference_To (Ftype, Loc)));
4483 Insert_After (Last_Decl, Decl);
4486 Append_To (Components,
4487 Make_Component_Declaration (Loc,
4488 Defining_Identifier => Component,
4489 Subtype_Indication => New_Reference_To (Ctype, Loc)));
4491 Next_Formal_With_Extras (Formal);
4494 -- Create the Entry_Parameter_Record declaration
4497 Make_Defining_Identifier (Loc, New_Internal_Name ('P'));
4500 Make_Full_Type_Declaration (Loc,
4501 Defining_Identifier => Rec_Ent,
4503 Make_Record_Definition (Loc,
4505 Make_Component_List (Loc,
4506 Component_Items => Components)));
4508 Insert_After (Last_Decl, Decl);
4511 -- Construct and link in the corresponding access type
4514 Make_Defining_Identifier (Loc, New_Internal_Name ('A'));
4516 Set_Entry_Parameters_Type (Entry_Ent, Acc_Ent);
4519 Make_Full_Type_Declaration (Loc,
4520 Defining_Identifier => Acc_Ent,
4522 Make_Access_To_Object_Definition (Loc,
4523 All_Present => True,
4524 Subtype_Indication => New_Reference_To (Rec_Ent, Loc)));
4526 Insert_After (Last_Decl, Decl);
4531 end Expand_N_Entry_Declaration;
4533 -----------------------------
4534 -- Expand_N_Protected_Body --
4535 -----------------------------
4537 -- Protected bodies are expanded to the completion of the subprograms
4538 -- created for the corresponding protected type. These are a protected
4539 -- and unprotected version of each protected subprogram in the object,
4540 -- a function to calculate each entry barrier, and a procedure to
4541 -- execute the sequence of statements of each protected entry body.
4542 -- For example, for protected type ptype:
4545 -- (O : System.Address;
4546 -- E : Protected_Entry_Index)
4549 -- <discriminant renamings>
4550 -- <private object renamings>
4552 -- return <barrier expression>;
4555 -- procedure pprocN (_object : in out poV;...) is
4556 -- <discriminant renamings>
4557 -- <private object renamings>
4559 -- <sequence of statements>
4562 -- procedure pproc (_object : in out poV;...) is
4563 -- procedure _clean is
4566 -- ptypeS (_object, Pn);
4567 -- Unlock (_object._object'Access);
4568 -- Abort_Undefer.all;
4572 -- Lock (_object._object'Access);
4573 -- pprocN (_object;...);
4578 -- function pfuncN (_object : poV;...) return Return_Type is
4579 -- <discriminant renamings>
4580 -- <private object renamings>
4582 -- <sequence of statements>
4585 -- function pfunc (_object : poV) return Return_Type is
4586 -- procedure _clean is
4588 -- Unlock (_object._object'Access);
4589 -- Abort_Undefer.all;
4593 -- Lock (_object._object'Access);
4594 -- return pfuncN (_object);
4600 -- (O : System.Address;
4601 -- P : System.Address;
4602 -- E : Protected_Entry_Index)
4604 -- <discriminant renamings>
4605 -- <private object renamings>
4606 -- type poVP is access poV;
4607 -- _Object : ptVP := ptVP!(O);
4610 -- <statement sequence>
4611 -- Complete_Entry_Body (_Object._Object);
4613 -- when all others =>
4614 -- Exceptional_Complete_Entry_Body (
4615 -- _Object._Object, Get_GNAT_Exception);
4619 -- The type poV is the record created for the protected type to hold
4620 -- the state of the protected object.
4622 procedure Expand_N_Protected_Body (N : Node_Id) is
4623 Pid : constant Entity_Id := Corresponding_Spec (N);
4624 Has_Entries : Boolean := False;
4628 New_Op_Body : Node_Id;
4629 Current_Node : Node_Id;
4630 Num_Entries : Natural := 0;
4633 if Nkind (Parent (N)) = N_Subunit then
4635 -- This is the proper body corresponding to a stub. The declarations
4636 -- must be inserted at the point of the stub, which is in the decla-
4637 -- rative part of the parent unit.
4639 Current_Node := Corresponding_Stub (Parent (N));
4645 Op_Body := First (Declarations (N));
4647 -- The protected body is replaced with the bodies of its
4648 -- protected operations, and the declarations for internal objects
4649 -- that may have been created for entry family bounds.
4651 Rewrite (N, Make_Null_Statement (Sloc (N)));
4654 while Present (Op_Body) loop
4656 case Nkind (Op_Body) is
4657 when N_Subprogram_Declaration =>
4660 when N_Subprogram_Body =>
4662 -- Exclude functions created to analyze defaults.
4664 if not Is_Eliminated (Defining_Entity (Op_Body)) then
4666 Build_Unprotected_Subprogram_Body (Op_Body, Pid);
4668 Insert_After (Current_Node, New_Op_Body);
4669 Current_Node := New_Op_Body;
4670 Analyze (New_Op_Body);
4672 Update_Prival_Subtypes (New_Op_Body);
4674 -- Build the corresponding protected operation only if
4675 -- this is a visible operation of the type, or if it is
4676 -- an interrupt handler. Otherwise it is only callable
4677 -- from within the object, and the unprotected version
4680 if Present (Corresponding_Spec (Op_Body)) then
4682 Unit_Declaration_Node (Corresponding_Spec (Op_Body));
4684 if Nkind (Parent (Op_Decl)) = N_Protected_Definition
4686 (List_Containing (Op_Decl) =
4687 Visible_Declarations (Parent (Op_Decl))
4689 Is_Interrupt_Handler
4690 (Corresponding_Spec (Op_Body)))
4693 Build_Protected_Subprogram_Body (
4694 Op_Body, Pid, Specification (New_Op_Body));
4696 Insert_After (Current_Node, New_Op_Body);
4697 Analyze (New_Op_Body);
4702 when N_Entry_Body =>
4703 Op_Id := Defining_Identifier (Op_Body);
4704 Has_Entries := True;
4705 Num_Entries := Num_Entries + 1;
4707 New_Op_Body := Build_Protected_Entry (Op_Body, Op_Id, Pid);
4709 Insert_After (Current_Node, New_Op_Body);
4710 Current_Node := New_Op_Body;
4711 Analyze (New_Op_Body);
4713 Update_Prival_Subtypes (New_Op_Body);
4715 when N_Implicit_Label_Declaration =>
4718 when N_Itype_Reference =>
4719 Insert_After (Current_Node, New_Copy (Op_Body));
4721 when N_Freeze_Entity =>
4722 New_Op_Body := New_Copy (Op_Body);
4724 if Present (Entity (Op_Body))
4725 and then Freeze_Node (Entity (Op_Body)) = Op_Body
4727 Set_Freeze_Node (Entity (Op_Body), New_Op_Body);
4730 Insert_After (Current_Node, New_Op_Body);
4731 Current_Node := New_Op_Body;
4732 Analyze (New_Op_Body);
4735 New_Op_Body := New_Copy (Op_Body);
4736 Insert_After (Current_Node, New_Op_Body);
4737 Current_Node := New_Op_Body;
4738 Analyze (New_Op_Body);
4740 when N_Object_Declaration =>
4741 pragma Assert (not Comes_From_Source (Op_Body));
4742 New_Op_Body := New_Copy (Op_Body);
4743 Insert_After (Current_Node, New_Op_Body);
4744 Current_Node := New_Op_Body;
4745 Analyze (New_Op_Body);
4748 raise Program_Error;
4755 -- Finally, create the body of the function that maps an entry index
4756 -- into the corresponding body index, except when there is no entry,
4757 -- or in a ravenscar-like profile (no abort, no entry queue, 1 entry)
4760 and then (Abort_Allowed
4761 or else Restrictions (No_Entry_Queue) = False
4762 or else Num_Entries > 1)
4764 New_Op_Body := Build_Find_Body_Index (Pid);
4765 Insert_After (Current_Node, New_Op_Body);
4766 Analyze (New_Op_Body);
4768 end Expand_N_Protected_Body;
4770 -----------------------------------------
4771 -- Expand_N_Protected_Type_Declaration --
4772 -----------------------------------------
4774 -- First we create a corresponding record type declaration used to
4775 -- represent values of this protected type.
4776 -- The general form of this type declaration is
4778 -- type poV (discriminants) is record
4779 -- _Object : aliased <kind>Protection
4780 -- [(<entry count> [, <handler count>])];
4781 -- [entry_family : array (bounds) of Void;]
4782 -- <private data fields>
4785 -- The discriminants are present only if the corresponding protected
4786 -- type has discriminants, and they exactly mirror the protected type
4787 -- discriminants. The private data fields similarly mirror the
4788 -- private declarations of the protected type.
4790 -- The Object field is always present. It contains RTS specific data
4791 -- used to control the protected object. It is declared as Aliased
4792 -- so that it can be passed as a pointer to the RTS. This allows the
4793 -- protected record to be referenced within RTS data structures.
4794 -- An appropriate Protection type and discriminant are generated.
4796 -- The Service field is present for protected objects with entries. It
4797 -- contains sufficient information to allow the entry service procedure
4798 -- for this object to be called when the object is not known till runtime.
4800 -- One entry_family component is present for each entry family in the
4801 -- task definition (see Expand_N_Task_Type_Declaration).
4803 -- When a protected object is declared, an instance of the protected type
4804 -- value record is created. The elaboration of this declaration creates
4805 -- the correct bounds for the entry families, and also evaluates the
4806 -- priority expression if needed. The initialization routine for
4807 -- the protected type itself then calls Initialize_Protection with
4808 -- appropriate parameters to initialize the value of the Task_Id field.
4809 -- Install_Handlers may be also called if a pragma Attach_Handler applies.
4811 -- Note: this record is passed to the subprograms created by the
4812 -- expansion of protected subprograms and entries. It is an in parameter
4813 -- to protected functions and an in out parameter to procedures and
4814 -- entry bodies. The Entity_Id for this created record type is placed
4815 -- in the Corresponding_Record_Type field of the associated protected
4818 -- Next we create a procedure specifications for protected subprograms
4819 -- and entry bodies. For each protected subprograms two subprograms are
4820 -- created, an unprotected and a protected version. The unprotected
4821 -- version is called from within other operations of the same protected
4824 -- We also build the call to register the procedure if a pragma
4825 -- Interrupt_Handler applies.
4827 -- A single subprogram is created to service all entry bodies; it has an
4828 -- additional boolean out parameter indicating that the previous entry
4829 -- call made by the current task was serviced immediately, i.e. not by
4830 -- proxy. The O parameter contains a pointer to a record object of the
4831 -- type described above. An untyped interface is used here to allow this
4832 -- procedure to be called in places where the type of the object to be
4833 -- serviced is not known. This must be done, for example, when a call
4834 -- that may have been requeued is cancelled; the corresponding object
4835 -- must be serviced, but which object that is not known till runtime.
4838 -- (O : System.Address; P : out Boolean);
4839 -- procedure pprocN (_object : in out poV);
4840 -- procedure pproc (_object : in out poV);
4841 -- function pfuncN (_object : poV);
4842 -- function pfunc (_object : poV);
4845 -- Note that this must come after the record type declaration, since
4846 -- the specs refer to this type.
4848 procedure Expand_N_Protected_Type_Declaration (N : Node_Id) is
4849 Loc : constant Source_Ptr := Sloc (N);
4850 Prottyp : constant Entity_Id := Defining_Identifier (N);
4851 Protnm : constant Name_Id := Chars (Prottyp);
4853 Pdef : constant Node_Id := Protected_Definition (N);
4854 -- This contains two lists; one for visible and one for private decls
4858 Discr_Map : Elist_Id := New_Elmt_List;
4863 Comp_Id : Entity_Id;
4865 Current_Node : Node_Id := N;
4867 Bdef : Entity_Id := Empty; -- avoid uninit warning
4868 Edef : Entity_Id := Empty; -- avoid uninit warning
4869 Entries_Aggr : Node_Id;
4870 Body_Id : Entity_Id;
4873 Object_Comp : Node_Id;
4875 procedure Register_Handler;
4876 -- for a protected operation that is an interrupt handler, add the
4877 -- freeze action that will register it as such.
4879 ----------------------
4880 -- Register_Handler --
4881 ----------------------
4883 procedure Register_Handler is
4885 -- All semantic checks already done in Sem_Prag
4887 Prot_Proc : constant Entity_Id :=
4889 (Specification (Current_Node));
4891 Proc_Address : constant Node_Id :=
4892 Make_Attribute_Reference (Loc,
4893 Prefix => New_Reference_To (Prot_Proc, Loc),
4894 Attribute_Name => Name_Address);
4896 RTS_Call : constant Entity_Id :=
4897 Make_Procedure_Call_Statement (Loc,
4900 RTE (RE_Register_Interrupt_Handler), Loc),
4901 Parameter_Associations =>
4902 New_List (Proc_Address));
4904 Append_Freeze_Action (Prot_Proc, RTS_Call);
4905 end Register_Handler;
4907 -- Start of processing for Expand_N_Protected_Type_Declaration
4910 if Present (Corresponding_Record_Type (Prottyp)) then
4913 Rec_Decl := Build_Corresponding_Record (N, Prottyp, Loc);
4914 Cdecls := Component_Items
4915 (Component_List (Type_Definition (Rec_Decl)));
4918 Qualify_Entity_Names (N);
4920 -- If the type has discriminants, their occurrences in the declaration
4921 -- have been replaced by the corresponding discriminals. For components
4922 -- that are constrained by discriminants, their homologues in the
4923 -- corresponding record type must refer to the discriminants of that
4924 -- record, so we must apply a new renaming to subtypes_indications:
4926 -- protected discriminant => discriminal => record discriminant.
4927 -- This replacement is not applied to default expressions, for which
4928 -- the discriminal is correct.
4930 if Has_Discriminants (Prottyp) then
4936 Disc := First_Discriminant (Prottyp);
4937 Decl := First (Discriminant_Specifications (Rec_Decl));
4939 while Present (Disc) loop
4940 Append_Elmt (Discriminal (Disc), Discr_Map);
4941 Append_Elmt (Defining_Identifier (Decl), Discr_Map);
4942 Next_Discriminant (Disc);
4948 -- Fill in the component declarations.
4950 -- Add components for entry families. For each entry family,
4951 -- create an anonymous type declaration with the same size, and
4952 -- analyze the type.
4954 Collect_Entry_Families (Loc, Cdecls, Current_Node, Prottyp);
4956 -- Prepend the _Object field with the right type to the component
4957 -- list. We need to compute the number of entries, and in some cases
4958 -- the number of Attach_Handler pragmas.
4962 Num_Attach_Handler : Int := 0;
4963 Protection_Subtype : Node_Id;
4964 Entry_Count_Expr : constant Node_Id :=
4965 Build_Entry_Count_Expression
4966 (Prottyp, Cdecls, Loc);
4969 if Has_Attach_Handler (Prottyp) then
4970 Ritem := First_Rep_Item (Prottyp);
4971 while Present (Ritem) loop
4972 if Nkind (Ritem) = N_Pragma
4973 and then Chars (Ritem) = Name_Attach_Handler
4975 Num_Attach_Handler := Num_Attach_Handler + 1;
4978 Next_Rep_Item (Ritem);
4981 if Restricted_Profile then
4982 Protection_Subtype :=
4983 New_Reference_To (RTE (RE_Protection_Entry), Loc);
4986 Protection_Subtype :=
4987 Make_Subtype_Indication
4991 (RTE (RE_Static_Interrupt_Protection), Loc),
4993 Make_Index_Or_Discriminant_Constraint (
4995 Constraints => New_List (
4997 Make_Integer_Literal (Loc, Num_Attach_Handler))));
5000 elsif Has_Interrupt_Handler (Prottyp) then
5001 Protection_Subtype :=
5002 Make_Subtype_Indication (
5004 Subtype_Mark => New_Reference_To
5005 (RTE (RE_Dynamic_Interrupt_Protection), Loc),
5007 Make_Index_Or_Discriminant_Constraint (
5009 Constraints => New_List (Entry_Count_Expr)));
5011 elsif Has_Entries (Prottyp) then
5013 or else Restrictions (No_Entry_Queue) = False
5014 or else Number_Entries (Prottyp) > 1
5016 Protection_Subtype :=
5017 Make_Subtype_Indication (
5020 New_Reference_To (RTE (RE_Protection_Entries), Loc),
5022 Make_Index_Or_Discriminant_Constraint (
5024 Constraints => New_List (Entry_Count_Expr)));
5027 Protection_Subtype :=
5028 New_Reference_To (RTE (RE_Protection_Entry), Loc);
5032 Protection_Subtype := New_Reference_To (RTE (RE_Protection), Loc);
5036 Make_Component_Declaration (Loc,
5037 Defining_Identifier =>
5038 Make_Defining_Identifier (Loc, Name_uObject),
5039 Aliased_Present => True,
5040 Subtype_Indication => Protection_Subtype);
5043 pragma Assert (Present (Pdef));
5045 -- Add private field components.
5047 if Present (Private_Declarations (Pdef)) then
5048 Priv := First (Private_Declarations (Pdef));
5050 while Present (Priv) loop
5052 if Nkind (Priv) = N_Component_Declaration then
5053 Pent := Defining_Identifier (Priv);
5055 Make_Component_Declaration (Loc,
5056 Defining_Identifier =>
5057 Make_Defining_Identifier (Sloc (Pent), Chars (Pent)),
5058 Subtype_Indication =>
5059 New_Copy_Tree (Subtype_Indication (Priv), Discr_Map),
5060 Expression => Expression (Priv));
5062 Append_To (Cdecls, New_Priv);
5064 elsif Nkind (Priv) = N_Subprogram_Declaration then
5066 -- Make the unprotected version of the subprogram available
5067 -- for expansion of intra object calls. There is need for
5068 -- a protected version only if the subprogram is an interrupt
5069 -- handler, otherwise this operation can only be called from
5073 Make_Subprogram_Declaration (Loc,
5075 Build_Protected_Sub_Specification
5076 (Priv, Prottyp, Unprotected => True));
5078 Insert_After (Current_Node, Sub);
5081 Set_Protected_Body_Subprogram
5082 (Defining_Unit_Name (Specification (Priv)),
5083 Defining_Unit_Name (Specification (Sub)));
5085 Current_Node := Sub;
5086 if Is_Interrupt_Handler
5087 (Defining_Unit_Name (Specification (Priv)))
5090 Make_Subprogram_Declaration (Loc,
5092 Build_Protected_Sub_Specification
5093 (Priv, Prottyp, Unprotected => False));
5095 Insert_After (Current_Node, Sub);
5097 Current_Node := Sub;
5099 if not Restricted_Profile then
5109 -- Put the _Object component after the private component so that it
5110 -- be finalized early as required by 9.4 (20)
5112 Append_To (Cdecls, Object_Comp);
5114 Insert_After (Current_Node, Rec_Decl);
5115 Current_Node := Rec_Decl;
5117 -- Analyze the record declaration immediately after construction,
5118 -- because the initialization procedure is needed for single object
5119 -- declarations before the next entity is analyzed (the freeze call
5120 -- that generates this initialization procedure is found below).
5122 Analyze (Rec_Decl, Suppress => All_Checks);
5124 -- Collect pointers to entry bodies and their barriers, to be placed
5125 -- in the Entry_Bodies_Array for the type. For each entry/family we
5126 -- add an expression to the aggregate which is the initial value of
5127 -- this array. The array is declared after all protected subprograms.
5129 if Has_Entries (Prottyp) then
5131 Make_Aggregate (Loc, Expressions => New_List);
5134 Entries_Aggr := Empty;
5137 -- Build two new procedure specifications for each protected
5138 -- subprogram; one to call from outside the object and one to
5139 -- call from inside. Build a barrier function and an entry
5140 -- body action procedure specification for each protected entry.
5141 -- Initialize the entry body array.
5145 Comp := First (Visible_Declarations (Pdef));
5147 while Present (Comp) loop
5148 if Nkind (Comp) = N_Subprogram_Declaration then
5150 Make_Subprogram_Declaration (Loc,
5152 Build_Protected_Sub_Specification
5153 (Comp, Prottyp, Unprotected => True));
5155 Insert_After (Current_Node, Sub);
5158 Set_Protected_Body_Subprogram
5159 (Defining_Unit_Name (Specification (Comp)),
5160 Defining_Unit_Name (Specification (Sub)));
5162 -- Make the protected version of the subprogram available
5163 -- for expansion of external calls.
5165 Current_Node := Sub;
5168 Make_Subprogram_Declaration (Loc,
5170 Build_Protected_Sub_Specification
5171 (Comp, Prottyp, Unprotected => False));
5173 Insert_After (Current_Node, Sub);
5175 Current_Node := Sub;
5177 -- If a pragma Interrupt_Handler applies, build and add
5178 -- a call to Register_Interrupt_Handler to the freezing actions
5179 -- of the protected version (Current_Node) of the subprogram:
5180 -- system.interrupts.register_interrupt_handler
5181 -- (prot_procP'address);
5183 if not Restricted_Profile
5184 and then Is_Interrupt_Handler
5185 (Defining_Unit_Name (Specification (Comp)))
5190 elsif Nkind (Comp) = N_Entry_Declaration then
5191 E_Count := E_Count + 1;
5192 Comp_Id := Defining_Identifier (Comp);
5193 Set_Privals_Chain (Comp_Id, New_Elmt_List);
5194 Nam := Chars (Comp_Id);
5196 Make_Defining_Identifier (Loc,
5197 Build_Selected_Name (Protnm, New_Internal_Name ('E')));
5199 Make_Subprogram_Declaration (Loc,
5201 Build_Protected_Entry_Specification (Edef, Comp_Id, Loc));
5203 Insert_After (Current_Node, Sub);
5206 Set_Protected_Body_Subprogram (
5207 Defining_Identifier (Comp),
5208 Defining_Unit_Name (Specification (Sub)));
5210 Current_Node := Sub;
5213 Make_Defining_Identifier (Loc,
5214 Build_Selected_Name (Protnm, New_Internal_Name ('B')));
5216 Make_Subprogram_Declaration (Loc,
5218 Build_Barrier_Function_Specification (Bdef, Loc));
5220 Insert_After (Current_Node, Sub);
5222 Set_Protected_Body_Subprogram (Bdef, Bdef);
5223 Set_Barrier_Function (Comp_Id, Bdef);
5224 Set_Scope (Bdef, Scope (Comp_Id));
5225 Current_Node := Sub;
5227 -- Collect pointers to the protected subprogram and the barrier
5228 -- of the current entry, for insertion into Entry_Bodies_Array.
5231 Make_Aggregate (Loc,
5232 Expressions => New_List (
5233 Make_Attribute_Reference (Loc,
5234 Prefix => New_Reference_To (Bdef, Loc),
5235 Attribute_Name => Name_Unrestricted_Access),
5236 Make_Attribute_Reference (Loc,
5237 Prefix => New_Reference_To (Edef, Loc),
5238 Attribute_Name => Name_Unrestricted_Access))),
5239 Expressions (Entries_Aggr));
5246 -- If there are some private entry declarations, expand it as if they
5247 -- were visible entries.
5249 if Present (Private_Declarations (Pdef)) then
5250 Comp := First (Private_Declarations (Pdef));
5252 while Present (Comp) loop
5253 if Nkind (Comp) = N_Entry_Declaration then
5254 E_Count := E_Count + 1;
5255 Comp_Id := Defining_Identifier (Comp);
5256 Set_Privals_Chain (Comp_Id, New_Elmt_List);
5257 Nam := Chars (Comp_Id);
5259 Make_Defining_Identifier (Loc,
5260 Build_Selected_Name (Protnm, New_Internal_Name ('E')));
5263 Make_Subprogram_Declaration (Loc,
5265 Build_Protected_Entry_Specification (Edef, Comp_Id, Loc));
5267 Insert_After (Current_Node, Sub);
5270 Set_Protected_Body_Subprogram (
5271 Defining_Identifier (Comp),
5272 Defining_Unit_Name (Specification (Sub)));
5274 Current_Node := Sub;
5277 Make_Defining_Identifier (Loc,
5278 Build_Selected_Name (Protnm, New_Internal_Name ('B')));
5280 Make_Subprogram_Declaration (Loc,
5282 Build_Barrier_Function_Specification (Bdef, Loc));
5284 Insert_After (Current_Node, Sub);
5286 Set_Protected_Body_Subprogram (Bdef, Bdef);
5287 Set_Barrier_Function (Comp_Id, Bdef);
5288 Set_Scope (Bdef, Scope (Comp_Id));
5289 Current_Node := Sub;
5291 -- Collect pointers to the protected subprogram and the
5292 -- barrier of the current entry, for insertion into
5293 -- Entry_Bodies_Array.
5296 Make_Aggregate (Loc,
5297 Expressions => New_List (
5298 Make_Attribute_Reference (Loc,
5299 Prefix => New_Reference_To (Bdef, Loc),
5300 Attribute_Name => Name_Unrestricted_Access),
5301 Make_Attribute_Reference (Loc,
5302 Prefix => New_Reference_To (Edef, Loc),
5303 Attribute_Name => Name_Unrestricted_Access))),
5304 Expressions (Entries_Aggr));
5311 -- Emit declaration for Entry_Bodies_Array, now that the addresses of
5312 -- all protected subprograms have been collected.
5314 if Has_Entries (Prottyp) then
5315 Body_Id := Make_Defining_Identifier (Sloc (Prottyp),
5316 New_External_Name (Chars (Prottyp), 'A'));
5319 or else Restrictions (No_Entry_Queue) = False
5322 Body_Arr := Make_Object_Declaration (Loc,
5323 Defining_Identifier => Body_Id,
5324 Aliased_Present => True,
5325 Object_Definition =>
5326 Make_Subtype_Indication (Loc,
5327 Subtype_Mark => New_Reference_To (
5328 RTE (RE_Protected_Entry_Body_Array), Loc),
5330 Make_Index_Or_Discriminant_Constraint (Loc,
5331 Constraints => New_List (
5333 Make_Integer_Literal (Loc, 1),
5334 Make_Integer_Literal (Loc, E_Count))))),
5335 Expression => Entries_Aggr);
5338 Body_Arr := Make_Object_Declaration (Loc,
5339 Defining_Identifier => Body_Id,
5340 Aliased_Present => True,
5341 Object_Definition => New_Reference_To (RTE (RE_Entry_Body), Loc),
5343 Make_Aggregate (Loc,
5344 Expressions => New_List (
5345 Make_Attribute_Reference (Loc,
5346 Prefix => New_Reference_To (Bdef, Loc),
5347 Attribute_Name => Name_Unrestricted_Access),
5348 Make_Attribute_Reference (Loc,
5349 Prefix => New_Reference_To (Edef, Loc),
5350 Attribute_Name => Name_Unrestricted_Access))));
5353 -- A pointer to this array will be placed in the corresponding
5354 -- record by its initialization procedure, so this needs to be
5357 Insert_After (Current_Node, Body_Arr);
5358 Current_Node := Body_Arr;
5361 Set_Entry_Bodies_Array (Prottyp, Body_Id);
5363 -- Finally, build the function that maps an entry index into the
5364 -- corresponding body. A pointer to this function is placed in each
5365 -- object of the type. Except for a ravenscar-like profile (no abort,
5366 -- no entry queue, 1 entry)
5369 or else Restrictions (No_Entry_Queue) = False
5373 Make_Subprogram_Declaration (Loc,
5374 Specification => Build_Find_Body_Index_Spec (Prottyp));
5375 Insert_After (Current_Node, Sub);
5379 end Expand_N_Protected_Type_Declaration;
5381 --------------------------------
5382 -- Expand_N_Requeue_Statement --
5383 --------------------------------
5385 -- A requeue statement is expanded into one of four GNARLI operations,
5386 -- depending on the source and destination (task or protected object).
5387 -- In addition, code must be generated to jump around the remainder of
5388 -- processing for the original entry and, if the destination is a
5389 -- (different) protected object, to attempt to service it.
5390 -- The following illustrates the various cases:
5393 -- (O : System.Address;
5394 -- P : System.Address;
5395 -- E : Protected_Entry_Index)
5397 -- <discriminant renamings>
5398 -- <private object renamings>
5399 -- type poVP is access poV;
5400 -- _Object : ptVP := ptVP!(O);
5404 -- <start of statement sequence for entry>
5406 -- -- Requeue from one protected entry body to another protected
5409 -- Requeue_Protected_Entry (
5410 -- _object._object'Access,
5411 -- new._object'Access,
5416 -- <some more of the statement sequence for entry>
5418 -- -- Requeue from an entry body to a task entry.
5420 -- Requeue_Protected_To_Task_Entry (
5426 -- <rest of statement sequence for entry>
5427 -- Complete_Entry_Body (_Object._Object);
5430 -- when all others =>
5431 -- Exceptional_Complete_Entry_Body (
5432 -- _Object._Object, Get_GNAT_Exception);
5436 -- Requeue of a task entry call to a task entry.
5438 -- Accept_Call (E, Ann);
5439 -- <start of statement sequence for accept statement>
5440 -- Requeue_Task_Entry (New._task_id, E, Abort_Present);
5442 -- <rest of statement sequence for accept statement>
5444 -- Complete_Rendezvous;
5446 -- when all others =>
5447 -- Exceptional_Complete_Rendezvous (Get_GNAT_Exception);
5449 -- Requeue of a task entry call to a protected entry.
5451 -- Accept_Call (E, Ann);
5452 -- <start of statement sequence for accept statement>
5453 -- Requeue_Task_To_Protected_Entry (
5454 -- new._object'Access,
5459 -- <rest of statement sequence for accept statement>
5461 -- Complete_Rendezvous;
5463 -- when all others =>
5464 -- Exceptional_Complete_Rendezvous (Get_GNAT_Exception);
5466 -- Further details on these expansions can be found in
5467 -- Expand_N_Protected_Body and Expand_N_Accept_Statement.
5469 procedure Expand_N_Requeue_Statement (N : Node_Id) is
5470 Loc : constant Source_Ptr := Sloc (N);
5475 Conctyp : Entity_Id;
5479 Abortable : Node_Id;
5480 Skip_Stat : Node_Id;
5481 Self_Param : Node_Id;
5482 New_Param : Node_Id;
5484 RTS_Call : Entity_Id;
5487 if Abort_Present (N) then
5488 Abortable := New_Occurrence_Of (Standard_True, Loc);
5490 Abortable := New_Occurrence_Of (Standard_False, Loc);
5493 -- Set up the target object.
5495 Extract_Entry (N, Concval, Ename, Index);
5496 Conctyp := Etype (Concval);
5497 New_Param := Concurrent_Ref (Concval);
5499 -- The target entry index and abortable flag are the same for all cases.
5501 Params := New_List (
5502 Entry_Index_Expression (Loc, Entity (Ename), Index, Conctyp),
5505 -- Determine proper GNARLI call and required additional parameters
5506 -- Loop to find nearest enclosing task type or protected type
5508 Oldtyp := Current_Scope;
5510 if Is_Task_Type (Oldtyp) then
5511 if Is_Task_Type (Conctyp) then
5512 RTS_Call := RTE (RE_Requeue_Task_Entry);
5515 pragma Assert (Is_Protected_Type (Conctyp));
5516 RTS_Call := RTE (RE_Requeue_Task_To_Protected_Entry);
5518 Make_Attribute_Reference (Loc,
5519 Prefix => New_Param,
5520 Attribute_Name => Name_Unchecked_Access);
5523 Prepend (New_Param, Params);
5526 elsif Is_Protected_Type (Oldtyp) then
5528 Make_Attribute_Reference (Loc,
5529 Prefix => Concurrent_Ref (New_Occurrence_Of (Oldtyp, Loc)),
5530 Attribute_Name => Name_Unchecked_Access);
5532 if Is_Task_Type (Conctyp) then
5533 RTS_Call := RTE (RE_Requeue_Protected_To_Task_Entry);
5536 pragma Assert (Is_Protected_Type (Conctyp));
5537 RTS_Call := RTE (RE_Requeue_Protected_Entry);
5539 Make_Attribute_Reference (Loc,
5540 Prefix => New_Param,
5541 Attribute_Name => Name_Unchecked_Access);
5544 Prepend (New_Param, Params);
5545 Prepend (Self_Param, Params);
5548 -- If neither task type or protected type, must be in some
5549 -- inner enclosing block, so move on out
5552 Oldtyp := Scope (Oldtyp);
5556 -- Create the GNARLI call.
5558 Rcall := Make_Procedure_Call_Statement (Loc,
5560 New_Occurrence_Of (RTS_Call, Loc),
5561 Parameter_Associations => Params);
5566 if Is_Protected_Type (Oldtyp) then
5568 -- Build the return statement to skip the rest of the entry body
5570 Skip_Stat := Make_Return_Statement (Loc);
5573 -- If the requeue is within a task, find the end label of the
5574 -- enclosing accept statement.
5576 Acc_Stat := Parent (N);
5577 while Nkind (Acc_Stat) /= N_Accept_Statement loop
5578 Acc_Stat := Parent (Acc_Stat);
5581 -- The last statement is the second label, used for completing the
5582 -- rendezvous the usual way.
5583 -- The label we are looking for is right before it.
5586 Prev (Last (Statements (Handled_Statement_Sequence (Acc_Stat))));
5588 pragma Assert (Nkind (Lab_Node) = N_Label);
5590 -- Build the goto statement to skip the rest of the accept
5594 Make_Goto_Statement (Loc,
5595 Name => New_Occurrence_Of (Entity (Identifier (Lab_Node)), Loc));
5598 Set_Analyzed (Skip_Stat);
5600 Insert_After (N, Skip_Stat);
5602 end Expand_N_Requeue_Statement;
5604 -------------------------------
5605 -- Expand_N_Selective_Accept --
5606 -------------------------------
5608 procedure Expand_N_Selective_Accept (N : Node_Id) is
5609 Loc : constant Source_Ptr := Sloc (N);
5610 Alts : constant List_Id := Select_Alternatives (N);
5612 Accept_Case : List_Id;
5613 Accept_List : List_Id := New_List;
5616 Alt_List : List_Id := New_List;
5617 Alt_Stats : List_Id;
5618 Ann : Entity_Id := Empty;
5621 Check_Guard : Boolean := True;
5622 Decls : List_Id := New_List;
5623 Stats : List_Id := New_List;
5625 Body_List : List_Id := New_List;
5626 Trailing_List : List_Id := New_List;
5629 Else_Present : Boolean := False;
5630 Terminate_Alt : Node_Id := Empty;
5631 Select_Mode : Node_Id;
5633 Delay_Case : List_Id;
5634 Delay_Count : Integer := 0;
5635 Delay_Val : Entity_Id;
5636 Delay_Index : Entity_Id;
5637 Delay_Min : Entity_Id;
5638 Delay_Num : Int := 1;
5639 Delay_Alt_List : List_Id := New_List;
5640 Delay_List : List_Id := New_List;
5644 First_Delay : Boolean := True;
5645 Guard_Open : Entity_Id;
5651 Num_Accept : Nat := 0;
5654 Time_Type : Entity_Id;
5656 Select_Call : Node_Id;
5658 Qnam : constant Entity_Id :=
5659 Make_Defining_Identifier (Loc, New_External_Name ('S', 0));
5661 Xnam : constant Entity_Id :=
5662 Make_Defining_Identifier (Loc, New_External_Name ('J', 1));
5664 -----------------------
5665 -- Local subprograms --
5666 -----------------------
5668 function Accept_Or_Raise return List_Id;
5669 -- For the rare case where delay alternatives all have guards, and
5670 -- all of them are closed, it is still possible that there were open
5671 -- accept alternatives with no callers. We must reexamine the
5672 -- Accept_List, and execute a selective wait with no else if some
5673 -- accept is open. If none, we raise program_error.
5675 procedure Add_Accept (Alt : Node_Id);
5676 -- Process a single accept statement in a select alternative. Build
5677 -- procedure for body of accept, and add entry to dispatch table with
5678 -- expression for guard, in preparation for call to run time select.
5680 function Make_And_Declare_Label (Num : Int) return Node_Id;
5681 -- Manufacture a label using Num as a serial number and declare it.
5682 -- The declaration is appended to Decls. The label marks the trailing
5683 -- statements of an accept or delay alternative.
5685 function Make_Select_Call (Select_Mode : Entity_Id) return Node_Id;
5686 -- Build call to Selective_Wait runtime routine.
5688 procedure Process_Delay_Alternative (Alt : Node_Id; Index : Int);
5689 -- Add code to compare value of delay with previous values, and
5690 -- generate case entry for trailing statements.
5692 procedure Process_Accept_Alternative
5696 -- Add code to call corresponding procedure, and branch to
5697 -- trailing statements, if any.
5699 ---------------------
5700 -- Accept_Or_Raise --
5701 ---------------------
5703 function Accept_Or_Raise return List_Id is
5706 J : constant Entity_Id := Make_Defining_Identifier (Loc,
5707 New_Internal_Name ('J'));
5710 -- We generate the following:
5712 -- for J in q'range loop
5713 -- if q(J).S /=null_task_entry then
5714 -- selective_wait (simple_mode,...);
5720 -- if no rendez_vous then
5721 -- raise program_error;
5724 -- Note that the code needs to know that the selector name
5725 -- in an Accept_Alternative is named S.
5727 Cond := Make_Op_Ne (Loc,
5729 Make_Selected_Component (Loc,
5730 Prefix => Make_Indexed_Component (Loc,
5731 Prefix => New_Reference_To (Qnam, Loc),
5732 Expressions => New_List (New_Reference_To (J, Loc))),
5733 Selector_Name => Make_Identifier (Loc, Name_S)),
5735 New_Reference_To (RTE (RE_Null_Task_Entry), Loc));
5738 Make_Implicit_Loop_Statement (N,
5739 Identifier => Empty,
5741 Make_Iteration_Scheme (Loc,
5742 Loop_Parameter_Specification =>
5743 Make_Loop_Parameter_Specification (Loc,
5744 Defining_Identifier => J,
5745 Discrete_Subtype_Definition =>
5746 Make_Attribute_Reference (Loc,
5747 Prefix => New_Reference_To (Qnam, Loc),
5748 Attribute_Name => Name_Range,
5749 Expressions => New_List (
5750 Make_Integer_Literal (Loc, 1))))),
5752 Statements => New_List (
5753 Make_Implicit_If_Statement (N,
5755 Then_Statements => New_List (
5757 New_Reference_To (RTE (RE_Simple_Mode), Loc)),
5758 Make_Exit_Statement (Loc))))));
5761 Make_Raise_Program_Error (Loc,
5762 Condition => Make_Op_Eq (Loc,
5763 Left_Opnd => New_Reference_To (Xnam, Loc),
5765 New_Reference_To (RTE (RE_No_Rendezvous), Loc)),
5766 Reason => PE_All_Guards_Closed));
5769 end Accept_Or_Raise;
5775 procedure Add_Accept (Alt : Node_Id) is
5776 Acc_Stm : constant Node_Id := Accept_Statement (Alt);
5777 Ename : constant Node_Id := Entry_Direct_Name (Acc_Stm);
5778 Eent : constant Entity_Id := Entity (Ename);
5779 Index : constant Node_Id := Entry_Index (Acc_Stm);
5780 Null_Body : Node_Id;
5781 Proc_Body : Node_Id;
5788 Ann := Node (Last_Elmt (Accept_Address (Eent)));
5791 if Present (Condition (Alt)) then
5793 Make_Conditional_Expression (Loc, New_List (
5795 Entry_Index_Expression (Loc, Eent, Index, Scope (Eent)),
5796 New_Reference_To (RTE (RE_Null_Task_Entry), Loc)));
5799 Entry_Index_Expression
5800 (Loc, Eent, Index, Scope (Eent));
5803 if Present (Handled_Statement_Sequence (Accept_Statement (Alt))) then
5804 Null_Body := New_Reference_To (Standard_False, Loc);
5806 if Abort_Allowed then
5807 Call := Make_Procedure_Call_Statement (Loc,
5808 Name => New_Reference_To (RTE (RE_Abort_Undefer), Loc));
5809 Insert_Before (First (Statements (Handled_Statement_Sequence (
5810 Accept_Statement (Alt)))), Call);
5815 Make_Defining_Identifier (Sloc (Ename),
5816 New_External_Name (Chars (Ename), 'A', Num_Accept));
5819 Make_Subprogram_Body (Loc,
5821 Make_Procedure_Specification (Loc,
5822 Defining_Unit_Name => PB_Ent),
5823 Declarations => Declarations (Acc_Stm),
5824 Handled_Statement_Sequence =>
5825 Build_Accept_Body (Accept_Statement (Alt)));
5827 -- During the analysis of the body of the accept statement, any
5828 -- zero cost exception handler records were collected in the
5829 -- Accept_Handler_Records field of the N_Accept_Alternative
5830 -- node. This is where we move them to where they belong,
5831 -- namely the newly created procedure.
5833 Set_Handler_Records (PB_Ent, Accept_Handler_Records (Alt));
5834 Append (Proc_Body, Body_List);
5837 Null_Body := New_Reference_To (Standard_True, Loc);
5839 -- if accept statement has declarations, insert above, given
5840 -- that we are not creating a body for the accept.
5842 if Present (Declarations (Acc_Stm)) then
5843 Insert_Actions (N, Declarations (Acc_Stm));
5847 Append_To (Accept_List,
5848 Make_Aggregate (Loc, Expressions => New_List (Null_Body, Expr)));
5850 Num_Accept := Num_Accept + 1;
5854 ----------------------------
5855 -- Make_And_Declare_Label --
5856 ----------------------------
5858 function Make_And_Declare_Label (Num : Int) return Node_Id is
5862 Lab_Id := Make_Identifier (Loc, New_External_Name ('L', Num));
5864 Make_Label (Loc, Lab_Id);
5867 Make_Implicit_Label_Declaration (Loc,
5868 Defining_Identifier =>
5869 Make_Defining_Identifier (Loc, Chars (Lab_Id)),
5870 Label_Construct => Lab));
5873 end Make_And_Declare_Label;
5875 ----------------------
5876 -- Make_Select_Call --
5877 ----------------------
5879 function Make_Select_Call (Select_Mode : Entity_Id) return Node_Id is
5880 Params : List_Id := New_List;
5884 Make_Attribute_Reference (Loc,
5885 Prefix => New_Reference_To (Qnam, Loc),
5886 Attribute_Name => Name_Unchecked_Access),
5888 Append (Select_Mode, Params);
5889 Append (New_Reference_To (Ann, Loc), Params);
5890 Append (New_Reference_To (Xnam, Loc), Params);
5893 Make_Procedure_Call_Statement (Loc,
5894 Name => New_Reference_To (RTE (RE_Selective_Wait), Loc),
5895 Parameter_Associations => Params);
5896 end Make_Select_Call;
5898 --------------------------------
5899 -- Process_Accept_Alternative --
5900 --------------------------------
5902 procedure Process_Accept_Alternative
5907 Choices : List_Id := No_List;
5908 Alt_Stats : List_Id;
5911 Adjust_Condition (Condition (Alt));
5912 Alt_Stats := No_List;
5914 if Present (Handled_Statement_Sequence (Accept_Statement (Alt))) then
5915 Choices := New_List (
5916 Make_Integer_Literal (Loc, Index));
5918 Alt_Stats := New_List (
5919 Make_Procedure_Call_Statement (Loc,
5920 Name => New_Reference_To (
5921 Defining_Unit_Name (Specification (Proc)), Loc)));
5924 if Statements (Alt) /= Empty_List then
5926 if No (Alt_Stats) then
5928 -- Accept with no body, followed by trailing statements.
5930 Choices := New_List (
5931 Make_Integer_Literal (Loc, Index));
5933 Alt_Stats := New_List;
5936 -- After the call, if any, branch to to trailing statements.
5937 -- We create a label for each, as well as the corresponding
5938 -- label declaration.
5940 Lab := Make_And_Declare_Label (Index);
5941 Append_To (Alt_Stats,
5942 Make_Goto_Statement (Loc,
5943 Name => New_Copy (Identifier (Lab))));
5945 Append (Lab, Trailing_List);
5946 Append_List (Statements (Alt), Trailing_List);
5947 Append_To (Trailing_List,
5948 Make_Goto_Statement (Loc,
5949 Name => New_Copy (Identifier (End_Lab))));
5952 if Present (Alt_Stats) then
5954 -- Procedure call. and/or trailing statements
5956 Append_To (Alt_List,
5957 Make_Case_Statement_Alternative (Loc,
5958 Discrete_Choices => Choices,
5959 Statements => Alt_Stats));
5961 end Process_Accept_Alternative;
5963 -------------------------------
5964 -- Process_Delay_Alternative --
5965 -------------------------------
5967 procedure Process_Delay_Alternative (Alt : Node_Id; Index : Int) is
5970 Delay_Alt : List_Id;
5973 -- Deal with C/Fortran boolean as delay condition
5975 Adjust_Condition (Condition (Alt));
5977 -- Determine the smallest specified delay.
5978 -- for each delay alternative generate:
5980 -- if guard-expression then
5981 -- Delay_Val := delay-expression;
5982 -- Guard_Open := True;
5983 -- if Delay_Val < Delay_Min then
5984 -- Delay_Min := Delay_Val;
5985 -- Delay_Index := Index;
5989 -- The enclosing if-statement is omitted if there is no guard.
5994 First_Delay := False;
5996 Delay_Alt := New_List (
5997 Make_Assignment_Statement (Loc,
5998 Name => New_Reference_To (Delay_Min, Loc),
5999 Expression => Expression (Delay_Statement (Alt))));
6001 if Delay_Count > 1 then
6002 Append_To (Delay_Alt,
6003 Make_Assignment_Statement (Loc,
6004 Name => New_Reference_To (Delay_Index, Loc),
6005 Expression => Make_Integer_Literal (Loc, Index)));
6009 Delay_Alt := New_List (
6010 Make_Assignment_Statement (Loc,
6011 Name => New_Reference_To (Delay_Val, Loc),
6012 Expression => Expression (Delay_Statement (Alt))));
6014 if Time_Type = Standard_Duration then
6017 Left_Opnd => New_Reference_To (Delay_Val, Loc),
6018 Right_Opnd => New_Reference_To (Delay_Min, Loc));
6021 -- The scope of the time type must define a comparison
6022 -- operator. The scope itself may not be visible, so we
6023 -- construct a node with entity information to insure that
6024 -- semantic analysis can find the proper operator.
6027 Make_Function_Call (Loc,
6028 Name => Make_Selected_Component (Loc,
6029 Prefix => New_Reference_To (Scope (Time_Type), Loc),
6031 Make_Operator_Symbol (Loc,
6032 Chars => Name_Op_Lt,
6033 Strval => No_String)),
6034 Parameter_Associations =>
6036 New_Reference_To (Delay_Val, Loc),
6037 New_Reference_To (Delay_Min, Loc)));
6039 Set_Entity (Prefix (Name (Cond)), Scope (Time_Type));
6042 Append_To (Delay_Alt,
6043 Make_Implicit_If_Statement (N,
6045 Then_Statements => New_List (
6046 Make_Assignment_Statement (Loc,
6047 Name => New_Reference_To (Delay_Min, Loc),
6048 Expression => New_Reference_To (Delay_Val, Loc)),
6050 Make_Assignment_Statement (Loc,
6051 Name => New_Reference_To (Delay_Index, Loc),
6052 Expression => Make_Integer_Literal (Loc, Index)))));
6056 Append_To (Delay_Alt,
6057 Make_Assignment_Statement (Loc,
6058 Name => New_Reference_To (Guard_Open, Loc),
6059 Expression => New_Reference_To (Standard_True, Loc)));
6062 if Present (Condition (Alt)) then
6063 Delay_Alt := New_List (
6064 Make_Implicit_If_Statement (N,
6065 Condition => Condition (Alt),
6066 Then_Statements => Delay_Alt));
6069 Append_List (Delay_Alt, Delay_List);
6071 -- If the delay alternative has a statement part, add a
6072 -- choice to the case statements for delays.
6074 if Present (Statements (Alt)) then
6076 if Delay_Count = 1 then
6077 Append_List (Statements (Alt), Delay_Alt_List);
6080 Choices := New_List (
6081 Make_Integer_Literal (Loc, Index));
6083 Append_To (Delay_Alt_List,
6084 Make_Case_Statement_Alternative (Loc,
6085 Discrete_Choices => Choices,
6086 Statements => Statements (Alt)));
6089 elsif Delay_Count = 1 then
6091 -- If the single delay has no trailing statements, add a branch
6092 -- to the exit label to the selective wait.
6094 Delay_Alt_List := New_List (
6095 Make_Goto_Statement (Loc,
6096 Name => New_Copy (Identifier (End_Lab))));
6099 end Process_Delay_Alternative;
6101 -- Start of processing for Expand_N_Selective_Accept
6104 -- First insert some declarations before the select. The first is:
6108 -- This variable holds the parameters passed to the accept body. This
6109 -- declaration has already been inserted by the time we get here by
6110 -- a call to Expand_Accept_Declarations made from the semantics when
6111 -- processing the first accept statement contained in the select. We
6112 -- can find this entity as Accept_Address (E), where E is any of the
6113 -- entries references by contained accept statements.
6115 -- The first step is to scan the list of Selective_Accept_Statements
6116 -- to find this entity, and also count the number of accepts, and
6117 -- determine if terminated, delay or else is present:
6121 Alt := First (Alts);
6122 while Present (Alt) loop
6124 if Nkind (Alt) = N_Accept_Alternative then
6127 elsif Nkind (Alt) = N_Delay_Alternative then
6128 Delay_Count := Delay_Count + 1;
6130 -- If the delays are relative delays, the delay expressions have
6131 -- type Standard_Duration. Otherwise they must have some time type
6132 -- recognized by GNAT.
6134 if Nkind (Delay_Statement (Alt)) = N_Delay_Relative_Statement then
6135 Time_Type := Standard_Duration;
6137 Time_Type := Etype (Expression (Delay_Statement (Alt)));
6139 if Is_RTE (Base_Type (Etype (Time_Type)), RO_CA_Time)
6140 or else Is_RTE (Base_Type (Etype (Time_Type)), RO_RT_Time)
6145 "& is not a time type ('R'M 9.6(6))",
6146 Expression (Delay_Statement (Alt)), Time_Type);
6147 Time_Type := Standard_Duration;
6148 Set_Etype (Expression (Delay_Statement (Alt)), Any_Type);
6152 if No (Condition (Alt)) then
6154 -- This guard will always be open.
6156 Check_Guard := False;
6159 elsif Nkind (Alt) = N_Terminate_Alternative then
6160 Adjust_Condition (Condition (Alt));
6161 Terminate_Alt := Alt;
6164 Num_Alts := Num_Alts + 1;
6168 Else_Present := Present (Else_Statements (N));
6170 -- At the same time (see procedure Add_Accept) we build the accept list:
6172 -- Qnn : Accept_List (1 .. num-select) := (
6173 -- (null-body, entry-index),
6174 -- (null-body, entry-index),
6176 -- (null_body, entry-index));
6178 -- In the above declaration, null-body is True if the corresponding
6179 -- accept has no body, and false otherwise. The entry is either the
6180 -- entry index expression if there is no guard, or if a guard is
6181 -- present, then a conditional expression of the form:
6183 -- (if guard then entry-index else Null_Task_Entry)
6185 -- If a guard is statically known to be false, the entry can simply
6186 -- be omitted from the accept list.
6189 Make_Object_Declaration (Loc,
6190 Defining_Identifier => Qnam,
6191 Object_Definition =>
6192 New_Reference_To (RTE (RE_Accept_List), Loc),
6193 Aliased_Present => True,
6196 Make_Qualified_Expression (Loc,
6198 New_Reference_To (RTE (RE_Accept_List), Loc),
6200 Make_Aggregate (Loc, Expressions => Accept_List)));
6204 -- Then we declare the variable that holds the index for the accept
6205 -- that will be selected for service:
6207 -- Xnn : Select_Index;
6210 Make_Object_Declaration (Loc,
6211 Defining_Identifier => Xnam,
6212 Object_Definition =>
6213 New_Reference_To (RTE (RE_Select_Index), Loc),
6215 New_Reference_To (RTE (RE_No_Rendezvous), Loc));
6219 -- After this follow procedure declarations for each accept body.
6226 -- where the ... are statements from the corresponding procedure body.
6227 -- No parameters are involved, since the parameters are passed via Ann
6228 -- and the parameter references have already been expanded to be direct
6229 -- references to Ann (see Exp_Ch2.Expand_Entry_Parameter). Furthermore,
6230 -- any embedded tasking statements (which would normally be illegal in
6231 -- procedures, have been converted to calls to the tasking runtime so
6232 -- there is no problem in putting them into procedures.
6234 -- The original accept statement has been expanded into a block in
6235 -- the same fashion as for simple accepts (see Build_Accept_Body).
6237 -- Note: we don't really need to build these procedures for the case
6238 -- where no delay statement is present, but it is just as easy to
6239 -- build them unconditionally, and not significantly inefficient,
6240 -- since if they are short they will be inlined anyway.
6242 -- The procedure declarations have been assembled in Body_List.
6244 -- If delays are present, we must compute the required delay.
6245 -- We first generate the declarations:
6247 -- Delay_Index : Boolean := 0;
6248 -- Delay_Min : Some_Time_Type.Time;
6249 -- Delay_Val : Some_Time_Type.Time;
6251 -- Delay_Index will be set to the index of the minimum delay, i.e. the
6252 -- active delay that is actually chosen as the basis for the possible
6253 -- delay if an immediate rendez-vous is not possible.
6254 -- In the most common case there is a single delay statement, and this
6255 -- is handled specially.
6257 if Delay_Count > 0 then
6259 -- Generate the required declarations
6262 Make_Defining_Identifier (Loc, New_External_Name ('D', 1));
6264 Make_Defining_Identifier (Loc, New_External_Name ('D', 2));
6266 Make_Defining_Identifier (Loc, New_External_Name ('D', 3));
6269 Make_Object_Declaration (Loc,
6270 Defining_Identifier => Delay_Val,
6271 Object_Definition => New_Reference_To (Time_Type, Loc)));
6274 Make_Object_Declaration (Loc,
6275 Defining_Identifier => Delay_Index,
6276 Object_Definition => New_Reference_To (Standard_Integer, Loc),
6277 Expression => Make_Integer_Literal (Loc, 0)));
6280 Make_Object_Declaration (Loc,
6281 Defining_Identifier => Delay_Min,
6282 Object_Definition => New_Reference_To (Time_Type, Loc),
6284 Unchecked_Convert_To (Time_Type,
6285 Make_Attribute_Reference (Loc,
6287 New_Occurrence_Of (Underlying_Type (Time_Type), Loc),
6288 Attribute_Name => Name_Last))));
6290 -- Create Duration and Delay_Mode objects used for passing a delay
6293 D := Make_Defining_Identifier (Loc, New_Internal_Name ('D'));
6294 M := Make_Defining_Identifier (Loc, New_Internal_Name ('M'));
6300 -- Note that these values are defined in s-osprim.ads and must
6303 -- Relative : constant := 0;
6304 -- Absolute_Calendar : constant := 1;
6305 -- Absolute_RT : constant := 2;
6307 if Time_Type = Standard_Duration then
6308 Discr := Make_Integer_Literal (Loc, 0);
6310 elsif Is_RTE (Base_Type (Etype (Time_Type)), RO_CA_Time) then
6311 Discr := Make_Integer_Literal (Loc, 1);
6315 (Is_RTE (Base_Type (Etype (Time_Type)), RO_RT_Time));
6316 Discr := Make_Integer_Literal (Loc, 2);
6320 Make_Object_Declaration (Loc,
6321 Defining_Identifier => D,
6322 Object_Definition =>
6323 New_Reference_To (Standard_Duration, Loc)));
6326 Make_Object_Declaration (Loc,
6327 Defining_Identifier => M,
6328 Object_Definition =>
6329 New_Reference_To (Standard_Integer, Loc),
6330 Expression => Discr));
6335 Make_Defining_Identifier (Loc, New_External_Name ('G', 1));
6338 Make_Object_Declaration (Loc,
6339 Defining_Identifier => Guard_Open,
6340 Object_Definition => New_Reference_To (Standard_Boolean, Loc),
6341 Expression => New_Reference_To (Standard_False, Loc)));
6344 -- Delay_Count is zero, don't need M and D set (suppress warning)
6351 if Present (Terminate_Alt) then
6353 -- If the terminate alternative guard is False, use
6354 -- Simple_Mode; otherwise use Terminate_Mode.
6356 if Present (Condition (Terminate_Alt)) then
6357 Select_Mode := Make_Conditional_Expression (Loc,
6358 New_List (Condition (Terminate_Alt),
6359 New_Reference_To (RTE (RE_Terminate_Mode), Loc),
6360 New_Reference_To (RTE (RE_Simple_Mode), Loc)));
6362 Select_Mode := New_Reference_To (RTE (RE_Terminate_Mode), Loc);
6365 elsif Else_Present or Delay_Count > 0 then
6366 Select_Mode := New_Reference_To (RTE (RE_Else_Mode), Loc);
6369 Select_Mode := New_Reference_To (RTE (RE_Simple_Mode), Loc);
6372 Select_Call := Make_Select_Call (Select_Mode);
6373 Append (Select_Call, Stats);
6375 -- Now generate code to act on the result. There is an entry
6376 -- in this case for each accept statement with a non-null body,
6377 -- followed by a branch to the statements that follow the Accept.
6378 -- In the absence of delay alternatives, we generate:
6381 -- when No_Rendezvous => -- omitted if simple mode
6396 -- Lab0: Else_Statements;
6399 -- Lab1: Trailing_Statements1;
6402 -- Lab2: Trailing_Statements2;
6407 -- Generate label for common exit.
6409 End_Lab := Make_And_Declare_Label (Num_Alts + 1);
6411 -- First entry is the default case, when no rendezvous is possible.
6413 Choices := New_List (New_Reference_To (RTE (RE_No_Rendezvous), Loc));
6415 if Else_Present then
6417 -- If no rendezvous is possible, the else part is executed.
6419 Lab := Make_And_Declare_Label (0);
6420 Alt_Stats := New_List (
6421 Make_Goto_Statement (Loc,
6422 Name => New_Copy (Identifier (Lab))));
6424 Append (Lab, Trailing_List);
6425 Append_List (Else_Statements (N), Trailing_List);
6426 Append_To (Trailing_List,
6427 Make_Goto_Statement (Loc,
6428 Name => New_Copy (Identifier (End_Lab))));
6430 Alt_Stats := New_List (
6431 Make_Goto_Statement (Loc,
6432 Name => New_Copy (Identifier (End_Lab))));
6435 Append_To (Alt_List,
6436 Make_Case_Statement_Alternative (Loc,
6437 Discrete_Choices => Choices,
6438 Statements => Alt_Stats));
6440 -- We make use of the fact that Accept_Index is an integer type,
6441 -- and generate successive literals for entries for each accept.
6442 -- Only those for which there is a body or trailing statements are
6443 -- given a case entry.
6445 Alt := First (Select_Alternatives (N));
6446 Proc := First (Body_List);
6448 while Present (Alt) loop
6450 if Nkind (Alt) = N_Accept_Alternative then
6451 Process_Accept_Alternative (Alt, Index, Proc);
6455 (Handled_Statement_Sequence (Accept_Statement (Alt)))
6460 elsif Nkind (Alt) = N_Delay_Alternative then
6461 Process_Delay_Alternative (Alt, Delay_Num);
6462 Delay_Num := Delay_Num + 1;
6468 -- An others choice is always added to the main case, as well
6469 -- as the delay case (to satisfy the compiler).
6471 Append_To (Alt_List,
6472 Make_Case_Statement_Alternative (Loc,
6474 New_List (Make_Others_Choice (Loc)),
6476 New_List (Make_Goto_Statement (Loc,
6477 Name => New_Copy (Identifier (End_Lab))))));
6479 Accept_Case := New_List (
6480 Make_Case_Statement (Loc,
6481 Expression => New_Reference_To (Xnam, Loc),
6482 Alternatives => Alt_List));
6484 Append_List (Trailing_List, Accept_Case);
6485 Append (End_Lab, Accept_Case);
6486 Append_List (Body_List, Decls);
6488 -- Construct case statement for trailing statements of delay
6489 -- alternatives, if there are several of them.
6491 if Delay_Count > 1 then
6492 Append_To (Delay_Alt_List,
6493 Make_Case_Statement_Alternative (Loc,
6495 New_List (Make_Others_Choice (Loc)),
6497 New_List (Make_Null_Statement (Loc))));
6499 Delay_Case := New_List (
6500 Make_Case_Statement (Loc,
6501 Expression => New_Reference_To (Delay_Index, Loc),
6502 Alternatives => Delay_Alt_List));
6504 Delay_Case := Delay_Alt_List;
6507 -- If there are no delay alternatives, we append the case statement
6508 -- to the statement list.
6510 if Delay_Count = 0 then
6511 Append_List (Accept_Case, Stats);
6513 -- Delay alternatives present
6516 -- If delay alternatives are present we generate:
6518 -- find minimum delay.
6519 -- DX := minimum delay;
6520 -- M := <delay mode>;
6521 -- Timed_Selective_Wait (Q'Unchecked_Access, Delay_Mode, P,
6524 -- if X = No_Rendezvous then
6525 -- case statement for delay statements.
6527 -- case statement for accept alternatives.
6538 -- The type of the delay expression is known to be legal
6540 if Time_Type = Standard_Duration then
6541 Conv := New_Reference_To (Delay_Min, Loc);
6543 elsif Is_RTE (Base_Type (Etype (Time_Type)), RO_CA_Time) then
6544 Conv := Make_Function_Call (Loc,
6545 New_Reference_To (RTE (RO_CA_To_Duration), Loc),
6546 New_List (New_Reference_To (Delay_Min, Loc)));
6550 (Is_RTE (Base_Type (Etype (Time_Type)), RO_RT_Time));
6552 Conv := Make_Function_Call (Loc,
6553 New_Reference_To (RTE (RO_RT_To_Duration), Loc),
6554 New_List (New_Reference_To (Delay_Min, Loc)));
6557 Stmt := Make_Assignment_Statement (Loc,
6558 Name => New_Reference_To (D, Loc),
6559 Expression => Conv);
6561 -- Change the value for Accept_Modes. (Else_Mode -> Delay_Mode)
6563 Parms := Parameter_Associations (Select_Call);
6564 Parm := First (Parms);
6566 while Present (Parm)
6567 and then Parm /= Select_Mode
6572 pragma Assert (Present (Parm));
6573 Rewrite (Parm, New_Reference_To (RTE (RE_Delay_Mode), Loc));
6576 -- Prepare two new parameters of Duration and Delay_Mode type
6577 -- which represent the value and the mode of the minimum delay.
6580 Insert_After (Parm, New_Reference_To (M, Loc));
6581 Insert_After (Parm, New_Reference_To (D, Loc));
6583 -- Create a call to RTS.
6585 Rewrite (Select_Call,
6586 Make_Procedure_Call_Statement (Loc,
6587 Name => New_Reference_To (RTE (RE_Timed_Selective_Wait), Loc),
6588 Parameter_Associations => Parms));
6590 -- This new call should follow the calculation of the
6593 Insert_List_Before (Select_Call, Delay_List);
6597 Make_Implicit_If_Statement (N,
6598 Condition => New_Reference_To (Guard_Open, Loc),
6600 New_List (New_Copy_Tree (Stmt),
6601 New_Copy_Tree (Select_Call)),
6602 Else_Statements => Accept_Or_Raise);
6603 Rewrite (Select_Call, Stmt);
6605 Insert_Before (Select_Call, Stmt);
6609 Make_Implicit_If_Statement (N,
6610 Condition => Make_Op_Eq (Loc,
6611 Left_Opnd => New_Reference_To (Xnam, Loc),
6613 New_Reference_To (RTE (RE_No_Rendezvous), Loc)),
6615 Then_Statements => Delay_Case,
6616 Else_Statements => Accept_Case);
6618 Append (Cases, Stats);
6622 -- Replace accept statement with appropriate block
6625 Make_Block_Statement (Loc,
6626 Declarations => Decls,
6627 Handled_Statement_Sequence =>
6628 Make_Handled_Sequence_Of_Statements (Loc,
6629 Statements => Stats));
6634 -- Note: have to worry more about abort deferral in above code ???
6636 -- Final step is to unstack the Accept_Address entries for all accept
6637 -- statements appearing in accept alternatives in the select statement
6639 Alt := First (Alts);
6640 while Present (Alt) loop
6641 if Nkind (Alt) = N_Accept_Alternative then
6642 Remove_Last_Elmt (Accept_Address
6643 (Entity (Entry_Direct_Name (Accept_Statement (Alt)))));
6649 end Expand_N_Selective_Accept;
6651 --------------------------------------
6652 -- Expand_N_Single_Task_Declaration --
6653 --------------------------------------
6655 -- Single task declarations should never be present after semantic
6656 -- analysis, since we expect them to be replaced by a declaration of
6657 -- an anonymous task type, followed by a declaration of the task
6658 -- object. We include this routine to make sure that is happening!
6660 procedure Expand_N_Single_Task_Declaration (N : Node_Id) is
6662 raise Program_Error;
6663 end Expand_N_Single_Task_Declaration;
6665 ------------------------
6666 -- Expand_N_Task_Body --
6667 ------------------------
6669 -- Given a task body
6671 -- task body tname is
6677 -- This expansion routine converts it into a procedure and sets the
6678 -- elaboration flag for the procedure to true, to represent the fact
6679 -- that the task body is now elaborated:
6681 -- procedure tnameB (_Task : access tnameV) is
6682 -- discriminal : dtype renames _Task.discriminant;
6684 -- procedure _clean is
6688 -- Abort_Undefer.all;
6692 -- Abort_Undefer.all;
6694 -- System.Task_Stages.Complete_Activation;
6702 -- In addition, if the task body is an activator, then a call to
6703 -- activate tasks is added at the start of the statements, before
6704 -- the call to Complete_Activation, and if in addition the task is
6705 -- a master then it must be established as a master. These calls are
6706 -- inserted and analyzed in Expand_Cleanup_Actions, when the
6707 -- Handled_Sequence_Of_Statements is expanded.
6709 -- There is one discriminal declaration line generated for each
6710 -- discriminant that is present to provide an easy reference point
6711 -- for discriminant references inside the body (see Exp_Ch2.Expand_Name).
6713 -- Note on relationship to GNARLI definition. In the GNARLI definition,
6714 -- task body procedures have a profile (Arg : System.Address). That is
6715 -- needed because GNARLI has to use the same access-to-subprogram type
6716 -- for all task types. We depend here on knowing that in GNAT, passing
6717 -- an address argument by value is identical to passing a record value
6718 -- by access (in either case a single pointer is passed), so even though
6719 -- this procedure has the wrong profile. In fact it's all OK, since the
6720 -- callings sequence is identical.
6722 procedure Expand_N_Task_Body (N : Node_Id) is
6723 Loc : constant Source_Ptr := Sloc (N);
6724 Ttyp : constant Entity_Id := Corresponding_Spec (N);
6729 -- Do not attempt expansion if in no run time mode
6732 and then not Restricted_Profile
6734 Disallow_In_No_Run_Time_Mode (N);
6738 -- Here we start the expansion by generating discriminal declarations
6740 Add_Discriminal_Declarations (Declarations (N), Ttyp, Name_uTask, Loc);
6742 -- Add a call to Abort_Undefer at the very beginning of the task
6743 -- body since this body is called with abort still deferred.
6745 if Abort_Allowed then
6746 Call := Build_Runtime_Call (Loc, RE_Abort_Undefer);
6748 (First (Statements (Handled_Statement_Sequence (N))), Call);
6752 -- The statement part has already been protected with an at_end and
6753 -- cleanup actions. The call to Complete_Activation must be placed
6754 -- at the head of the sequence of statements of that block. The
6755 -- declarations have been merged in this sequence of statements but
6756 -- the first real statement is accessible from the First_Real_Statement
6757 -- field (which was set for exactly this purpose).
6759 if Restricted_Profile then
6760 Call := Build_Runtime_Call (Loc, RE_Complete_Restricted_Activation);
6762 Call := Build_Runtime_Call (Loc, RE_Complete_Activation);
6766 (First_Real_Statement (Handled_Statement_Sequence (N)), Call);
6770 Make_Subprogram_Body (Loc,
6771 Specification => Build_Task_Proc_Specification (Ttyp),
6772 Declarations => Declarations (N),
6773 Handled_Statement_Sequence => Handled_Statement_Sequence (N));
6775 -- If the task contains generic instantiations, cleanup actions
6776 -- are delayed until after instantiation. Transfer the activation
6777 -- chain to the subprogram, to insure that the activation call is
6778 -- properly generated. It the task body contains inner tasks, indicate
6779 -- that the subprogram is a task master.
6781 if Delay_Cleanups (Ttyp) then
6782 Set_Activation_Chain_Entity (New_N, Activation_Chain_Entity (N));
6783 Set_Is_Task_Master (New_N, Is_Task_Master (N));
6789 -- Set elaboration flag immediately after task body. If the body
6790 -- is a subunit, the flag is set in the declarative part that
6791 -- contains the stub.
6793 if Nkind (Parent (N)) /= N_Subunit then
6795 Make_Assignment_Statement (Loc,
6797 Make_Identifier (Loc, New_External_Name (Chars (Ttyp), 'E')),
6798 Expression => New_Reference_To (Standard_True, Loc)));
6800 end Expand_N_Task_Body;
6802 ------------------------------------
6803 -- Expand_N_Task_Type_Declaration --
6804 ------------------------------------
6806 -- We have several things to do. First we must create a Boolean flag used
6807 -- to mark if the body is elaborated yet. This variable gets set to True
6808 -- when the body of the task is elaborated (we can't rely on the normal
6809 -- ABE mechanism for the task body, since we need to pass an access to
6810 -- this elaboration boolean to the runtime routines).
6812 -- taskE : aliased Boolean := False;
6814 -- Next a variable is declared to hold the task stack size (either
6815 -- the default : Unspecified_Size, or a value that is set by a pragma
6816 -- Storage_Size). If the value of the pragma Storage_Size is static, then
6817 -- the variable is initialized with this value:
6819 -- taskZ : Size_Type := Unspecified_Size;
6821 -- taskZ : Size_Type := Size_Type (size_expression);
6823 -- Next we create a corresponding record type declaration used to represent
6824 -- values of this task. The general form of this type declaration is
6826 -- type taskV (discriminants) is record
6827 -- _Task_Id : Task_Id;
6828 -- entry_family : array (bounds) of Void;
6829 -- _Priority : Integer := priority_expression;
6830 -- _Size : Size_Type := Size_Type (size_expression);
6831 -- _Task_Info : Task_Info_Type := task_info_expression;
6832 -- _Task_Name : Task_Image_Type := new String'(task_name_expression);
6835 -- The discriminants are present only if the corresponding task type has
6836 -- discriminants, and they exactly mirror the task type discriminants.
6838 -- The Id field is always present. It contains the Task_Id value, as
6839 -- set by the call to Create_Task. Note that although the task is
6840 -- limited, the task value record type is not limited, so there is no
6841 -- problem in passing this field as an out parameter to Create_Task.
6843 -- One entry_family component is present for each entry family in the
6844 -- task definition. The bounds correspond to the bounds of the entry
6845 -- family (which may depend on discriminants). The element type is
6846 -- void, since we only need the bounds information for determining
6847 -- the entry index. Note that the use of an anonymous array would
6848 -- normally be illegal in this context, but this is a parser check,
6849 -- and the semantics is quite prepared to handle such a case.
6851 -- The _Size field is present only if a Storage_Size pragma appears in
6852 -- the task definition. The expression captures the argument that was
6853 -- present in the pragma, and is used to override the task stack size
6854 -- otherwise associated with the task type.
6856 -- The _Priority field is present only if a Priority or Interrupt_Priority
6857 -- pragma appears in the task definition. The expression captures the
6858 -- argument that was present in the pragma, and is used to provide
6859 -- the Size parameter to the call to Create_Task.
6861 -- The _Task_Info field is present only if a Task_Info pragma appears in
6862 -- the task definition. The expression captures the argument that was
6863 -- present in the pragma, and is used to provide the Task_Image parameter
6864 -- to the call to Create_Task.
6866 -- The _Task_Name field is present only if a Task_Name pragma appears in
6867 -- the task definition. The expression captures the argument that was
6868 -- present in the pragma, and is used to provide the Task_Id parameter
6869 -- to the call to Create_Task.
6871 -- When a task is declared, an instance of the task value record is
6872 -- created. The elaboration of this declaration creates the correct
6873 -- bounds for the entry families, and also evaluates the size, priority,
6874 -- and task_Info expressions if needed. The initialization routine for
6875 -- the task type itself then calls Create_Task with appropriate
6876 -- parameters to initialize the value of the Task_Id field.
6878 -- Note: the address of this record is passed as the "Discriminants"
6879 -- parameter for Create_Task. Since Create_Task merely passes this onto
6880 -- the body procedure, it does not matter that it does not quite match
6881 -- the GNARLI model of what is being passed (the record contains more
6882 -- than just the discriminants, but the discriminants can be found from
6883 -- the record value).
6885 -- The Entity_Id for this created record type is placed in the
6886 -- Corresponding_Record_Type field of the associated task type entity.
6888 -- Next we create a procedure specification for the task body procedure:
6890 -- procedure taskB (_Task : access taskV);
6892 -- Note that this must come after the record type declaration, since
6893 -- the spec refers to this type. It turns out that the initialization
6894 -- procedure for the value type references the task body spec, but that's
6895 -- fine, since it won't be generated till the freeze point for the type,
6896 -- which is certainly after the task body spec declaration.
6898 -- Finally, we set the task index value field of the entry attribute in
6899 -- the case of a simple entry.
6901 procedure Expand_N_Task_Type_Declaration (N : Node_Id) is
6902 Loc : constant Source_Ptr := Sloc (N);
6903 Tasktyp : constant Entity_Id := Etype (Defining_Identifier (N));
6904 Tasknm : constant Name_Id := Chars (Tasktyp);
6905 Taskdef : constant Node_Id := Task_Definition (N);
6907 Proc_Spec : Node_Id;
6909 Rec_Ent : Entity_Id;
6911 Elab_Decl : Node_Id;
6912 Size_Decl : Node_Id;
6913 Body_Decl : Node_Id;
6916 -- Do not attempt expansion if in no run time mode
6919 and then not Restricted_Profile
6921 Disallow_In_No_Run_Time_Mode (N);
6924 -- If already expanded, nothing to do
6926 elsif Present (Corresponding_Record_Type (Tasktyp)) then
6930 -- Here we will do the expansion
6932 Rec_Decl := Build_Corresponding_Record (N, Tasktyp, Loc);
6933 Rec_Ent := Defining_Identifier (Rec_Decl);
6934 Cdecls := Component_Items (Component_List
6935 (Type_Definition (Rec_Decl)));
6937 Qualify_Entity_Names (N);
6939 -- First create the elaboration variable
6942 Make_Object_Declaration (Loc,
6943 Defining_Identifier =>
6944 Make_Defining_Identifier (Sloc (Tasktyp),
6945 Chars => New_External_Name (Tasknm, 'E')),
6946 Aliased_Present => True,
6947 Object_Definition => New_Reference_To (Standard_Boolean, Loc),
6948 Expression => New_Reference_To (Standard_False, Loc));
6949 Insert_After (N, Elab_Decl);
6951 -- Next create the declaration of the size variable (tasknmZ)
6953 Set_Storage_Size_Variable (Tasktyp,
6954 Make_Defining_Identifier (Sloc (Tasktyp),
6955 Chars => New_External_Name (Tasknm, 'Z')));
6957 if Present (Taskdef) and then Has_Storage_Size_Pragma (Taskdef) and then
6958 Is_Static_Expression (Expression (First (
6959 Pragma_Argument_Associations (Find_Task_Or_Protected_Pragma (
6960 Taskdef, Name_Storage_Size)))))
6963 Make_Object_Declaration (Loc,
6964 Defining_Identifier => Storage_Size_Variable (Tasktyp),
6965 Object_Definition => New_Reference_To (RTE (RE_Size_Type), Loc),
6967 Convert_To (RTE (RE_Size_Type),
6970 Pragma_Argument_Associations (
6971 Find_Task_Or_Protected_Pragma
6972 (Taskdef, Name_Storage_Size)))))));
6976 Make_Object_Declaration (Loc,
6977 Defining_Identifier => Storage_Size_Variable (Tasktyp),
6978 Object_Definition => New_Reference_To (RTE (RE_Size_Type), Loc),
6979 Expression => New_Reference_To (RTE (RE_Unspecified_Size), Loc));
6982 Insert_After (Elab_Decl, Size_Decl);
6984 -- Next build the rest of the corresponding record declaration.
6985 -- This is done last, since the corresponding record initialization
6986 -- procedure will reference the previously created entities.
6988 -- Fill in the component declarations. First the _Task_Id field.
6991 Make_Component_Declaration (Loc,
6992 Defining_Identifier =>
6993 Make_Defining_Identifier (Loc, Name_uTask_Id),
6994 Subtype_Indication => New_Reference_To (RTE (RO_ST_Task_ID), Loc)));
6996 -- Add components for entry families
6998 Collect_Entry_Families (Loc, Cdecls, Size_Decl, Tasktyp);
7000 -- Add the _Priority component if a Priority pragma is present
7002 if Present (Taskdef) and then Has_Priority_Pragma (Taskdef) then
7004 Make_Component_Declaration (Loc,
7005 Defining_Identifier =>
7006 Make_Defining_Identifier (Loc, Name_uPriority),
7007 Subtype_Indication => New_Reference_To (Standard_Integer, Loc),
7008 Expression => New_Copy (
7010 Pragma_Argument_Associations (
7011 Find_Task_Or_Protected_Pragma
7012 (Taskdef, Name_Priority)))))));
7015 -- Add the _Task_Size component if a Storage_Size pragma is present
7017 if Present (Taskdef)
7018 and then Has_Storage_Size_Pragma (Taskdef)
7021 Make_Component_Declaration (Loc,
7022 Defining_Identifier =>
7023 Make_Defining_Identifier (Loc, Name_uSize),
7025 Subtype_Indication => New_Reference_To (RTE (RE_Size_Type), Loc),
7028 Convert_To (RTE (RE_Size_Type),
7031 Pragma_Argument_Associations (
7032 Find_Task_Or_Protected_Pragma
7033 (Taskdef, Name_Storage_Size))))))));
7036 -- Add the _Task_Info component if a Task_Info pragma is present
7038 if Present (Taskdef) and then Has_Task_Info_Pragma (Taskdef) then
7040 Make_Component_Declaration (Loc,
7041 Defining_Identifier =>
7042 Make_Defining_Identifier (Loc, Name_uTask_Info),
7043 Subtype_Indication =>
7044 New_Reference_To (RTE (RE_Task_Info_Type), Loc),
7045 Expression => New_Copy (
7047 Pragma_Argument_Associations (
7048 Find_Task_Or_Protected_Pragma
7049 (Taskdef, Name_Task_Info)))))));
7052 -- Add the _Task_Name component if a Task_Name pragma is present
7054 if Present (Taskdef) and then Has_Task_Name_Pragma (Taskdef) then
7056 Make_Component_Declaration (Loc,
7057 Defining_Identifier =>
7058 Make_Defining_Identifier (Loc, Name_uTask_Info),
7059 Subtype_Indication =>
7060 New_Reference_To (RTE (RE_Task_Image_Type), Loc),
7062 Make_Allocator (Loc,
7064 Make_Qualified_Expression (Loc,
7066 New_Occurrence_Of (Standard_String, Loc),
7070 Pragma_Argument_Associations (
7071 Find_Task_Or_Protected_Pragma
7072 (Taskdef, Name_Task_Name)))))))));
7075 Insert_After (Size_Decl, Rec_Decl);
7077 -- Analyze the record declaration immediately after construction,
7078 -- because the initialization procedure is needed for single task
7079 -- declarations before the next entity is analyzed.
7083 -- Create the declaration of the task body procedure
7085 Proc_Spec := Build_Task_Proc_Specification (Tasktyp);
7087 Make_Subprogram_Declaration (Loc,
7088 Specification => Proc_Spec);
7090 Insert_After (Rec_Decl, Body_Decl);
7092 -- Now we can freeze the corresponding record. This needs manually
7093 -- freezing, since it is really part of the task type, and the task
7094 -- type is frozen at this stage. We of course need the initialization
7095 -- procedure for this corresponding record type and we won't get it
7096 -- in time if we don't freeze now.
7099 L : constant List_Id := Freeze_Entity (Rec_Ent, Loc);
7102 if Is_Non_Empty_List (L) then
7103 Insert_List_After (Body_Decl, L);
7107 -- Complete the expansion of access types to the current task
7108 -- type, if any were declared.
7110 Expand_Previous_Access_Type (Tasktyp);
7111 end Expand_N_Task_Type_Declaration;
7113 -------------------------------
7114 -- Expand_N_Timed_Entry_Call --
7115 -------------------------------
7117 -- A timed entry call in normal case is not implemented using ATC
7118 -- mechanism anymore for efficiency reason.
7128 -- is expanded as follow:
7130 -- 1) When T.E is a task entry_call;
7134 -- X : Task_Entry_Index := <entry index>;
7135 -- DX : Duration := To_Duration (D);
7136 -- M : Delay_Mode := <discriminant>;
7137 -- P : parms := (parm, parm, parm);
7140 -- Timed_Protected_Entry_Call (<acceptor-task>, X, P'Address,
7149 -- 2) When T.E is a protected entry_call;
7153 -- X : Protected_Entry_Index := <entry index>;
7154 -- DX : Duration := To_Duration (D);
7155 -- M : Delay_Mode := <discriminant>;
7156 -- P : parms := (parm, parm, parm);
7159 -- Timed_Protected_Entry_Call (<object>'unchecked_access, X,
7160 -- P'Address, DX, M, B);
7168 procedure Expand_N_Timed_Entry_Call (N : Node_Id) is
7169 Loc : constant Source_Ptr := Sloc (N);
7172 Entry_Call_Statement (Entry_Call_Alternative (N));
7173 E_Stats : constant List_Id :=
7174 Statements (Entry_Call_Alternative (N));
7175 D_Stat : constant Node_Id :=
7176 Delay_Statement (Delay_Alternative (N));
7177 D_Stats : constant List_Id :=
7178 Statements (Delay_Alternative (N));
7201 -- The arguments in the call may require dynamic allocation, and the
7202 -- call statement may have been transformed into a block. The block
7203 -- may contain additional declarations for internal entities, and the
7204 -- original call is found by sequential search.
7206 if Nkind (E_Call) = N_Block_Statement then
7207 E_Call := First (Statements (Handled_Statement_Sequence (E_Call)));
7209 while Nkind (E_Call) /= N_Procedure_Call_Statement
7210 and then Nkind (E_Call) /= N_Entry_Call_Statement
7216 -- Build an entry call using Simple_Entry_Call. We will use this as the
7217 -- base for creating appropriate calls.
7219 Extract_Entry (E_Call, Concval, Ename, Index);
7220 Build_Simple_Entry_Call (E_Call, Concval, Ename, Index);
7222 Stmts := Statements (Handled_Statement_Sequence (E_Call));
7223 Decls := Declarations (E_Call);
7229 Dtyp := Base_Type (Etype (Expression (D_Stat)));
7231 -- Use the type of the delay expression (Calendar or Real_Time)
7232 -- to generate the appropriate conversion.
7234 if Nkind (D_Stat) = N_Delay_Relative_Statement then
7235 Disc := Make_Integer_Literal (Loc, 0);
7236 Conv := Relocate_Node (Expression (D_Stat));
7238 elsif Is_RTE (Dtyp, RO_CA_Time) then
7239 Disc := Make_Integer_Literal (Loc, 1);
7240 Conv := Make_Function_Call (Loc,
7241 New_Reference_To (RTE (RO_CA_To_Duration), Loc),
7242 New_List (New_Copy (Expression (D_Stat))));
7244 else pragma Assert (Is_RTE (Dtyp, RO_RT_Time));
7245 Disc := Make_Integer_Literal (Loc, 2);
7246 Conv := Make_Function_Call (Loc,
7247 New_Reference_To (RTE (RO_RT_To_Duration), Loc),
7248 New_List (New_Copy (Expression (D_Stat))));
7251 -- Create a Duration and a Delay_Mode object used for passing a delay
7254 D := Make_Defining_Identifier (Loc, New_Internal_Name ('D'));
7255 M := Make_Defining_Identifier (Loc, New_Internal_Name ('M'));
7258 Make_Object_Declaration (Loc,
7259 Defining_Identifier => D,
7260 Object_Definition => New_Reference_To (Standard_Duration, Loc)));
7263 Make_Object_Declaration (Loc,
7264 Defining_Identifier => M,
7265 Object_Definition => New_Reference_To (Standard_Integer, Loc),
7266 Expression => Disc));
7268 B := Make_Defining_Identifier (Loc, Name_uB);
7270 -- Create a boolean object used for a return parameter.
7273 Make_Object_Declaration (Loc,
7274 Defining_Identifier => B,
7275 Object_Definition => New_Reference_To (Standard_Boolean, Loc)));
7277 Stmt := First (Stmts);
7279 -- Skip assignments to temporaries created for in-out parameters.
7280 -- This makes unwarranted assumptions about the shape of the expanded
7281 -- tree for the call, and should be cleaned up ???
7283 while Nkind (Stmt) /= N_Procedure_Call_Statement loop
7287 -- Do the assignement at this stage only because the evaluation of the
7288 -- expression must not occur before (see ACVC C97302A).
7290 Insert_Before (Stmt,
7291 Make_Assignment_Statement (Loc,
7292 Name => New_Reference_To (D, Loc),
7293 Expression => Conv));
7297 Parms := Parameter_Associations (Call);
7299 -- For a protected type, we build a Timed_Protected_Entry_Call
7301 if Is_Protected_Type (Etype (Concval)) then
7303 -- Create a new call statement
7305 Parm := First (Parms);
7307 while Present (Parm)
7308 and then not Is_RTE (Etype (Parm), RE_Call_Modes)
7313 Dummy := Remove_Next (Next (Parm));
7315 -- In case some garbage is following the Cancel_Param, remove.
7317 Dummy := Next (Parm);
7319 -- Remove the mode of the Protected_Entry_Call call, the
7320 -- Communication_Block of the Protected_Entry_Call call, and add a
7321 -- Duration and a Delay_Mode parameter
7323 pragma Assert (Present (Parm));
7324 Rewrite (Parm, New_Reference_To (D, Loc));
7326 Rewrite (Dummy, New_Reference_To (M, Loc));
7328 -- Add a Boolean flag for successful entry call.
7330 Append_To (Parms, New_Reference_To (B, Loc));
7333 or else Restrictions (No_Entry_Queue) = False
7334 or else Number_Entries (Etype (Concval)) > 1
7337 Make_Procedure_Call_Statement (Loc,
7339 New_Reference_To (RTE (RE_Timed_Protected_Entry_Call), Loc),
7340 Parameter_Associations => Parms));
7343 Parm := First (Parms);
7345 while Present (Parm)
7346 and then not Is_RTE (Etype (Parm), RE_Protected_Entry_Index)
7354 Make_Procedure_Call_Statement (Loc,
7355 Name => New_Reference_To (
7356 RTE (RE_Timed_Protected_Single_Entry_Call), Loc),
7357 Parameter_Associations => Parms));
7360 -- For the task case, build a Timed_Task_Entry_Call
7363 -- Create a new call statement
7365 Append_To (Parms, New_Reference_To (D, Loc));
7366 Append_To (Parms, New_Reference_To (M, Loc));
7367 Append_To (Parms, New_Reference_To (B, Loc));
7370 Make_Procedure_Call_Statement (Loc,
7371 Name => New_Reference_To (RTE (RE_Timed_Task_Entry_Call), Loc),
7372 Parameter_Associations => Parms));
7377 Make_Implicit_If_Statement (N,
7378 Condition => New_Reference_To (B, Loc),
7379 Then_Statements => E_Stats,
7380 Else_Statements => D_Stats));
7383 Make_Block_Statement (Loc,
7384 Declarations => Decls,
7385 Handled_Statement_Sequence =>
7386 Make_Handled_Sequence_Of_Statements (Loc, Stmts)));
7390 end Expand_N_Timed_Entry_Call;
7392 ----------------------------------------
7393 -- Expand_Protected_Body_Declarations --
7394 ----------------------------------------
7396 -- Part of the expansion of a protected body involves the creation of
7397 -- a declaration that can be referenced from the statement sequences of
7398 -- the entry bodies:
7402 -- This declaration is inserted in the declarations of the service
7403 -- entries procedure for the protected body, and it is important that
7404 -- it be inserted before the statements of the entry body statement
7405 -- sequences are analyzed. Thus it would be too late to create this
7406 -- declaration in the Expand_N_Protected_Body routine, which is why
7407 -- there is a separate procedure to be called directly from Sem_Ch9.
7409 -- Ann is used to hold the address of the record containing the parameters
7410 -- (see Expand_N_Entry_Call for more details on how this record is built).
7411 -- References to the parameters do an unchecked conversion of this address
7412 -- to a pointer to the required record type, and then access the field that
7413 -- holds the value of the required parameter. The entity for the address
7414 -- variable is held as the top stack element (i.e. the last element) of the
7415 -- Accept_Address stack in the corresponding entry entity, and this element
7416 -- must be set in place before the statements are processed.
7418 -- No stack is needed for entry bodies, since they cannot be nested, but
7419 -- it is kept for consistency between protected and task entries. The
7420 -- stack will never contain more than one element. There is also only one
7421 -- such variable for a given protected body, but this is placed on the
7422 -- Accept_Address stack of all of the entries, again for consistency.
7424 -- To expand the requeue statement, a label is provided at the end of
7425 -- the loop in the entry service routine created by the expander (see
7426 -- Expand_N_Protected_Body for details), so that the statement can be
7427 -- skipped after the requeue is complete. This label is created during the
7428 -- expansion of the entry body, which will take place after the expansion
7429 -- of the requeue statements that it contains, so a placeholder defining
7430 -- identifier is associated with the task type here.
7432 -- Another label is provided following case statement created by the
7433 -- expander. This label is need for implementing return statement from
7434 -- entry body so that a return can be expanded as a goto to this label.
7435 -- This label is created during the expansion of the entry body, which
7436 -- will take place after the expansion of the return statements that it
7437 -- contains. Therefore, just like the label for expanding requeues, we
7438 -- need another placeholder for the label.
7440 procedure Expand_Protected_Body_Declarations
7442 Spec_Id : Entity_Id)
7447 if Expander_Active then
7449 -- Associate privals with the first subprogram or entry
7450 -- body to be expanded. These are used to expand references
7451 -- to private data objects.
7453 Op := First_Protected_Operation (Declarations (N));
7455 if Present (Op) then
7456 Set_Discriminals (Parent (Spec_Id));
7457 Set_Privals (Parent (Spec_Id), Op, Sloc (N));
7460 end Expand_Protected_Body_Declarations;
7462 -------------------------
7463 -- External_Subprogram --
7464 -------------------------
7466 function External_Subprogram (E : Entity_Id) return Entity_Id is
7467 Subp : constant Entity_Id := Protected_Body_Subprogram (E);
7468 Decl : constant Node_Id := Unit_Declaration_Node (E);
7471 -- If the protected operation is defined in the visible part of the
7472 -- protected type, or if it is an interrupt handler, the internal and
7473 -- external subprograms follow each other on the entity chain. If the
7474 -- operation is defined in the private part of the type, there is no
7475 -- need for a separate locking version of the operation, and internal
7476 -- calls use the protected_body_subprogram directly.
7478 if List_Containing (Decl) = Visible_Declarations (Parent (Decl))
7479 or else Is_Interrupt_Handler (E)
7481 return Next_Entity (Subp);
7485 end External_Subprogram;
7491 procedure Extract_Entry
7493 Concval : out Node_Id;
7494 Ename : out Node_Id;
7495 Index : out Node_Id)
7497 Nam : constant Node_Id := Name (N);
7500 -- For a simple entry, the name is a selected component, with the
7501 -- prefix being the task value, and the selector being the entry.
7503 if Nkind (Nam) = N_Selected_Component then
7504 Concval := Prefix (Nam);
7505 Ename := Selector_Name (Nam);
7508 -- For a member of an entry family, the name is an indexed
7509 -- component where the prefix is a selected component,
7510 -- whose prefix in turn is the task value, and whose
7511 -- selector is the entry family. The single expression in
7512 -- the expressions list of the indexed component is the
7513 -- subscript for the family.
7516 pragma Assert (Nkind (Nam) = N_Indexed_Component);
7517 Concval := Prefix (Prefix (Nam));
7518 Ename := Selector_Name (Prefix (Nam));
7519 Index := First (Expressions (Nam));
7528 function Family_Offset
7535 function Convert_Discriminant_Ref (Bound : Node_Id) return Node_Id;
7536 -- If one of the bounds is a reference to a discriminant, replace
7537 -- with corresponding discriminal of type. Within the body of a task
7538 -- retrieve the renamed discriminant by simple visibility, using its
7539 -- generated name. Within a protected object, find the original dis-
7540 -- criminant and replace it with the discriminal of the current prot-
7543 ------------------------------
7544 -- Convert_Discriminant_Ref --
7545 ------------------------------
7547 function Convert_Discriminant_Ref (Bound : Node_Id) return Node_Id is
7548 Loc : constant Source_Ptr := Sloc (Bound);
7553 if Is_Entity_Name (Bound)
7554 and then Ekind (Entity (Bound)) = E_Discriminant
7556 if Is_Task_Type (Ttyp)
7557 and then Has_Completion (Ttyp)
7559 B := Make_Identifier (Loc, Chars (Entity (Bound)));
7560 Find_Direct_Name (B);
7562 elsif Is_Protected_Type (Ttyp) then
7563 D := First_Discriminant (Ttyp);
7565 while Chars (D) /= Chars (Entity (Bound)) loop
7566 Next_Discriminant (D);
7569 B := New_Reference_To (Discriminal (D), Loc);
7572 B := New_Reference_To (Discriminal (Entity (Bound)), Loc);
7575 elsif Nkind (Bound) = N_Attribute_Reference then
7579 B := New_Copy_Tree (Bound);
7583 Make_Attribute_Reference (Loc,
7584 Attribute_Name => Name_Pos,
7585 Prefix => New_Occurrence_Of (Etype (Bound), Loc),
7586 Expressions => New_List (B));
7587 end Convert_Discriminant_Ref;
7589 -- Start of processing for Family_Offset
7593 Make_Op_Subtract (Loc,
7594 Left_Opnd => Convert_Discriminant_Ref (Hi),
7595 Right_Opnd => Convert_Discriminant_Ref (Lo));
7603 function Family_Size
7613 if Is_Task_Type (Ttyp) then
7614 Ityp := RTE (RE_Task_Entry_Index);
7616 Ityp := RTE (RE_Protected_Entry_Index);
7620 Make_Attribute_Reference (Loc,
7621 Prefix => New_Reference_To (Ityp, Loc),
7622 Attribute_Name => Name_Max,
7623 Expressions => New_List (
7626 Family_Offset (Loc, Hi, Lo, Ttyp),
7628 Make_Integer_Literal (Loc, 1)),
7629 Make_Integer_Literal (Loc, 0)));
7632 -----------------------------------
7633 -- Find_Task_Or_Protected_Pragma --
7634 -----------------------------------
7636 function Find_Task_Or_Protected_Pragma
7644 N := First (Visible_Declarations (T));
7646 while Present (N) loop
7647 if Nkind (N) = N_Pragma then
7648 if Chars (N) = P then
7651 elsif P = Name_Priority
7652 and then Chars (N) = Name_Interrupt_Priority
7665 N := First (Private_Declarations (T));
7667 while Present (N) loop
7668 if Nkind (N) = N_Pragma then
7669 if Chars (N) = P then
7672 elsif P = Name_Priority
7673 and then Chars (N) = Name_Interrupt_Priority
7686 raise Program_Error;
7687 end Find_Task_Or_Protected_Pragma;
7689 -------------------------------
7690 -- First_Protected_Operation --
7691 -------------------------------
7693 function First_Protected_Operation (D : List_Id) return Node_Id is
7697 First_Op := First (D);
7698 while Present (First_Op)
7699 and then Nkind (First_Op) /= N_Subprogram_Body
7700 and then Nkind (First_Op) /= N_Entry_Body
7706 end First_Protected_Operation;
7708 --------------------------------
7709 -- Index_Constant_Declaration --
7710 --------------------------------
7712 function Index_Constant_Declaration
7714 Index_Id : Entity_Id;
7718 Loc : constant Source_Ptr := Sloc (N);
7719 Decls : List_Id := New_List;
7720 Index_Con : constant Entity_Id := Entry_Index_Constant (Index_Id);
7721 Index_Typ : Entity_Id;
7723 Hi : Node_Id := Type_High_Bound (Etype (Index_Id));
7724 Lo : Node_Id := Type_Low_Bound (Etype (Index_Id));
7726 function Replace_Discriminant (Bound : Node_Id) return Node_Id;
7727 -- The bounds of the entry index may depend on discriminants, so
7728 -- each declaration of an entry_index_constant must have its own
7729 -- subtype declaration, using the local renaming of the object discri-
7732 --------------------------
7733 -- Replace_Discriminant --
7734 --------------------------
7736 function Replace_Discriminant (Bound : Node_Id) return Node_Id is
7738 if Nkind (Bound) = N_Identifier
7739 and then Ekind (Entity (Bound)) = E_Constant
7740 and then Present (Discriminal_Link (Entity (Bound)))
7742 return Make_Identifier (Loc, Chars (Entity (Bound)));
7744 return Duplicate_Subexpr (Bound);
7746 end Replace_Discriminant;
7748 -- Start of processing for Index_Constant_Declaration
7751 Set_Discriminal_Link (Index_Con, Index_Id);
7754 Original_Node (Discrete_Subtype_Definition (Parent (Index_Id))))
7756 -- Simple case: entry family is given by a subtype mark, and index
7757 -- constant has the same type, no replacement needed.
7759 Index_Typ := Etype (Index_Id);
7762 Hi := Replace_Discriminant (Hi);
7763 Lo := Replace_Discriminant (Lo);
7765 Index_Typ := Make_Defining_Identifier (Loc, New_Internal_Name ('I'));
7768 Make_Subtype_Declaration (Loc,
7769 Defining_Identifier => Index_Typ,
7770 Subtype_Indication =>
7771 Make_Subtype_Indication (Loc,
7773 New_Occurrence_Of (Base_Type (Etype (Index_Id)), Loc),
7775 Make_Range_Constraint (Loc,
7776 Range_Expression => Make_Range (Loc, Lo, Hi)))),
7782 Make_Object_Declaration (Loc,
7783 Defining_Identifier => Index_Con,
7784 Constant_Present => True,
7785 Object_Definition => New_Occurrence_Of (Index_Typ, Loc),
7788 Make_Attribute_Reference (Loc,
7789 Prefix => New_Reference_To (Index_Typ, Loc),
7790 Attribute_Name => Name_Val,
7792 Expressions => New_List (
7796 Make_Op_Subtract (Loc,
7797 Left_Opnd => Make_Identifier (Loc, Name_uE),
7799 Entry_Index_Expression (Loc,
7800 Defining_Identifier (N), Empty, Prot)),
7803 Make_Attribute_Reference (Loc,
7804 Prefix => New_Reference_To (Index_Typ, Loc),
7805 Attribute_Name => Name_Pos,
7806 Expressions => New_List (
7807 Make_Attribute_Reference (Loc,
7808 Prefix => New_Reference_To (Index_Typ, Loc),
7809 Attribute_Name => Name_First))))))),
7813 end Index_Constant_Declaration;
7815 --------------------------------
7816 -- Make_Initialize_Protection --
7817 --------------------------------
7819 function Make_Initialize_Protection
7820 (Protect_Rec : Entity_Id)
7823 Loc : constant Source_Ptr := Sloc (Protect_Rec);
7830 L : List_Id := New_List;
7833 -- We may need two calls to properly initialize the object, one
7834 -- to Initialize_Protection, and possibly one to Install_Handlers
7835 -- if we have a pragma Attach_Handler.
7837 Ptyp := Corresponding_Concurrent_Type (Protect_Rec);
7838 Pnam := Chars (Ptyp);
7840 -- Get protected declaration. In the case of a task type declaration,
7841 -- this is simply the parent of the protected type entity.
7842 -- In the single protected object
7843 -- declaration, this parent will be the implicit type, and we can find
7844 -- the corresponding single protected object declaration by
7845 -- searching forward in the declaration list in the tree.
7846 -- ??? I am not sure that the test for N_Single_Protected_Declaration
7847 -- is needed here. Nodes of this type should have been removed
7848 -- during semantic analysis.
7850 Pdec := Parent (Ptyp);
7852 while Nkind (Pdec) /= N_Protected_Type_Declaration
7853 and then Nkind (Pdec) /= N_Single_Protected_Declaration
7858 -- Now we can find the object definition from this declaration
7860 Pdef := Protected_Definition (Pdec);
7862 -- Build the parameter list for the call. Note that _Init is the name
7863 -- of the formal for the object to be initialized, which is the task
7864 -- value record itself.
7868 -- Object parameter. This is a pointer to the object of type
7869 -- Protection used by the GNARL to control the protected object.
7872 Make_Attribute_Reference (Loc,
7874 Make_Selected_Component (Loc,
7875 Prefix => Make_Identifier (Loc, Name_uInit),
7876 Selector_Name => Make_Identifier (Loc, Name_uObject)),
7877 Attribute_Name => Name_Unchecked_Access));
7879 -- Priority parameter. Set to Unspecified_Priority unless there is a
7880 -- priority pragma, in which case we take the value from the pragma,
7881 -- or there is an interrupt pragma and no priority pragma, and we
7882 -- set the ceiling to Interrupt_Priority'Last, an implementation-
7883 -- defined value, see D.3(10).
7886 and then Has_Priority_Pragma (Pdef)
7889 Duplicate_Subexpr (Expression (First (Pragma_Argument_Associations
7890 (Find_Task_Or_Protected_Pragma (Pdef, Name_Priority))))));
7892 elsif Has_Interrupt_Handler (Ptyp)
7893 or else Has_Attach_Handler (Ptyp)
7895 -- When no priority is specified but an xx_Handler pragma is,
7896 -- we default to System.Interrupts.Default_Interrupt_Priority,
7900 New_Reference_To (RTE (RE_Default_Interrupt_Priority), Loc));
7904 New_Reference_To (RTE (RE_Unspecified_Priority), Loc));
7907 if Has_Entries (Ptyp)
7908 or else Has_Interrupt_Handler (Ptyp)
7909 or else Has_Attach_Handler (Ptyp)
7911 -- Compiler_Info parameter. This parameter allows entry body
7912 -- procedures and barrier functions to be called from the runtime.
7913 -- It is a pointer to the record generated by the compiler to
7914 -- represent the protected object.
7917 Make_Attribute_Reference (Loc,
7918 Prefix => Make_Identifier (Loc, Name_uInit),
7919 Attribute_Name => Name_Address));
7921 if Has_Entries (Ptyp) then
7922 -- Entry_Bodies parameter. This is a pointer to an array of
7923 -- pointers to the entry body procedures and barrier functions
7924 -- of the object. If the protected type has no entries this
7925 -- object will not exist; in this case, pass a null.
7927 P_Arr := Entry_Bodies_Array (Ptyp);
7930 Make_Attribute_Reference (Loc,
7931 Prefix => New_Reference_To (P_Arr, Loc),
7932 Attribute_Name => Name_Unrestricted_Access));
7935 or else Restrictions (No_Entry_Queue) = False
7936 or else Number_Entries (Ptyp) > 1
7938 -- Find index mapping function (clumsy but ok for now).
7940 while Ekind (P_Arr) /= E_Function loop
7941 Next_Entity (P_Arr);
7945 Make_Attribute_Reference (Loc,
7947 New_Reference_To (P_Arr, Loc),
7948 Attribute_Name => Name_Unrestricted_Access));
7952 Append_To (Args, Make_Null (Loc));
7953 Append_To (Args, Make_Null (Loc));
7957 or else Restrictions (No_Entry_Queue) = False
7958 or else Number_Entries (Ptyp) > 1
7961 Make_Procedure_Call_Statement (Loc,
7962 Name => New_Reference_To (
7963 RTE (RE_Initialize_Protection_Entries), Loc),
7964 Parameter_Associations => Args));
7968 Make_Procedure_Call_Statement (Loc,
7969 Name => New_Reference_To (
7970 RTE (RE_Initialize_Protection_Entry), Loc),
7971 Parameter_Associations => Args));
7976 Make_Procedure_Call_Statement (Loc,
7977 Name => New_Reference_To (RTE (RE_Initialize_Protection), Loc),
7978 Parameter_Associations => Args));
7981 if Has_Attach_Handler (Ptyp) then
7983 -- We have a list of N Attach_Handler (ProcI, ExprI),
7984 -- and we have to make the following call:
7985 -- Install_Handlers (_object,
7986 -- ((Expr1, Proc1'access), ...., (ExprN, ProcN'access));
7989 Args : List_Id := New_List;
7990 Table : List_Id := New_List;
7991 Ritem : Node_Id := First_Rep_Item (Ptyp);
7994 -- Appends the _object argument
7997 Make_Attribute_Reference (Loc,
7999 Make_Selected_Component (Loc,
8000 Prefix => Make_Identifier (Loc, Name_uInit),
8001 Selector_Name => Make_Identifier (Loc, Name_uObject)),
8002 Attribute_Name => Name_Unchecked_Access));
8004 -- Build the Attach_Handler table argument
8006 while Present (Ritem) loop
8007 if Nkind (Ritem) = N_Pragma
8008 and then Chars (Ritem) = Name_Attach_Handler
8011 Handler : Node_Id :=
8012 First (Pragma_Argument_Associations (Ritem));
8013 Interrupt : Node_Id :=
8018 Make_Aggregate (Loc, Expressions => New_List (
8019 Duplicate_Subexpr (Expression (Interrupt)),
8020 Make_Attribute_Reference (Loc,
8021 Prefix => Make_Selected_Component (Loc,
8022 Make_Identifier (Loc, Name_uInit),
8023 Duplicate_Subexpr (Expression (Handler))),
8024 Attribute_Name => Name_Access))));
8028 Next_Rep_Item (Ritem);
8031 -- Appends the table argument we just built.
8032 Append_To (Args, Make_Aggregate (Loc, Table));
8034 -- Appends the Install_Handler call to the statements.
8036 Make_Procedure_Call_Statement (Loc,
8037 Name => New_Reference_To (RTE (RE_Install_Handlers), Loc),
8038 Parameter_Associations => Args));
8043 end Make_Initialize_Protection;
8045 ---------------------------
8046 -- Make_Task_Create_Call --
8047 ---------------------------
8049 function Make_Task_Create_Call (Task_Rec : Entity_Id) return Node_Id is
8050 Loc : constant Source_Ptr := Sloc (Task_Rec);
8060 Ttyp := Corresponding_Concurrent_Type (Task_Rec);
8061 Tnam := Chars (Ttyp);
8063 -- Get task declaration. In the case of a task type declaration, this
8064 -- is simply the parent of the task type entity. In the single task
8065 -- declaration, this parent will be the implicit type, and we can find
8066 -- the corresponding single task declaration by searching forward in
8067 -- the declaration list in the tree.
8068 -- ??? I am not sure that the test for N_Single_Task_Declaration
8069 -- is needed here. Nodes of this type should have been removed
8070 -- during semantic analysis.
8072 Tdec := Parent (Ttyp);
8074 while Nkind (Tdec) /= N_Task_Type_Declaration
8075 and then Nkind (Tdec) /= N_Single_Task_Declaration
8080 -- Now we can find the task definition from this declaration
8082 Tdef := Task_Definition (Tdec);
8084 -- Build the parameter list for the call. Note that _Init is the name
8085 -- of the formal for the object to be initialized, which is the task
8086 -- value record itself.
8090 -- Priority parameter. Set to Unspecified_Priority unless there is a
8091 -- priority pragma, in which case we take the value from the pragma.
8094 and then Has_Priority_Pragma (Tdef)
8097 Make_Selected_Component (Loc,
8098 Prefix => Make_Identifier (Loc, Name_uInit),
8099 Selector_Name => Make_Identifier (Loc, Name_uPriority)));
8103 New_Reference_To (RTE (RE_Unspecified_Priority), Loc));
8106 -- Size parameter. If no Storage_Size pragma is present, then
8107 -- the size is taken from the taskZ variable for the type, which
8108 -- is either Unspecified_Size, or has been reset by the use of
8109 -- a Storage_Size attribute definition clause. If a pragma is
8110 -- present, then the size is taken from the _Size field of the
8111 -- task value record, which was set from the pragma value.
8114 and then Has_Storage_Size_Pragma (Tdef)
8117 Make_Selected_Component (Loc,
8118 Prefix => Make_Identifier (Loc, Name_uInit),
8119 Selector_Name => Make_Identifier (Loc, Name_uSize)));
8123 New_Reference_To (Storage_Size_Variable (Ttyp), Loc));
8126 -- Task_Info parameter. Set to Unspecified_Task_Info unless there is a
8127 -- Task_Info pragma, in which case we take the value from the pragma.
8130 and then Has_Task_Info_Pragma (Tdef)
8133 Make_Selected_Component (Loc,
8134 Prefix => Make_Identifier (Loc, Name_uInit),
8135 Selector_Name => Make_Identifier (Loc, Name_uTask_Info)));
8139 New_Reference_To (RTE (RE_Unspecified_Task_Info), Loc));
8142 if not Restricted_Profile then
8144 -- Number of entries. This is an expression of the form:
8146 -- n + _Init.a'Length + _Init.a'B'Length + ...
8148 -- where a,b... are the entry family names for the task definition
8150 Ecount := Build_Entry_Count_Expression (
8152 Component_Items (Component_List (
8153 Type_Definition (Parent (
8154 Corresponding_Record_Type (Ttyp))))),
8156 Append_To (Args, Ecount);
8158 -- Master parameter. This is a reference to the _Master parameter of
8159 -- the initialization procedure, except in the case of the pragma
8160 -- Restrictions (No_Task_Hierarchy) where the value is fixed to 3.
8161 -- See comments in System.Tasking.Initialization.Init_RTS for the
8164 if Restrictions (No_Task_Hierarchy) = False then
8165 Append_To (Args, Make_Identifier (Loc, Name_uMaster));
8167 Append_To (Args, Make_Integer_Literal (Loc, 3));
8171 -- State parameter. This is a pointer to the task body procedure. The
8172 -- required value is obtained by taking the address of the task body
8173 -- procedure and converting it (with an unchecked conversion) to the
8174 -- type required by the task kernel. For further details, see the
8175 -- description of Expand_Task_Body
8178 Unchecked_Convert_To (RTE (RE_Task_Procedure_Access),
8179 Make_Attribute_Reference (Loc,
8181 New_Occurrence_Of (Get_Task_Body_Procedure (Ttyp), Loc),
8182 Attribute_Name => Name_Address)));
8184 -- Discriminants parameter. This is just the address of the task
8185 -- value record itself (which contains the discriminant values
8188 Make_Attribute_Reference (Loc,
8189 Prefix => Make_Identifier (Loc, Name_uInit),
8190 Attribute_Name => Name_Address));
8192 -- Elaborated parameter. This is an access to the elaboration Boolean
8195 Make_Attribute_Reference (Loc,
8196 Prefix => Make_Identifier (Loc, New_External_Name (Tnam, 'E')),
8197 Attribute_Name => Name_Unchecked_Access));
8199 -- Chain parameter. This is a reference to the _Chain parameter of
8200 -- the initialization procedure.
8202 Append_To (Args, Make_Identifier (Loc, Name_uChain));
8204 -- Task name parameter. Take this from the _Task_Info parameter to the
8205 -- init call unless there is a Task_Name pragma, in which case we take
8206 -- the value from the pragma.
8209 and then Has_Task_Name_Pragma (Tdef)
8212 Make_Selected_Component (Loc,
8213 Prefix => Make_Identifier (Loc, Name_uInit),
8214 Selector_Name => Make_Identifier (Loc, Name_uTask_Info)));
8217 Append_To (Args, Make_Identifier (Loc, Name_uTask_Id));
8220 -- Created_Task parameter. This is the _Task_Id field of the task
8224 Make_Selected_Component (Loc,
8225 Prefix => Make_Identifier (Loc, Name_uInit),
8226 Selector_Name => Make_Identifier (Loc, Name_uTask_Id)));
8228 if Restricted_Profile then
8229 Name := New_Reference_To (RTE (RE_Create_Restricted_Task), Loc);
8231 Name := New_Reference_To (RTE (RE_Create_Task), Loc);
8234 return Make_Procedure_Call_Statement (Loc,
8235 Name => Name, Parameter_Associations => Args);
8236 end Make_Task_Create_Call;
8238 ------------------------------
8239 -- Next_Protected_Operation --
8240 ------------------------------
8242 function Next_Protected_Operation (N : Node_Id) return Node_Id is
8246 Next_Op := Next (N);
8248 while Present (Next_Op)
8249 and then Nkind (Next_Op) /= N_Subprogram_Body
8250 and then Nkind (Next_Op) /= N_Entry_Body
8256 end Next_Protected_Operation;
8258 ----------------------
8259 -- Set_Discriminals --
8260 ----------------------
8262 procedure Set_Discriminals (Dec : Node_Id) is
8265 D_Minal : Entity_Id;
8268 pragma Assert (Nkind (Dec) = N_Protected_Type_Declaration);
8269 Pdef := Defining_Identifier (Dec);
8271 if Has_Discriminants (Pdef) then
8272 D := First_Discriminant (Pdef);
8274 while Present (D) loop
8276 Make_Defining_Identifier (Sloc (D),
8277 Chars => New_External_Name (Chars (D), 'D'));
8279 Set_Ekind (D_Minal, E_Constant);
8280 Set_Etype (D_Minal, Etype (D));
8281 Set_Discriminal (D, D_Minal);
8282 Set_Discriminal_Link (D_Minal, D);
8284 Next_Discriminant (D);
8287 end Set_Discriminals;
8293 procedure Set_Privals
8302 Body_Ent : Entity_Id;
8303 Prec_Decl : constant Node_Id :=
8304 Parent (Corresponding_Record_Type
8305 (Defining_Identifier (Dec)));
8306 Prec_Def : constant Entity_Id := Type_Definition (Prec_Decl);
8308 P_Subtype : Entity_Id;
8309 New_Decl : Entity_Id;
8310 Assoc_L : Elist_Id := New_Elmt_List;
8314 pragma Assert (Nkind (Dec) = N_Protected_Type_Declaration);
8316 (Nkind (Op) = N_Subprogram_Body or else Nkind (Op) = N_Entry_Body);
8318 Def := Protected_Definition (Dec);
8320 if Present (Private_Declarations (Def)) then
8322 P_Decl := First (Private_Declarations (Def));
8324 while Present (P_Decl) loop
8325 if Nkind (P_Decl) = N_Component_Declaration then
8326 P_Id := Defining_Identifier (P_Decl);
8328 Make_Defining_Identifier (Loc,
8329 New_External_Name (Chars (P_Id), 'P'));
8331 Set_Ekind (Priv, E_Variable);
8332 Set_Etype (Priv, Etype (P_Id));
8333 Set_Scope (Priv, Scope (P_Id));
8334 Set_Esize (Priv, Esize (Etype (P_Id)));
8335 Set_Alignment (Priv, Alignment (Etype (P_Id)));
8337 -- If the type of the component is an itype, we must
8338 -- create a new itype for the corresponding prival in
8339 -- each protected operation, to avoid scoping problems.
8340 -- We create new itypes by copying the tree for the
8341 -- component definition.
8343 if Is_Itype (Etype (P_Id)) then
8344 Append_Elmt (P_Id, Assoc_L);
8345 Append_Elmt (Priv, Assoc_L);
8347 if Nkind (Op) = N_Entry_Body then
8348 Op_Id := Defining_Identifier (Op);
8350 Op_Id := Defining_Unit_Name (Specification (Op));
8353 New_Decl := New_Copy_Tree (P_Decl, Assoc_L,
8354 New_Scope => Op_Id);
8357 Set_Protected_Operation (P_Id, Op);
8358 Set_Prival (P_Id, Priv);
8365 -- There is one more implicit private declaration: the object
8366 -- itself. A "prival" for this is attached to the protected
8367 -- body defining identifier.
8369 Body_Ent := Corresponding_Body (Dec);
8372 Make_Defining_Identifier (Sloc (Body_Ent),
8373 Chars => New_External_Name (Chars (Body_Ent), 'R'));
8375 -- Set the Etype to the implicit subtype of Protection created when
8376 -- the protected type declaration was expanded. This node will not
8377 -- be analyzed until it is used as the defining identifier for the
8378 -- renaming declaration in the protected operation body, and it will
8379 -- be needed in the references expanded before that body is expanded.
8380 -- Since the Protection field is aliased, set Is_Aliased as well.
8382 Obj_Decl := First (Component_Items (Component_List (Prec_Def)));
8383 while Chars (Defining_Identifier (Obj_Decl)) /= Name_uObject loop
8387 P_Subtype := Etype (Defining_Identifier (Obj_Decl));
8388 Set_Etype (Priv, P_Subtype);
8389 Set_Is_Aliased (Priv);
8390 Set_Object_Ref (Body_Ent, Priv);
8394 ----------------------------
8395 -- Update_Prival_Subtypes --
8396 ----------------------------
8398 procedure Update_Prival_Subtypes (N : Node_Id) is
8400 function Process (N : Node_Id) return Traverse_Result;
8401 -- Update the etype of occurrences of privals whose etype does not
8402 -- match the current Etype of the prival entity itself.
8404 procedure Update_Array_Bounds (E : Entity_Id);
8405 -- Itypes generated for array expressions may depend on the
8406 -- determinants of the protected object, and need to be processed
8407 -- separately because they are not attached to the tree.
8413 function Process (N : Node_Id) return Traverse_Result is
8415 if Is_Entity_Name (N) then
8417 E : Entity_Id := Entity (N);
8421 and then (Ekind (E) = E_Constant
8422 or else Ekind (E) = E_Variable)
8423 and then Nkind (Parent (E)) = N_Object_Renaming_Declaration
8424 and then not Is_Scalar_Type (Etype (E))
8425 and then Etype (N) /= Etype (E)
8427 Set_Etype (N, Etype (Entity (Original_Node (N))));
8429 -- If the prefix has an actual subtype that is different
8430 -- from the nominal one, update the types of the indices,
8431 -- so that the proper constraints are applied. Do not
8432 -- apply this transformation to a packed array, where the
8433 -- index type is computed for a byte array and is different
8434 -- from the source index.
8436 if Nkind (Parent (N)) = N_Indexed_Component
8438 not Is_Bit_Packed_Array (Etype (Prefix (Parent (N))))
8445 Indx1 := First (Expressions (Parent (N)));
8446 I_Typ := First_Index (Etype (N));
8448 while Present (Indx1) and then Present (I_Typ) loop
8450 if not Is_Entity_Name (Indx1) then
8451 Set_Etype (Indx1, Base_Type (Etype (I_Typ)));
8461 and then Ekind (E) = E_Constant
8462 and then Present (Discriminal_Link (E))
8464 Set_Etype (N, Etype (E));
8470 elsif Nkind (N) = N_Defining_Identifier
8471 or else Nkind (N) = N_Defining_Operator_Symbol
8472 or else Nkind (N) = N_Defining_Character_Literal
8476 elsif Nkind (N) = N_String_Literal then
8477 -- array type, but bounds are constant.
8480 elsif Nkind (N) = N_Object_Declaration
8481 and then Is_Itype (Etype (Defining_Identifier (N)))
8482 and then Is_Array_Type (Etype (Defining_Identifier (N)))
8484 Update_Array_Bounds (Etype (Defining_Identifier (N)));
8487 -- For array components of discriminated records, use the
8488 -- base type directly, because it may depend indirectly
8489 -- on the discriminants of the protected type. Cleaner would
8490 -- be a systematic mechanism to compute actual subtypes of
8491 -- private components ???
8493 elsif Nkind (N) in N_Has_Etype
8494 and then Present (Etype (N))
8495 and then Is_Array_Type (Etype (N))
8496 and then Nkind (N) = N_Selected_Component
8497 and then Has_Discriminants (Etype (Prefix (N)))
8499 Set_Etype (N, Base_Type (Etype (N)));
8503 if Nkind (N) in N_Has_Etype
8504 and then Present (Etype (N))
8505 and then Is_Itype (Etype (N)) then
8507 if Is_Array_Type (Etype (N)) then
8508 Update_Array_Bounds (Etype (N));
8510 elsif Is_Scalar_Type (Etype (N)) then
8511 Update_Prival_Subtypes (Type_Low_Bound (Etype (N)));
8512 Update_Prival_Subtypes (Type_High_Bound (Etype (N)));
8520 -------------------------
8521 -- Update_Array_Bounds --
8522 -------------------------
8524 procedure Update_Array_Bounds (E : Entity_Id) is
8528 Ind := First_Index (E);
8530 while Present (Ind) loop
8531 Update_Prival_Subtypes (Type_Low_Bound (Etype (Ind)));
8532 Update_Prival_Subtypes (Type_High_Bound (Etype (Ind)));
8535 end Update_Array_Bounds;
8537 procedure Traverse is new Traverse_Proc;
8539 -- Start of processing for Update_Prival_Subtypes
8543 end Update_Prival_Subtypes;