-- --
-- B o d y --
-- --
--- Copyright (C) 1992-2010, Free Software Foundation, Inc. --
+-- Copyright (C) 1992-2011, Free Software Foundation, Inc. --
-- --
-- GNAT is free software; you can redistribute it and/or modify it under --
-- terms of the GNU General Public License as published by the Free Soft- --
with Elists; use Elists;
with Errout; use Errout;
with Exp_Ch3; use Exp_Ch3;
-with Exp_Ch11; use Exp_Ch11;
with Exp_Ch6; use Exp_Ch6;
+with Exp_Ch11; use Exp_Ch11;
with Exp_Dbug; use Exp_Dbug;
with Exp_Disp; use Exp_Disp;
with Exp_Sel; use Exp_Sel;
-- types with defaulted discriminant of an integer type, when the bound
-- of some entry family depends on a discriminant. The limitation to
-- entry families of 128K should be reasonable in all cases, and is a
- -- documented implementation restriction. It will be lifted when protected
- -- entry families are re-implemented as a single ordered queue.
+ -- documented implementation restriction.
Entry_Family_Bound : constant Int := 2**16;
-- <formalN> : AnnN;
-- end record;
+ procedure Build_PPC_Wrapper (E : Entity_Id; Decl : Node_Id);
+ -- Build body of wrapper procedure for an entry or entry family that has
+ -- pre/postconditions. The body gathers the PPC's and expands them in the
+ -- usual way, and performs the entry call itself. This way preconditions
+ -- are evaluated before the call is queued. E is the entry in question,
+ -- and Decl is the enclosing synchronized type declaration at whose
+ -- freeze point the generated body is analyzed.
+
+ function Build_Renamed_Formal_Declaration
+ (New_F : Entity_Id;
+ Formal : Entity_Id;
+ Comp : Entity_Id;
+ Renamed_Formal : Node_Id) return Node_Id;
+ -- Create a renaming declaration for a formal, within a protected entry
+ -- body or an accept body. The renamed object is a component of the
+ -- parameter block that is a parameter in the entry call.
+
+ -- In Ada 2012, if the formal is an incomplete tagged type, the renaming
+ -- does not dereference the corresponding component to prevent an illegal
+ -- use of the incomplete type (AI05-0151).
+
procedure Build_Wrapper_Bodies
(Loc : Source_Ptr;
Typ : Entity_Id;
Lo : Node_Id;
Ttyp : Entity_Id;
Cap : Boolean) return Node_Id;
- -- Compute (Hi - Lo) for two entry family indices. Hi is the index in
+ -- Compute (Hi - Lo) for two entry family indexes. Hi is the index in
-- an accept statement, or the upper bound in the discrete subtype of
-- an entry declaration. Lo is the corresponding lower bound. Ttyp is
-- the concurrent type of the entry. If Cap is true, the result is
-- to handle properly the case of bounds that depend on discriminants.
-- If Cap is true, the result is capped according to Entry_Family_Bound.
+ procedure Find_Enclosing_Context
+ (N : Node_Id;
+ Context : out Node_Id;
+ Context_Id : out Entity_Id;
+ Context_Decls : out List_Id);
+ -- Subsidiary routine to procedures Build_Activation_Chain_Entity and
+ -- Build_Master_Entity. Given an arbitrary node in the tree, find the
+ -- nearest enclosing body, block, package or return statement and return
+ -- its constituents. Context is the enclosing construct, Context_Id is
+ -- the scope of Context_Id and Context_Decls is the declarative list of
+ -- Context.
+
procedure Extract_Dispatching_Call
(N : Node_Id;
Call_Ent : out Entity_Id;
Actuals : out List_Id;
Formals : out List_Id);
-- Given a dispatching call, extract the entity of the name of the call,
- -- its object parameter, its actual parameters and the formal parameters
- -- of the overridden interface-level version.
+ -- its actual dispatching object, its actual parameters and the formal
+ -- parameters of the overridden interface-level version. If the type of
+ -- the dispatching object is an access type then an explicit dereference
+ -- is returned in Object.
procedure Extract_Entry
(N : Node_Id;
-- The name of the formal that holds the address of the parameter block
-- for the call.
- Comp : Entity_Id;
- Decl : Node_Id;
- Formal : Entity_Id;
- New_F : Entity_Id;
+ Comp : Entity_Id;
+ Decl : Node_Id;
+ Formal : Entity_Id;
+ New_F : Entity_Id;
+ Renamed_Formal : Node_Id;
begin
Formal := First_Formal (Ent);
Set_Actual_Subtype (New_F, Actual_Subtype (Formal));
+ Renamed_Formal :=
+ Make_Selected_Component (Loc,
+ Prefix =>
+ Unchecked_Convert_To (Entry_Parameters_Type (Ent),
+ Make_Identifier (Loc, Chars (Ptr))),
+ Selector_Name => New_Reference_To (Comp, Loc));
+
Decl :=
- Make_Object_Renaming_Declaration (Loc,
- Defining_Identifier => New_F,
- Subtype_Mark =>
- New_Reference_To (Etype (Formal), Loc),
- Name =>
- Make_Explicit_Dereference (Loc,
- Make_Selected_Component (Loc,
- Prefix =>
- Unchecked_Convert_To (Entry_Parameters_Type (Ent),
- Make_Identifier (Loc, Chars (Ptr))),
- Selector_Name =>
- New_Reference_To (Comp, Loc))));
+ Build_Renamed_Formal_Declaration
+ (New_F, Formal, Comp, Renamed_Formal);
Append (Decl, Decls);
Set_Renamed_Object (Formal, New_F);
Object_Definition =>
New_Reference_To (Obj_Ptr, Loc),
Expression =>
- Unchecked_Convert_To (Obj_Ptr,
- Make_Identifier (Loc, Name_uO)));
+ Unchecked_Convert_To (Obj_Ptr, Make_Identifier (Loc, Name_uO)));
Set_Debug_Info_Needed (Defining_Identifier (Decl));
Prepend_To (Decls, Decl);
Obj_Ptr,
Type_Definition =>
Make_Access_To_Object_Definition (Loc,
- Subtype_Indication =>
- New_Reference_To (Rec_Typ, Loc)));
+ Subtype_Indication =>
+ New_Reference_To (Rec_Typ, Loc)));
Set_Debug_Info_Needed (Defining_Identifier (Decl));
Prepend_To (Decls, Decl);
end Add_Object_Pointer;
-----------------------------------
procedure Build_Activation_Chain_Entity (N : Node_Id) is
- P : Node_Id;
- Decls : List_Id;
- Chain : Entity_Id;
+ function Has_Activation_Chain (Stmt : Node_Id) return Boolean;
+ -- Determine whether an extended return statement has an activation
+ -- chain.
- begin
- -- Loop to find enclosing construct containing activation chain variable
- -- The construct is a body, a block, or an extended return.
-
- P := Parent (N);
-
- while not Nkind_In (P, N_Subprogram_Body,
- N_Entry_Body,
- N_Package_Declaration,
- N_Package_Body,
- N_Block_Statement,
- N_Task_Body,
- N_Extended_Return_Statement)
- loop
- P := Parent (P);
- end loop;
+ --------------------------
+ -- Has_Activation_Chain --
+ --------------------------
- -- If we are in a package body, the activation chain variable is
- -- declared in the body, but the Activation_Chain_Entity is attached
- -- to the spec.
+ function Has_Activation_Chain (Stmt : Node_Id) return Boolean is
+ Decl : Node_Id;
- if Nkind (P) = N_Package_Body then
- Decls := Declarations (P);
- P := Unit_Declaration_Node (Corresponding_Spec (P));
+ begin
+ Decl := First (Return_Object_Declarations (Stmt));
+ while Present (Decl) loop
+ if Nkind (Decl) = N_Object_Declaration
+ and then Chars (Defining_Identifier (Decl)) = Name_uChain
+ then
+ return True;
+ end if;
- elsif Nkind (P) = N_Package_Declaration then
- Decls := Visible_Declarations (Specification (P));
+ Next (Decl);
+ end loop;
- elsif Nkind (P) = N_Extended_Return_Statement then
- Decls := Return_Object_Declarations (P);
+ return False;
+ end Has_Activation_Chain;
- else
- Decls := Declarations (P);
- end if;
+ -- Local variables
- -- If activation chain entity not already declared, declare it
+ Context : Node_Id;
+ Context_Id : Entity_Id;
+ Decls : List_Id;
- if Nkind (P) = N_Extended_Return_Statement
- or else No (Activation_Chain_Entity (P))
+ -- Start of processing for Build_Activation_Chain_Entity
+
+ begin
+ Find_Enclosing_Context (N, Context, Context_Id, Decls);
+
+ -- If an activation chain entity has not been declared already, create
+ -- one.
+
+ if Nkind (Context) = N_Extended_Return_Statement
+ or else No (Activation_Chain_Entity (Context))
then
- Chain := Make_Defining_Identifier (Sloc (N), Name_uChain);
-
- -- Note: An extended return statement is not really a task activator,
- -- but it does have an activation chain on which to store the tasks
- -- temporarily. On successful return, the tasks on this chain are
- -- moved to the chain passed in by the caller. We do not build an
- -- Activation_Chain_Entity for an N_Extended_Return_Statement,
- -- because we do not want to build a call to Activate_Tasks. Task
- -- activation is the responsibility of the caller.
-
- if Nkind (P) /= N_Extended_Return_Statement then
- Set_Activation_Chain_Entity (P, Chain);
+ -- Since extended return statements do not store the entity of the
+ -- chain, examine the return object declarations to avoid creating
+ -- a duplicate.
+
+ if Nkind (Context) = N_Extended_Return_Statement
+ and then Has_Activation_Chain (Context)
+ then
+ return;
end if;
- Prepend_To (Decls,
- Make_Object_Declaration (Sloc (P),
- Defining_Identifier => Chain,
- Aliased_Present => True,
- Object_Definition =>
- New_Reference_To (RTE (RE_Activation_Chain), Sloc (P))));
+ declare
+ Loc : constant Source_Ptr := Sloc (Context);
+ Chain : Entity_Id;
+ Decl : Node_Id;
+
+ begin
+ Chain := Make_Defining_Identifier (Sloc (N), Name_uChain);
+
+ -- Note: An extended return statement is not really a task
+ -- activator, but it does have an activation chain on which to
+ -- store the tasks temporarily. On successful return, the tasks
+ -- on this chain are moved to the chain passed in by the caller.
+ -- We do not build an Activation_Chain_Entity for an extended
+ -- return statement, because we do not want to build a call to
+ -- Activate_Tasks. Task activation is the responsibility of the
+ -- caller.
+
+ if Nkind (Context) /= N_Extended_Return_Statement then
+ Set_Activation_Chain_Entity (Context, Chain);
+ end if;
+
+ Decl :=
+ Make_Object_Declaration (Loc,
+ Defining_Identifier => Chain,
+ Aliased_Present => True,
+ Object_Definition =>
+ New_Reference_To (RTE (RE_Activation_Chain), Loc));
+
+ Prepend_To (Decls, Decl);
+
+ -- Ensure that the _chain appears in the proper scope of the
+ -- context.
- Analyze (First (Decls));
+ if Context_Id /= Current_Scope then
+ Push_Scope (Context_Id);
+ Analyze (Decl);
+ Pop_Scope;
+ else
+ Analyze (Decl);
+ end if;
+ end;
end if;
end Build_Activation_Chain_Entity;
Ent : Entity_Id;
Pid : Node_Id) return Node_Id
is
- Loc : constant Source_Ptr := Sloc (N);
- Func_Id : constant Entity_Id := Barrier_Function (Ent);
Ent_Formals : constant Node_Id := Entry_Body_Formal_Part (N);
+ Cond : constant Node_Id := Condition (Ent_Formals);
+ Loc : constant Source_Ptr := Sloc (Cond);
+ Func_Id : constant Entity_Id := Barrier_Function (Ent);
Op_Decls : constant List_Id := New_List;
+ Stmt : Node_Id;
Func_Body : Node_Id;
begin
-- for the discriminals and privals and finally a declaration for the
-- entry family index (if applicable).
- Install_Private_Data_Declarations
- (Loc, Func_Id, Pid, N, Op_Decls, True, Ekind (Ent) = E_Entry_Family);
+ Install_Private_Data_Declarations (Sloc (N),
+ Spec_Id => Func_Id,
+ Conc_Typ => Pid,
+ Body_Nod => N,
+ Decls => Op_Decls,
+ Barrier => True,
+ Family => Ekind (Ent) = E_Entry_Family);
+
+ -- If compiling with -fpreserve-control-flow, make sure we insert an
+ -- IF statement so that the back-end knows to generate a conditional
+ -- branch instruction, even if the condition is just the name of a
+ -- boolean object.
+
+ if Opt.Suppress_Control_Flow_Optimizations then
+ Stmt := Make_Implicit_If_Statement (Cond,
+ Condition => Cond,
+ Then_Statements => New_List (
+ Make_Simple_Return_Statement (Loc,
+ New_Occurrence_Of (Standard_True, Loc))),
+ Else_Statements => New_List (
+ Make_Simple_Return_Statement (Loc,
+ New_Occurrence_Of (Standard_False, Loc))));
+
+ else
+ Stmt := Make_Simple_Return_Statement (Loc, Cond);
+ end if;
-- Note: the condition in the barrier function needs to be properly
-- processed for the C/Fortran boolean possibility, but this happens
Declarations => Op_Decls,
Handled_Statement_Sequence =>
Make_Handled_Sequence_Of_Statements (Loc,
- Statements => New_List (
- Make_Simple_Return_Statement (Loc,
- Expression => Condition (Ent_Formals)))));
+ Statements => New_List (Stmt)));
Set_Is_Entry_Barrier_Function (Func_Body);
return Func_Body;
Parameter_Associations => New_List (Concurrent_Ref (N)));
end Build_Call_With_Task;
+ -----------------------------
+ -- Build_Class_Wide_Master --
+ -----------------------------
+
+ procedure Build_Class_Wide_Master (Typ : Entity_Id) is
+ Loc : constant Source_Ptr := Sloc (Typ);
+ Master_Id : Entity_Id;
+ Master_Scope : Entity_Id;
+ Name_Id : Node_Id;
+ Related_Node : Node_Id;
+ Ren_Decl : Node_Id;
+
+ begin
+ -- Nothing to do if there is no task hierarchy
+
+ if Restriction_Active (No_Task_Hierarchy) then
+ return;
+ end if;
+
+ -- Find the declaration that created the access type. It is either a
+ -- type declaration, or an object declaration with an access definition,
+ -- in which case the type is anonymous.
+
+ if Is_Itype (Typ) then
+ Related_Node := Associated_Node_For_Itype (Typ);
+ else
+ Related_Node := Parent (Typ);
+ end if;
+
+ Master_Scope := Find_Master_Scope (Typ);
+
+ -- Nothing to do if the master scope already contains a _master entity.
+ -- The only exception to this is the following scenario:
+
+ -- Source_Scope
+ -- Transient_Scope_1
+ -- _master
+
+ -- Transient_Scope_2
+ -- use of master
+
+ -- In this case the source scope is marked as having the master entity
+ -- even though the actual declaration appears inside an inner scope. If
+ -- the second transient scope requires a _master, it cannot use the one
+ -- already declared because the entity is not visible.
+
+ Name_Id := Make_Identifier (Loc, Name_uMaster);
+
+ if not Has_Master_Entity (Master_Scope)
+ or else No (Current_Entity_In_Scope (Name_Id))
+ then
+ declare
+ Master_Decl : Node_Id;
+
+ begin
+ Set_Has_Master_Entity (Master_Scope);
+
+ -- Generate:
+ -- _master : constant Integer := Current_Master.all;
+
+ Master_Decl :=
+ Make_Object_Declaration (Loc,
+ Defining_Identifier =>
+ Make_Defining_Identifier (Loc, Name_uMaster),
+ Constant_Present => True,
+ Object_Definition =>
+ New_Reference_To (Standard_Integer, Loc),
+ Expression =>
+ Make_Explicit_Dereference (Loc,
+ New_Reference_To (RTE (RE_Current_Master), Loc)));
+
+ Insert_Action (Related_Node, Master_Decl);
+ Analyze (Master_Decl);
+
+ -- Mark the containing scope as a task master. Masters associated
+ -- with return statements are already marked at this stage (see
+ -- Analyze_Subprogram_Body).
+
+ if Ekind (Current_Scope) /= E_Return_Statement then
+ declare
+ Par : Node_Id := Related_Node;
+
+ begin
+ while Nkind (Par) /= N_Compilation_Unit loop
+ Par := Parent (Par);
+
+ -- If we fall off the top, we are at the outer level, and
+ -- the environment task is our effective master, so
+ -- nothing to mark.
+
+ if Nkind_In (Par, N_Block_Statement,
+ N_Subprogram_Body,
+ N_Task_Body)
+ then
+ Set_Is_Task_Master (Par);
+ exit;
+ end if;
+ end loop;
+ end;
+ end if;
+ end;
+ end if;
+
+ Master_Id :=
+ Make_Defining_Identifier (Loc,
+ New_External_Name (Chars (Typ), 'M'));
+
+ -- Generate:
+ -- Mnn renames _master;
+
+ Ren_Decl :=
+ Make_Object_Renaming_Declaration (Loc,
+ Defining_Identifier => Master_Id,
+ Subtype_Mark => New_Reference_To (Standard_Integer, Loc),
+ Name => Name_Id);
+
+ Insert_Action (Related_Node, Ren_Decl);
+
+ Set_Master_Id (Typ, Master_Id);
+ end Build_Class_Wide_Master;
+
--------------------------------
-- Build_Corresponding_Record --
--------------------------------
-- for the task body.
-- In fact the discriminals b) are used in the renaming declarations
- -- for e). See details in einfo (Handling of Discriminants).
+ -- for e). See details in einfo (Handling of Discriminants).
if Present (Discriminant_Specifications (N)) then
Dlist := New_List;
Make_Component_List (Loc,
Component_Items => Cdecls),
Tagged_Present =>
- Ada_Version >= Ada_05 and then Is_Tagged_Type (Ctyp),
+ Ada_Version >= Ada_2005 and then Is_Tagged_Type (Ctyp),
Interface_List => Interface_List (N),
Limited_Present => True));
end Build_Corresponding_Record;
-- Generate the call to the runtime routine Set_Entry_Name with actuals
-- _init._task_id or _init._object, Inn and Arg3.
- function Find_Protection_Type (Conc_Typ : Entity_Id) return Entity_Id;
- -- Given a protected type or its corresponding record, find the type of
- -- field _object.
-
procedure Increment_Index (Stmts : List_Id);
-- Generate the following and add it to Stmts
-- Inn := Inn + 1;
Arg3)); -- Val
end Build_Set_Entry_Name_Call;
- --------------------------
- -- Find_Protection_Type --
- --------------------------
-
- function Find_Protection_Type (Conc_Typ : Entity_Id) return Entity_Id is
- Comp : Entity_Id;
- Typ : Entity_Id := Conc_Typ;
-
- begin
- if Is_Concurrent_Type (Typ) then
- Typ := Corresponding_Record_Type (Typ);
- end if;
-
- Comp := First_Component (Typ);
- while Present (Comp) loop
- if Chars (Comp) = Name_uObject then
- return Base_Type (Etype (Comp));
- end if;
-
- Next_Component (Comp);
- end loop;
-
- -- The corresponding record of a protected type should always have an
- -- _object field.
-
- raise Program_Error;
- end Find_Protection_Type;
-
---------------------
-- Increment_Index --
---------------------
return Rec_Nam;
end Build_Parameter_Block;
+ --------------------------------------
+ -- Build_Renamed_Formal_Declaration --
+ --------------------------------------
+
+ function Build_Renamed_Formal_Declaration
+ (New_F : Entity_Id;
+ Formal : Entity_Id;
+ Comp : Entity_Id;
+ Renamed_Formal : Node_Id) return Node_Id
+ is
+ Loc : constant Source_Ptr := Sloc (New_F);
+ Decl : Node_Id;
+
+ begin
+ -- If the formal is a tagged incomplete type, it is already passed
+ -- by reference, so it is sufficient to rename the pointer component
+ -- that corresponds to the actual. Otherwise we need to dereference
+ -- the pointer component to obtain the actual.
+
+ if Is_Incomplete_Type (Etype (Formal))
+ and then Is_Tagged_Type (Etype (Formal))
+ then
+ Decl :=
+ Make_Object_Renaming_Declaration (Loc,
+ Defining_Identifier => New_F,
+ Subtype_Mark => New_Reference_To (Etype (Comp), Loc),
+ Name => Renamed_Formal);
+
+ else
+ Decl :=
+ Make_Object_Renaming_Declaration (Loc,
+ Defining_Identifier => New_F,
+ Subtype_Mark => New_Reference_To (Etype (Formal), Loc),
+ Name =>
+ Make_Explicit_Dereference (Loc, Renamed_Formal));
+ end if;
+
+ return Decl;
+ end Build_Renamed_Formal_Declaration;
+
+ -----------------------
+ -- Build_PPC_Wrapper --
+ -----------------------
+
+ procedure Build_PPC_Wrapper (E : Entity_Id; Decl : Node_Id) is
+ Loc : constant Source_Ptr := Sloc (E);
+ Synch_Type : constant Entity_Id := Scope (E);
+
+ Wrapper_Id : constant Entity_Id :=
+ Make_Defining_Identifier (Loc,
+ Chars => New_External_Name (Chars (E), 'E'));
+ -- the wrapper procedure name
+
+ Wrapper_Body : Node_Id;
+
+ Synch_Id : constant Entity_Id :=
+ Make_Defining_Identifier (Loc,
+ Chars => New_External_Name (Chars (Scope (E)), 'A'));
+ -- The parameter that designates the synchronized object in the call
+
+ Actuals : constant List_Id := New_List;
+ -- The actuals in the entry call
+
+ Decls : constant List_Id := New_List;
+
+ Entry_Call : Node_Id;
+ Entry_Name : Node_Id;
+
+ Specs : List_Id;
+ -- The specification of the wrapper procedure
+
+ begin
+
+ -- Only build the wrapper if entry has pre/postconditions.
+ -- Should this be done unconditionally instead ???
+
+ declare
+ P : Node_Id;
+
+ begin
+ P := Spec_PPC_List (Contract (E));
+ if No (P) then
+ return;
+ end if;
+
+ -- Transfer ppc pragmas to the declarations of the wrapper
+
+ while Present (P) loop
+ if Pragma_Name (P) = Name_Precondition
+ or else Pragma_Name (P) = Name_Postcondition
+ then
+ Append (Relocate_Node (P), Decls);
+ Set_Analyzed (Last (Decls), False);
+ end if;
+
+ P := Next_Pragma (P);
+ end loop;
+ end;
+
+ -- First formal is synchronized object
+
+ Specs := New_List (
+ Make_Parameter_Specification (Loc,
+ Defining_Identifier => Synch_Id,
+ Out_Present => True,
+ In_Present => True,
+ Parameter_Type => New_Occurrence_Of (Scope (E), Loc)));
+
+ Entry_Name :=
+ Make_Selected_Component (Loc,
+ Prefix => New_Occurrence_Of (Synch_Id, Loc),
+ Selector_Name => New_Occurrence_Of (E, Loc));
+
+ -- If entity is entry family, second formal is the corresponding index,
+ -- and entry name is an indexed component.
+
+ if Ekind (E) = E_Entry_Family then
+ declare
+ Index : constant Entity_Id :=
+ Make_Defining_Identifier (Loc, Name_I);
+ begin
+ Append_To (Specs,
+ Make_Parameter_Specification (Loc,
+ Defining_Identifier => Index,
+ Parameter_Type =>
+ New_Occurrence_Of (Entry_Index_Type (E), Loc)));
+
+ Entry_Name :=
+ Make_Indexed_Component (Loc,
+ Prefix => Entry_Name,
+ Expressions => New_List (New_Occurrence_Of (Index, Loc)));
+ end;
+ end if;
+
+ Entry_Call :=
+ Make_Procedure_Call_Statement (Loc,
+ Name => Entry_Name,
+ Parameter_Associations => Actuals);
+
+ -- Now add formals that match those of the entry, and build actuals for
+ -- the nested entry call.
+
+ declare
+ Form : Entity_Id;
+ New_Form : Entity_Id;
+ Parm_Spec : Node_Id;
+
+ begin
+ Form := First_Formal (E);
+ while Present (Form) loop
+ New_Form := Make_Defining_Identifier (Loc, Chars (Form));
+ Parm_Spec :=
+ Make_Parameter_Specification (Loc,
+ Defining_Identifier => New_Form,
+ Out_Present => Out_Present (Parent (Form)),
+ In_Present => In_Present (Parent (Form)),
+ Parameter_Type => New_Occurrence_Of (Etype (Form), Loc));
+
+ Append (Parm_Spec, Specs);
+ Append (New_Occurrence_Of (New_Form, Loc), Actuals);
+ Next_Formal (Form);
+ end loop;
+ end;
+
+ -- Add renaming declarations for the discriminants of the enclosing
+ -- type, which may be visible in the preconditions.
+
+ if Has_Discriminants (Synch_Type) then
+ declare
+ D : Entity_Id;
+ Decl : Node_Id;
+
+ begin
+ D := First_Discriminant (Synch_Type);
+ while Present (D) loop
+ Decl :=
+ Make_Object_Renaming_Declaration (Loc,
+ Defining_Identifier =>
+ Make_Defining_Identifier (Loc, Chars (D)),
+ Subtype_Mark => New_Reference_To (Etype (D), Loc),
+ Name =>
+ Make_Selected_Component (Loc,
+ Prefix => New_Reference_To (Synch_Id, Loc),
+ Selector_Name => Make_Identifier (Loc, Chars (D))));
+ Prepend (Decl, Decls);
+ Next_Discriminant (D);
+ end loop;
+ end;
+ end if;
+
+ Set_PPC_Wrapper (E, Wrapper_Id);
+ Wrapper_Body :=
+ Make_Subprogram_Body (Loc,
+ Specification =>
+ Make_Procedure_Specification (Loc,
+ Defining_Unit_Name => Wrapper_Id,
+ Parameter_Specifications => Specs),
+ Declarations => Decls,
+ Handled_Statement_Sequence =>
+ Make_Handled_Sequence_Of_Statements (Loc,
+ Statements => New_List (Entry_Call)));
+
+ -- The wrapper body is analyzed when the enclosing type is frozen
+
+ Append_Freeze_Action (Defining_Entity (Decl), Wrapper_Body);
+ end Build_PPC_Wrapper;
+
--------------------------
-- Build_Wrapper_Bodies --
--------------------------
end if;
declare
- Actuals : List_Id := No_List;
- Conv_Id : Node_Id;
- First_Form : Node_Id;
- Formal : Node_Id;
- Nam : Node_Id;
+ Actuals : List_Id := No_List;
+ Conv_Id : Node_Id;
+ First_Form : Node_Id;
+ Formal : Node_Id;
+ Nam : Node_Id;
begin
-- Map formals to actuals. Use the list built for the wrapper
if Present (Formal) then
Actuals := New_List;
-
while Present (Formal) loop
Append_To (Actuals,
- Make_Identifier (Loc, Chars =>
- Chars (Defining_Identifier (Formal))));
-
+ Make_Identifier (Loc,
+ Chars => Chars (Defining_Identifier (Formal))));
Next (Formal);
end loop;
end if;
if Is_Controlling_Formal (First_Formal (Subp_Id)) then
Prepend_To (Actuals,
- Unchecked_Convert_To (
- Corresponding_Concurrent_Type (Obj_Typ),
- Make_Identifier (Loc, Name_uO)));
+ Unchecked_Convert_To
+ (Corresponding_Concurrent_Type (Obj_Typ),
+ Make_Identifier (Loc, Name_uO)));
else
Prepend_To (Actuals,
- Make_Identifier (Loc, Chars =>
- Chars (Defining_Identifier (First_Form))));
+ Make_Identifier (Loc,
+ Chars => Chars (Defining_Identifier (First_Form))));
end if;
Nam := New_Reference_To (Subp_Id, Loc);
Nam :=
Make_Selected_Component (Loc,
- Prefix =>
- Unchecked_Convert_To (
- Corresponding_Concurrent_Type (Obj_Typ),
- Conv_Id),
- Selector_Name =>
- New_Reference_To (Subp_Id, Loc));
+ Prefix =>
+ Unchecked_Convert_To
+ (Corresponding_Concurrent_Type (Obj_Typ), Conv_Id),
+ Selector_Name => New_Reference_To (Subp_Id, Loc));
end if;
-- Create the subprogram body. For a function, the call to the
end loop Search;
end if;
- -- If the subprogram to be wrapped is not overriding anything or is not
- -- a primitive declared between two views, do not produce anything. This
- -- avoids spurious errors involving overriding.
+ -- Ada 2012 (AI05-0090-1): If no interface primitive is covered by
+ -- this subprogram and this is not a primitive declared between two
+ -- views then force the generation of a wrapper. As an optimization,
+ -- previous versions of the frontend avoid generating the wrapper;
+ -- however, the wrapper facilitates locating and reporting an error
+ -- when a duplicate declaration is found later. See example in
+ -- AI05-0090-1.
if No (First_Param)
and then not Is_Private_Primitive_Subprogram (Subp_Id)
then
- return Empty;
+ if Is_Task_Type
+ (Corresponding_Concurrent_Type (Obj_Typ))
+ then
+ First_Param :=
+ Make_Parameter_Specification (Loc,
+ Defining_Identifier => Make_Defining_Identifier (Loc, Name_uO),
+ In_Present => True,
+ Out_Present => False,
+ Parameter_Type => New_Reference_To (Obj_Typ, Loc));
+
+ -- For entries and procedures of protected types the mode of
+ -- the controlling argument must be in-out.
+
+ else
+ First_Param :=
+ Make_Parameter_Specification (Loc,
+ Defining_Identifier =>
+ Make_Defining_Identifier (Loc,
+ Chars => Name_uO),
+ In_Present => True,
+ Out_Present => (Ekind (Subp_Id) /= E_Function),
+ Parameter_Type => New_Reference_To (Obj_Typ, Loc));
+ end if;
end if;
declare
Cond :=
Make_Op_Le (Loc,
- Left_Opnd => Make_Identifier (Loc, Name_uE),
+ Left_Opnd => Make_Identifier (Loc, Name_uE),
Right_Opnd => Siz);
- -- Map entry queue indices in the range of the current family
+ -- Map entry queue indexes in the range of the current family
-- into the current index, that designates the entry body.
if No (If_St) then
-- Build_Master_Entity --
-------------------------
- procedure Build_Master_Entity (E : Entity_Id) is
- Loc : constant Source_Ptr := Sloc (E);
- P : Node_Id;
- Decl : Node_Id;
- S : Entity_Id;
+ procedure Build_Master_Entity (Obj_Or_Typ : Entity_Id) is
+ Loc : constant Source_Ptr := Sloc (Obj_Or_Typ);
+ Context : Node_Id;
+ Context_Id : Entity_Id;
+ Decl : Node_Id;
+ Decls : List_Id;
+ Par : Node_Id;
begin
- S := Find_Master_Scope (E);
+ if Is_Itype (Obj_Or_Typ) then
+ Par := Associated_Node_For_Itype (Obj_Or_Typ);
+ else
+ Par := Parent (Obj_Or_Typ);
+ end if;
+
+ -- When creating a master for a record component which is either a task
+ -- or access-to-task, the enclosing record is the master scope and the
+ -- proper insertion point is the component list.
- -- Nothing to do if we already built a master entity for this scope
- -- or if there is no task hierarchy.
+ if Is_Record_Type (Current_Scope) then
+ Context := Par;
+ Context_Id := Current_Scope;
+ Decls := List_Containing (Context);
- if Has_Master_Entity (S)
+ -- Default case for object declarations and access types. Note that the
+ -- context is updated to the nearest enclosing body, block, package or
+ -- return statement.
+
+ else
+ Find_Enclosing_Context (Par, Context, Context_Id, Decls);
+ end if;
+
+ -- Do not create a master if one already exists or there is no task
+ -- hierarchy.
+
+ if Has_Master_Entity (Context_Id)
or else Restriction_Active (No_Task_Hierarchy)
then
return;
end if;
- -- Otherwise first build the master entity
+ -- Create a master, generate:
-- _Master : constant Master_Id := Current_Master.all;
- -- and insert it just before the current declaration
Decl :=
Make_Object_Declaration (Loc,
Defining_Identifier =>
Make_Defining_Identifier (Loc, Name_uMaster),
- Constant_Present => True,
- Object_Definition => New_Reference_To (RTE (RE_Master_Id), Loc),
- Expression =>
+ Constant_Present => True,
+ Object_Definition => New_Reference_To (RTE (RE_Master_Id), Loc),
+ Expression =>
Make_Explicit_Dereference (Loc,
New_Reference_To (RTE (RE_Current_Master), Loc)));
- P := Parent (E);
- Insert_Before (P, Decl);
- Analyze (Decl);
+ -- The master is inserted at the start of the declarative list of the
+ -- context.
+
+ Prepend_To (Decls, Decl);
+
+ -- In certain cases where transient scopes are involved, the immediate
+ -- scope is not always the proper master scope. Ensure that the master
+ -- declaration and entity appear in the same context.
+
+ if Context_Id /= Current_Scope then
+ Push_Scope (Context_Id);
+ Analyze (Decl);
+ Pop_Scope;
+ else
+ Analyze (Decl);
+ end if;
+
+ -- Mark the enclosing scope and its associated construct as being task
+ -- masters.
+
+ Set_Has_Master_Entity (Context_Id);
+
+ while Present (Context)
+ and then Nkind (Context) /= N_Compilation_Unit
+ loop
+ if Nkind_In (Context, N_Block_Statement,
+ N_Subprogram_Body,
+ N_Task_Body)
+ then
+ Set_Is_Task_Master (Context);
+ exit;
+
+ elsif Nkind (Parent (Context)) = N_Subunit then
+ Context := Corresponding_Stub (Parent (Context));
+ end if;
+
+ Context := Parent (Context);
+ end loop;
+ end Build_Master_Entity;
+
+ ---------------------------
+ -- Build_Master_Renaming --
+ ---------------------------
+
+ procedure Build_Master_Renaming
+ (Ptr_Typ : Entity_Id;
+ Ins_Nod : Node_Id := Empty)
+ is
+ Loc : constant Source_Ptr := Sloc (Ptr_Typ);
+ Context : Node_Id;
+ Master_Decl : Node_Id;
+ Master_Id : Entity_Id;
+
+ begin
+ -- Nothing to do if there is no task hierarchy
+
+ if Restriction_Active (No_Task_Hierarchy) then
+ return;
+ end if;
+
+ -- Determine the proper context to insert the master renaming
+
+ if Present (Ins_Nod) then
+ Context := Ins_Nod;
+ elsif Is_Itype (Ptr_Typ) then
+ Context := Associated_Node_For_Itype (Ptr_Typ);
+ else
+ Context := Parent (Ptr_Typ);
+ end if;
- Set_Has_Master_Entity (S);
+ -- Generate:
+ -- <Ptr_Typ>M : Master_Id renames _Master;
- -- Now mark the containing scope as a task master
+ Master_Id :=
+ Make_Defining_Identifier (Loc,
+ New_External_Name (Chars (Ptr_Typ), 'M'));
- while Nkind (P) /= N_Compilation_Unit loop
- P := Parent (P);
+ Master_Decl :=
+ Make_Object_Renaming_Declaration (Loc,
+ Defining_Identifier => Master_Id,
+ Subtype_Mark => New_Reference_To (RTE (RE_Master_Id), Loc),
+ Name => Make_Identifier (Loc, Name_uMaster));
- -- If we fall off the top, we are at the outer level, and the
- -- environment task is our effective master, so nothing to mark.
+ Insert_Action (Context, Master_Decl);
- if Nkind_In
- (P, N_Task_Body, N_Block_Statement, N_Subprogram_Body)
- then
- Set_Is_Task_Master (P, True);
- return;
+ -- The renamed master now services the access type
- elsif Nkind (Parent (P)) = N_Subunit then
- P := Corresponding_Stub (Parent (P));
- end if;
- end loop;
- end Build_Master_Entity;
+ Set_Master_Id (Ptr_Typ, Master_Id);
+ end Build_Master_Renaming;
-----------------------------------------
-- Build_Private_Protected_Declaration --
Make_Attribute_Reference (End_Loc,
Prefix =>
Make_Selected_Component (End_Loc,
- Prefix =>
- Make_Identifier (End_Loc, Name_uObject),
- Selector_Name =>
- Make_Identifier (End_Loc, Name_uObject)),
+ Prefix => Make_Identifier (End_Loc, Name_uObject),
+ Selector_Name => Make_Identifier (End_Loc, Name_uObject)),
Attribute_Name => Name_Unchecked_Access))));
-- When exceptions can not be propagated, we never need to call
raise Program_Error;
end case;
- -- Establish link between subprogram body entity and source entry.
+ -- Establish link between subprogram body entity and source entry
Set_Corresponding_Protected_Entry (Edef, Ent);
Make_Attribute_Reference (Han_Loc,
Prefix =>
Make_Selected_Component (Han_Loc,
- Prefix =>
+ Prefix =>
Make_Identifier (Han_Loc, Name_uObject),
Selector_Name =>
Make_Identifier (Han_Loc, Name_uObject)),
Stmts : List_Id;
Object_Parm : Node_Id;
Exc_Safe : Boolean;
+ Lock_Kind : RE_Id;
function Is_Exception_Safe (Subprogram : Node_Id) return Boolean;
-- Tell whether a given subprogram cannot raise an exception
Uactuals := New_List;
Pformal := First (Parameter_Specifications (P_Op_Spec));
while Present (Pformal) loop
- Append (
- Make_Identifier (Loc, Chars (Defining_Identifier (Pformal))),
- Uactuals);
+ Append_To (Uactuals,
+ Make_Identifier (Loc, Chars (Defining_Identifier (Pformal))));
Next (Pformal);
end loop;
Expression =>
Make_Function_Call (Loc,
Name => Make_Identifier (Loc,
- Chars (Defining_Unit_Name (N_Op_Spec))),
+ Chars => Chars (Defining_Unit_Name (N_Op_Spec))),
Parameter_Associations => Uactuals));
Return_Stmt :=
Expression => Make_Function_Call (Loc,
Name =>
Make_Identifier (Loc,
- Chars (Defining_Unit_Name (N_Op_Spec))),
+ Chars => Chars (Defining_Unit_Name (N_Op_Spec))),
Parameter_Associations => Uactuals));
end if;
+ Lock_Kind := RE_Lock_Read_Only;
+
else
Unprot_Call :=
Make_Procedure_Call_Statement (Loc,
Name =>
- Make_Identifier (Loc,
- Chars (Defining_Unit_Name (N_Op_Spec))),
+ Make_Identifier (Loc, Chars (Defining_Unit_Name (N_Op_Spec))),
Parameter_Associations => Uactuals);
+
+ Lock_Kind := RE_Lock;
end if;
-- Wrap call in block that will be covered by an at_end handler
Service_Name := New_Reference_To (RTE (RE_Service_Entry), Loc);
when System_Tasking_Protected_Objects =>
- Lock_Name := New_Reference_To (RTE (RE_Lock), Loc);
+ Lock_Name := New_Reference_To (RTE (Lock_Kind), Loc);
Service_Name := New_Reference_To (RTE (RE_Unlock), Loc);
when others =>
Make_Attribute_Reference (Loc,
Prefix =>
Make_Selected_Component (Loc,
- Prefix =>
- Make_Identifier (Loc, Name_uObject),
- Selector_Name =>
- Make_Identifier (Loc, Name_uObject)),
+ Prefix => Make_Identifier (Loc, Name_uObject),
+ Selector_Name => Make_Identifier (Loc, Name_uObject)),
Attribute_Name => Name_Unchecked_Access);
Lock_Stmt := Make_Procedure_Call_Statement (Loc,
if Nkind (Concval) = N_Function_Call
and then Is_Task_Type (Conctyp)
- and then Ada_Version >= Ada_05
+ and then Ada_Version >= Ada_2005
then
declare
ExpR : constant Node_Id := Relocate_Node (Concval);
Attribute_Name => Name_Unchecked_Access,
Prefix =>
New_Reference_To (Defining_Identifier (N_Node), Loc)));
+
+ -- If it is a VM_By_Copy_Actual, copy it to a new variable
+
+ elsif Is_VM_By_Copy_Actual (Actual) then
+ N_Node :=
+ Make_Object_Declaration (Loc,
+ Defining_Identifier => Make_Temporary (Loc, 'J'),
+ Aliased_Present => True,
+ Object_Definition =>
+ New_Reference_To (Etype (Formal), Loc),
+ Expression => New_Copy_Tree (Actual));
+ Set_Assignment_OK (N_Node);
+
+ Append (N_Node, Decls);
+
+ Append_To (Plist,
+ Make_Attribute_Reference (Loc,
+ Attribute_Name => Name_Unchecked_Access,
+ Prefix =>
+ New_Reference_To (Defining_Identifier (N_Node), Loc)));
+
else
-- Interface class-wide formal
- if Ada_Version >= Ada_05
+ if Ada_Version >= Ada_2005
and then Ekind (Etype (Formal)) = E_Class_Wide_Type
and then Is_Interface (Etype (Formal))
then
Set_Assignment_OK (Actual);
while Present (Actual) loop
- if Is_By_Copy_Type (Etype (Actual))
+ if (Is_By_Copy_Type (Etype (Actual))
+ or else Is_VM_By_Copy_Actual (Actual))
and then Ekind (Formal) /= E_In_Parameter
then
N_Node :=
Make_Object_Declaration (Loc,
Defining_Identifier => Chain,
- Aliased_Present => True,
+ Aliased_Present => True,
Object_Definition =>
New_Reference_To (RTE (RE_Activation_Chain), Loc))),
return
Make_Selected_Component (Loc,
- Prefix =>
+ Prefix =>
Unchecked_Convert_To (Corresponding_Record_Type (Ntyp),
New_Copy_Tree (N)),
Selector_Name => Make_Identifier (Loc, Sel));
Ldecl2 : Node_Id;
begin
- if Expander_Active then
+ if Full_Expander_Active then
-- If we have no handled statement sequence, we may need to build
-- a dummy sequence consisting of a null statement. This can be
then
Set_Handled_Statement_Sequence (N,
Make_Handled_Sequence_Of_Statements (Loc,
- New_List (Make_Null_Statement (Loc))));
+ Statements => New_List (Make_Null_Statement (Loc))));
end if;
-- Create and declare two labels to be placed at the end of the
and then Present (Handled_Statement_Sequence (N))
then
declare
- Comp : Entity_Id;
- Decl : Node_Id;
- Formal : Entity_Id;
- New_F : Entity_Id;
+ Comp : Entity_Id;
+ Decl : Node_Id;
+ Formal : Entity_Id;
+ New_F : Entity_Id;
+ Renamed_Formal : Node_Id;
begin
Push_Scope (Ent);
Set_Actual_Subtype (New_F, Actual_Subtype (Formal));
+ Renamed_Formal :=
+ Make_Selected_Component (Loc,
+ Prefix =>
+ Unchecked_Convert_To (
+ Entry_Parameters_Type (Ent),
+ New_Reference_To (Ann, Loc)),
+ Selector_Name =>
+ New_Reference_To (Comp, Loc));
+
Decl :=
- Make_Object_Renaming_Declaration (Loc,
- Defining_Identifier =>
- New_F,
- Subtype_Mark =>
- New_Reference_To (Etype (Formal), Loc),
- Name =>
- Make_Explicit_Dereference (Loc,
- Make_Selected_Component (Loc,
- Prefix =>
- Unchecked_Convert_To (
- Entry_Parameters_Type (Ent),
- New_Reference_To (Ann, Loc)),
- Selector_Name =>
- New_Reference_To (Comp, Loc))));
+ Build_Renamed_Formal_Declaration
+ (New_F, Formal, Comp, Renamed_Formal);
if No (Declarations (N)) then
Set_Declarations (N, New_List);
Insert_After (N, Decl1);
Analyze (Decl1);
+ -- Associate the access to subprogram with its original access to
+ -- protected subprogram type. Needed by the backend to know that this
+ -- type corresponds with an access to protected subprogram type.
+
+ Set_Original_Access_Type (D_T2, T);
+
-- Create Equivalent_Type, a record with two components for an access to
-- object and an access to subprogram.
Comps := New_List (
Make_Component_Declaration (Loc,
- Defining_Identifier => Make_Temporary (Loc, 'P'),
+ Defining_Identifier => Make_Temporary (Loc, 'P'),
Component_Definition =>
Make_Component_Definition (Loc,
Aliased_Present => False,
Decl2 :=
Make_Full_Type_Declaration (Loc,
Defining_Identifier => E_T,
- Type_Definition =>
+ Type_Definition =>
Make_Record_Definition (Loc,
Component_List =>
- Make_Component_List (Loc,
- Component_Items => Comps)));
+ Make_Component_List (Loc, Component_Items => Comps)));
Insert_After (Decl1, Decl2);
Analyze (Decl2);
-- barrier just as a protected function, and discard the protected
-- version of it because it is never called.
- if Expander_Active then
+ if Full_Expander_Active then
B_F := Build_Barrier_Function (N, Ent, Prot);
Func := Barrier_Function (Ent);
Set_Corresponding_Spec (B_F, Func);
-- condition does not reference any of the generated renamings
-- within the function.
- if Expander_Active
+ if Full_Expander_Active
and then Scope (Entity (Cond)) /= Func
then
Set_Declarations (B_F, Empty_List);
-- A task interface class-wide type object is being aborted.
-- Retrieve its _task_id by calling a dispatching routine.
- if Ada_Version >= Ada_05
+ if Ada_Version >= Ada_2005
and then Ekind (Etype (Tasknm)) = E_Class_Wide_Type
and then Is_Interface (Etype (Tasknm))
and then Is_Task_Interface (Etype (Tasknm))
New_Reference_To (RTE (RO_ST_Task_Id), Loc),
Expression =>
Make_Selected_Component (Loc,
- Prefix =>
- New_Copy_Tree (Tasknm),
+ Prefix => New_Copy_Tree (Tasknm),
Selector_Name =>
Make_Identifier (Loc, Name_uDisp_Get_Task_Id)))));
Declarations => Declarations (N),
Handled_Statement_Sequence => Build_Accept_Body (N));
+ -- For the analysis of the generated declarations, the parent node
+ -- must be properly set.
+
+ Set_Parent (Block, Parent (N));
+
-- Prepend call to Accept_Call to main statement sequence If the
-- accept has exception handlers, the statement sequence is wrapped
-- in a block. Insert call and renaming declarations in the
Enqueue_Call : Node_Id;
Formals : List_Id;
Hdle : List_Id;
+ Handler_Stmt : Node_Id;
Index : Node_Id;
Lim_Typ_Stmts : List_Id;
N_Orig : Node_Id;
ProtP_Stmts : List_Id;
Stmt : Node_Id;
Stmts : List_Id;
- Target_Undefer : RE_Id;
TaskE_Stmts : List_Id;
- Undefer_Args : List_Id := No_List;
B : Entity_Id; -- Call status flag
Bnn : Entity_Id; -- Communication block
T : Entity_Id; -- Additional status flag
begin
+ Process_Statements_For_Controlled_Objects (Trig);
+ Process_Statements_For_Controlled_Objects (Abrt);
+
Blk_Ent := Make_Temporary (Loc, 'A');
Ecall := Triggering_Statement (Trig);
-- trigger which was expanded into a procedure call.
if Nkind (Ecall) = N_Procedure_Call_Statement then
- if Ada_Version >= Ada_05
+ if Ada_Version >= Ada_2005
and then
(No (Original_Node (Ecall))
or else not Nkind_In (Original_Node (Ecall),
Make_Unchecked_Type_Conversion (Loc,
Subtype_Mark =>
New_Reference_To (RTE (RE_Communication_Block), Loc),
- Expression =>
- Make_Identifier (Loc, Name_uD))));
+ Expression => Make_Identifier (Loc, Name_uD))));
-- Generate:
-- _Disp_Asynchronous_Select (<object>, S, P'Address, D, B);
Make_Unchecked_Type_Conversion (Loc,
Subtype_Mark =>
New_Reference_To (RTE (RE_Communication_Block), Loc),
- Expression =>
- Make_Identifier (Loc, Name_uD))));
+ Expression => Make_Identifier (Loc, Name_uD))));
-- Generate:
-- _Disp_Asynchronous_Select (<object>, S, P'Address, D, B);
-- Create the inner block to protect the abortable part
- Hdle := New_List (
- Make_Implicit_Exception_Handler (Loc,
- Exception_Choices =>
- New_List (New_Reference_To (Stand.Abort_Signal, Loc)),
- Statements => New_List (
- Make_Procedure_Call_Statement (Loc,
- Name => New_Reference_To (RTE (RE_Abort_Undefer), Loc)))));
+ Hdle := New_List (Build_Abort_Block_Handler (Loc));
Prepend_To (Astats,
Make_Procedure_Call_Statement (Loc,
Append_To (Stmts,
Make_Implicit_If_Statement (N,
Condition => Make_Function_Call (Loc,
- Name => New_Reference_To (
- RTE (RE_Enqueued), Loc),
+ Name => New_Reference_To (RTE (RE_Enqueued), Loc),
Parameter_Associations => New_List (
New_Reference_To (Cancel_Param, Loc))),
Then_Statements => Astats));
-- See 4jexcept.ads for an explanation.
if VM_Target = No_VM then
- Target_Undefer := RE_Abort_Undefer;
+ if Exception_Mechanism = Back_End_Exceptions then
+
+ -- Aborts are not deferred at beginning of exception handlers
+ -- in ZCX.
+
+ Handler_Stmt := Make_Null_Statement (Loc);
+
+ else
+ Handler_Stmt := Make_Procedure_Call_Statement (Loc,
+ Name => New_Reference_To (RTE (RE_Abort_Undefer), Loc),
+ Parameter_Associations => No_List);
+ end if;
else
- Target_Undefer := RE_Update_Exception;
- Undefer_Args :=
- New_List (Make_Function_Call (Loc,
- Name => New_Occurrence_Of
- (RTE (RE_Current_Target_Exception), Loc)));
+ Handler_Stmt := Make_Procedure_Call_Statement (Loc,
+ Name => New_Reference_To (RTE (RE_Update_Exception), Loc),
+ Parameter_Associations => New_List (
+ Make_Function_Call (Loc,
+ Name => New_Occurrence_Of
+ (RTE (RE_Current_Target_Exception), Loc))));
end if;
Stmts := New_List (
Exception_Choices =>
New_List (New_Reference_To (Stand.Abort_Signal, Loc)),
- Statements => New_List (
- Make_Procedure_Call_Statement (Loc,
- Name => New_Reference_To (
- RTE (Target_Undefer), Loc),
- Parameter_Associations => Undefer_Args)))))),
+ Statements => New_List (Handler_Stmt))))),
-- if not Cancelled (Bnn) then
-- triggered statements
-- Create the inner block to protect the abortable part
- Hdle := New_List (
- Make_Implicit_Exception_Handler (Loc,
- Exception_Choices =>
- New_List (New_Reference_To (Stand.Abort_Signal, Loc)),
- Statements =>
- New_List (
- Make_Procedure_Call_Statement (Loc,
- Name => New_Reference_To (RTE (RE_Abort_Undefer), Loc)))));
+ Hdle := New_List (Build_Abort_Block_Handler (Loc));
Prepend_To (Astats,
Make_Procedure_Call_Statement (Loc,
S : Entity_Id; -- Primitive operation slot
begin
- if Ada_Version >= Ada_05
+ Process_Statements_For_Controlled_Objects (N);
+
+ if Ada_Version >= Ada_2005
and then Nkind (Blk) = N_Procedure_Call_Statement
then
Extract_Dispatching_Call (Blk, Call_Ent, Obj, Actuals, Formals);
Subtype_Indication => New_Reference_To (Rec_Ent, Loc)));
Insert_After (Last_Decl, Decl);
- Last_Decl := Decl;
end if;
end Expand_N_Entry_Declaration;
Op_Body : Node_Id;
Op_Id : Entity_Id;
- Chain : Entity_Id := Empty;
- -- Finalization chain that may be attached to new body
-
function Build_Dispatching_Subprogram_Body
(N : Node_Id;
Pid : Node_Id;
-- Generate a specification without a letter suffix in order to
-- override an interface function or procedure.
- Spec :=
- Build_Protected_Sub_Specification (N, Pid, Dispatching_Mode);
+ Spec := Build_Protected_Sub_Specification (N, Pid, Dispatching_Mode);
- -- The formal parameters become the actuals of the protected
- -- function or procedure call.
+ -- The formal parameters become the actuals of the protected function
+ -- or procedure call.
Actuals := New_List;
Formal := First (Parameter_Specifications (Spec));
return
Make_Subprogram_Body (Loc,
- Declarations => Empty_List,
- Specification => Spec,
+ Declarations => Empty_List,
+ Specification => Spec,
Handled_Statement_Sequence =>
Make_Handled_Sequence_Of_Statements (Loc, Stmts));
end Build_Dispatching_Subprogram_Body;
New_Op_Body :=
Build_Unprotected_Subprogram_Body (Op_Body, Pid);
- -- Propagate the finalization chain to the new body. In the
- -- unlikely event that the subprogram contains a declaration
- -- or allocator for an object that requires finalization,
- -- the corresponding chain is created when analyzing the
- -- body, and attached to its entity. This entity is not
- -- further elaborated, and so the chain properly belongs to
- -- the newly created subprogram body.
-
- Chain :=
- Finalization_Chain_Entity (Defining_Entity (Op_Body));
-
- if Present (Chain) then
- Set_Finalization_Chain_Entity
- (Protected_Body_Subprogram
- (Corresponding_Spec (Op_Body)), Chain);
- Set_Analyzed
- (Handled_Statement_Sequence (New_Op_Body), False);
- end if;
-
Insert_After (Current_Node, New_Op_Body);
Current_Node := New_Op_Body;
Analyze (New_Op_Body);
-- this subprogram if the protected type implements an
-- interface.
- if Ada_Version >= Ada_05
+ if Ada_Version >= Ada_2005
and then
Present (Interfaces (Corresponding_Record_Type (Pid)))
then
-- protected body. At this point all wrapper specs have been created,
-- frozen and included in the dispatch table for the protected type.
- if Ada_Version >= Ada_05 then
+ if Ada_Version >= Ada_2005 then
Build_Wrapper_Bodies (Loc, Pid, Current_Node);
end if;
end Expand_N_Protected_Body;
Make_Integer_Literal (Loc, Num_Attach_Handler))));
end if;
- elsif Has_Interrupt_Handler (Prot_Typ) then
+ elsif Has_Interrupt_Handler (Prot_Typ)
+ and then not Restriction_Active (No_Dynamic_Attachment)
+ then
Protection_Subtype :=
Make_Subtype_Indication (
Sloc => Loc,
-- Type has explicit entries or generated primitive entry wrappers
elsif Has_Entries (Prot_Typ)
- or else (Ada_Version >= Ada_05
+ or else (Ada_Version >= Ada_2005
and then Present (Interface_List (N)))
then
case Corresponding_Runtime_Package (Prot_Typ) is
-- the corresponding record is frozen. If any wrappers are generated,
-- Current_Node is updated accordingly.
- if Ada_Version >= Ada_05 then
+ if Ada_Version >= Ada_2005 then
Build_Wrapper_Specs (Loc, Prot_Typ, Current_Node);
end if;
Set_Protected_Body_Subprogram
(Defining_Unit_Name (Specification (Comp)),
Defining_Unit_Name (Specification (Sub)));
- Check_Inlining (Defining_Unit_Name (Specification (Comp)));
+ Check_Inlining (Defining_Unit_Name (Specification (Comp)));
-- Make the protected version of the subprogram available for
-- expansion of external calls.
-- Generate an overriding primitive operation specification for
-- this subprogram if the protected type implements an interface.
- if Ada_Version >= Ada_05
+ if Ada_Version >= Ada_2005
and then
Present (Interfaces (Corresponding_Record_Type (Prot_Typ)))
then
Insert_After (Current_Node, Sub);
Analyze (Sub);
+ -- Build wrapper procedure for pre/postconditions
+
+ Build_PPC_Wrapper (Comp_Id, N);
+
Set_Protected_Body_Subprogram
(Defining_Identifier (Comp),
Defining_Unit_Name (Specification (Sub)));
-- when all others =>
-- Exceptional_Complete_Rendezvous (Get_GNAT_Exception);
- -- Ada 2005 (AI05-0030): Dispatching requeue from protected to interface
- -- class-wide type:
+ -- Ada 2012 (AI05-0030): Dispatching requeue to an interface primitive
+ -- marked by pragma Implemented (XXX, By_Entry).
+
+ -- The requeue is inside a protected entry:
-- procedure entE
-- (O : System.Address;
-- end;
-- end entE;
- -- Ada 2005 (AI05-0030): Dispatching requeue from task to interface
- -- class-wide type:
+ -- The requeue is inside a task entry:
- -- Accept_Call (E, Ann);
+ -- Accept_Call (E, Ann);
-- <start of statement sequence for accept statement>
-- _Disp_Requeue
-- (<interface class-wide object>,
-- when all others =>
-- Exceptional_Complete_Rendezvous (Get_GNAT_Exception);
- -- Further details on these expansions can be found in Expand_N_Protected_
- -- Body and Expand_N_Accept_Statement.
+ -- Ada 2012 (AI05-0030): Dispatching requeue to an interface primitive
+ -- marked by pragma Implemented (XXX, By_Protected_Procedure). The requeue
+ -- statement is replaced by a dispatching call with actual parameters taken
+ -- from the inner-most accept statement or entry body.
+
+ -- Target.Primitive (Param1, ..., ParamN);
+
+ -- Ada 2012 (AI05-0030): Dispatching requeue to an interface primitive
+ -- marked by pragma Implemented (XXX, By_Any) or not marked at all.
+
+ -- declare
+ -- S : constant Offset_Index :=
+ -- Get_Offset_Index (Tag (Concval), DT_Position (Ename));
+ -- C : constant Prim_Op_Kind := Get_Prim_Op_Kind (Tag (Concval), S);
+
+ -- begin
+ -- if C = POK_Protected_Entry
+ -- or else C = POK_Task_Entry
+ -- then
+ -- <statements for dispatching requeue>
+
+ -- elsif C = POK_Protected_Procedure then
+ -- <dispatching call equivalent>
+
+ -- else
+ -- raise Program_Error;
+ -- end if;
+ -- end;
procedure Expand_N_Requeue_Statement (N : Node_Id) is
- Loc : constant Source_Ptr := Sloc (N);
- Abortable : Node_Id;
- Acc_Stat : Node_Id;
- Conc_Typ : Entity_Id;
- Concval : Node_Id;
- Ename : Node_Id;
- Index : Node_Id;
- Lab_Node : Node_Id;
- New_Param : Node_Id;
- Old_Typ : Entity_Id;
- Params : List_Id;
- Rcall : Node_Id;
- RTS_Call : Entity_Id;
- Self_Param : Node_Id;
- Skip_Stat : Node_Id;
+ Loc : constant Source_Ptr := Sloc (N);
+ Conc_Typ : Entity_Id;
+ Concval : Node_Id;
+ Ename : Node_Id;
+ Index : Node_Id;
+ Old_Typ : Entity_Id;
+
+ function Build_Dispatching_Call_Equivalent return Node_Id;
+ -- Ada 2012 (AI05-0030): N denotes a dispatching requeue statement of
+ -- the form Concval.Ename. It is statically known that Ename is allowed
+ -- to be implemented by a protected procedure. Create a dispatching call
+ -- equivalent of Concval.Ename taking the actual parameters from the
+ -- inner-most accept statement or entry body.
+
+ function Build_Dispatching_Requeue return Node_Id;
+ -- Ada 2012 (AI05-0030): N denotes a dispatching requeue statement of
+ -- the form Concval.Ename. It is statically known that Ename is allowed
+ -- to be implemented by a protected or a task entry. Create a call to
+ -- primitive _Disp_Requeue which handles the low-level actions.
+
+ function Build_Dispatching_Requeue_To_Any return Node_Id;
+ -- Ada 2012 (AI05-0030): N denotes a dispatching requeue statement of
+ -- the form Concval.Ename. Ename is either marked by pragma Implemented
+ -- (XXX, By_Any) or not marked at all. Create a block which determines
+ -- at runtime whether Ename denotes an entry or a procedure and perform
+ -- the appropriate kind of dispatching select.
+
+ function Build_Normal_Requeue return Node_Id;
+ -- N denotes a non-dispatching requeue statement to either a task or a
+ -- protected entry. Build the appropriate runtime call to perform the
+ -- action.
+
+ function Build_Skip_Statement (Search : Node_Id) return Node_Id;
+ -- For a protected entry, create a return statement to skip the rest of
+ -- the entry body. Otherwise, create a goto statement to skip the rest
+ -- of a task accept statement. The lookup for the enclosing entry body
+ -- or accept statement starts from Search.
- begin
- Abortable :=
- New_Occurrence_Of (Boolean_Literals (Abort_Present (N)), Loc);
+ ---------------------------------------
+ -- Build_Dispatching_Call_Equivalent --
+ ---------------------------------------
- -- Extract the components of the entry call
+ function Build_Dispatching_Call_Equivalent return Node_Id is
+ Call_Ent : constant Entity_Id := Entity (Ename);
+ Obj : constant Node_Id := Original_Node (Concval);
+ Acc_Ent : Node_Id;
+ Actuals : List_Id;
+ Formal : Node_Id;
+ Formals : List_Id;
- Extract_Entry (N, Concval, Ename, Index);
- Conc_Typ := Etype (Concval);
+ begin
+ -- Climb the parent chain looking for the inner-most entry body or
+ -- accept statement.
- -- Examine the scope stack in order to find nearest enclosing protected
- -- or task type. This will constitute our invocation source.
+ Acc_Ent := N;
+ while Present (Acc_Ent)
+ and then not Nkind_In (Acc_Ent, N_Accept_Statement,
+ N_Entry_Body)
+ loop
+ Acc_Ent := Parent (Acc_Ent);
+ end loop;
- Old_Typ := Current_Scope;
- while Present (Old_Typ)
- and then not Is_Protected_Type (Old_Typ)
- and then not Is_Task_Type (Old_Typ)
- loop
- Old_Typ := Scope (Old_Typ);
- end loop;
+ -- A requeue statement should be housed inside an entry body or an
+ -- accept statement at some level. If this is not the case, then the
+ -- tree is malformed.
- -- Generate the parameter list for all cases. The abortable flag is
- -- common among dispatching and regular requeue.
+ pragma Assert (Present (Acc_Ent));
- Params := New_List (Abortable);
+ -- Recover the list of formal parameters
- -- Ada 2005 (AI05-0030): We have a dispatching requeue of the form
- -- Concval.Ename where the type of Concval is class-wide concurrent
- -- interface.
+ if Nkind (Acc_Ent) = N_Entry_Body then
+ Acc_Ent := Entry_Body_Formal_Part (Acc_Ent);
+ end if;
- if Ada_Version >= Ada_05
- and then Present (Concval)
- and then Is_Class_Wide_Type (Conc_Typ)
- and then Is_Concurrent_Interface (Conc_Typ)
- then
- RTS_Call := Make_Identifier (Loc, Name_uDisp_Requeue);
+ Formals := Parameter_Specifications (Acc_Ent);
+
+ -- Create the actual parameters for the dispatching call. These are
+ -- simply copies of the entry body or accept statement formals in the
+ -- same order as they appear.
+
+ Actuals := No_List;
+
+ if Present (Formals) then
+ Actuals := New_List;
+ Formal := First (Formals);
+ while Present (Formal) loop
+ Append_To (Actuals,
+ Make_Identifier (Loc, Chars (Defining_Identifier (Formal))));
+ Next (Formal);
+ end loop;
+ end if;
-- Generate:
+ -- Obj.Call_Ent (Actuals);
+
+ return
+ Make_Procedure_Call_Statement (Loc,
+ Name =>
+ Make_Selected_Component (Loc,
+ Prefix => Make_Identifier (Loc, Chars (Obj)),
+ Selector_Name => Make_Identifier (Loc, Chars (Call_Ent))),
+
+ Parameter_Associations => Actuals);
+ end Build_Dispatching_Call_Equivalent;
+
+ -------------------------------
+ -- Build_Dispatching_Requeue --
+ -------------------------------
+
+ function Build_Dispatching_Requeue return Node_Id is
+ Params : constant List_Id := New_List;
+
+ begin
+ -- Process the "with abort" parameter
+
+ Prepend_To (Params,
+ New_Reference_To (Boolean_Literals (Abort_Present (N)), Loc));
+
+ -- Process the entry wrapper's position in the primary dispatch
+ -- table parameter. Generate:
+
-- Ada.Tags.Get_Offset_Index
-- (Ada.Tags.Tag (Concval),
-- <interface dispatch table position of Ename>)
- Prepend_To (Params,
- Make_Function_Call (Loc,
- Name =>
- New_Reference_To (RTE (RE_Get_Offset_Index), Loc),
- Parameter_Associations =>
- New_List (
- Unchecked_Convert_To (RTE (RE_Tag), Concval),
- Make_Integer_Literal (Loc, DT_Position (Entity (Ename))))));
+ if Tagged_Type_Expansion then
+ Prepend_To (Params,
+ Make_Function_Call (Loc,
+ Name => New_Reference_To (RTE (RE_Get_Offset_Index), Loc),
+ Parameter_Associations => New_List (
+ Unchecked_Convert_To (RTE (RE_Tag), Concval),
+ Make_Integer_Literal (Loc, DT_Position (Entity (Ename))))));
+
+ -- VM targets
+
+ else
+ Prepend_To (Params,
+ Make_Function_Call (Loc,
+ Name => New_Reference_To (RTE (RE_Get_Offset_Index), Loc),
+
+ Parameter_Associations => New_List (
+
+ -- Obj_Typ
+
+ Make_Attribute_Reference (Loc,
+ Prefix => Concval,
+ Attribute_Name => Name_Tag),
- -- Specific actuals for protected to interface class-wide type
- -- requeue.
+ -- Tag_Typ
+
+ Make_Attribute_Reference (Loc,
+ Prefix => New_Reference_To (Etype (Concval), Loc),
+ Attribute_Name => Name_Tag),
+
+ -- Position
+
+ Make_Integer_Literal (Loc, DT_Position (Entity (Ename))))));
+ end if;
+
+ -- Specific actuals for protected to XXX requeue
if Is_Protected_Type (Old_Typ) then
Prepend_To (Params,
Make_Attribute_Reference (Loc, -- _object'Address
Prefix =>
Concurrent_Ref (New_Occurrence_Of (Old_Typ, Loc)),
- Attribute_Name =>
- Name_Address));
+ Attribute_Name => Name_Address));
+
Prepend_To (Params, -- True
New_Reference_To (Standard_True, Loc));
- -- Specific actuals for task to interface class-wide type requeue
+ -- Specific actuals for task to XXX requeue
else
pragma Assert (Is_Task_Type (Old_Typ));
Prepend_To (Params, -- null
New_Reference_To (RTE (RE_Null_Address), Loc));
+
Prepend_To (Params, -- False
New_Reference_To (Standard_False, Loc));
end if;
- -- Finally, add the common object parameter
+ -- Add the object parameter
Prepend_To (Params, New_Copy_Tree (Concval));
- -- Regular requeue processing
+ -- Generate:
+ -- _Disp_Requeue (<Params>);
- else
- New_Param := Concurrent_Ref (Concval);
+ return
+ Make_Procedure_Call_Statement (Loc,
+ Name => Make_Identifier (Loc, Name_uDisp_Requeue),
+ Parameter_Associations => Params);
+ end Build_Dispatching_Requeue;
+
+ --------------------------------------
+ -- Build_Dispatching_Requeue_To_Any --
+ --------------------------------------
+
+ function Build_Dispatching_Requeue_To_Any return Node_Id is
+ Call_Ent : constant Entity_Id := Entity (Ename);
+ Obj : constant Node_Id := Original_Node (Concval);
+ Skip : constant Node_Id := Build_Skip_Statement (N);
+ C : Entity_Id;
+ Decls : List_Id;
+ S : Entity_Id;
+ Stmts : List_Id;
+
+ begin
+ Decls := New_List;
+ Stmts := New_List;
+
+ -- Dispatch table slot processing, generate:
+ -- S : Integer;
+
+ S := Build_S (Loc, Decls);
+
+ -- Call kind processing, generate:
+ -- C : Ada.Tags.Prim_Op_Kind;
+
+ C := Build_C (Loc, Decls);
+
+ -- Generate:
+ -- S := Ada.Tags.Get_Offset_Index
+ -- (Ada.Tags.Tag (Obj), DT_Position (Call_Ent));
+
+ Append_To (Stmts, Build_S_Assignment (Loc, S, Obj, Call_Ent));
+
+ -- Generate:
+ -- _Disp_Get_Prim_Op_Kind (Obj, S, C);
+
+ Append_To (Stmts,
+ Make_Procedure_Call_Statement (Loc,
+ Name =>
+ New_Reference_To (
+ Find_Prim_Op (Etype (Etype (Obj)),
+ Name_uDisp_Get_Prim_Op_Kind),
+ Loc),
+ Parameter_Associations => New_List (
+ New_Copy_Tree (Obj),
+ New_Reference_To (S, Loc),
+ New_Reference_To (C, Loc))));
+
+ Append_To (Stmts,
+
+ -- if C = POK_Protected_Entry
+ -- or else C = POK_Task_Entry
+ -- then
- -- The index expression is common among all four cases
+ Make_If_Statement (Loc,
+ Condition =>
+ Make_Op_Or (Loc,
+ Left_Opnd =>
+ Make_Op_Eq (Loc,
+ Left_Opnd =>
+ New_Reference_To (C, Loc),
+ Right_Opnd =>
+ New_Reference_To (RTE (RE_POK_Protected_Entry), Loc)),
+
+ Right_Opnd =>
+ Make_Op_Eq (Loc,
+ Left_Opnd =>
+ New_Reference_To (C, Loc),
+ Right_Opnd =>
+ New_Reference_To (RTE (RE_POK_Task_Entry), Loc))),
+
+ -- Dispatching requeue equivalent
+
+ Then_Statements => New_List (
+ Build_Dispatching_Requeue,
+ Skip),
+
+ -- elsif C = POK_Protected_Procedure then
+
+ Elsif_Parts => New_List (
+ Make_Elsif_Part (Loc,
+ Condition =>
+ Make_Op_Eq (Loc,
+ Left_Opnd =>
+ New_Reference_To (C, Loc),
+ Right_Opnd =>
+ New_Reference_To (
+ RTE (RE_POK_Protected_Procedure), Loc)),
+
+ -- Dispatching call equivalent
+
+ Then_Statements => New_List (
+ Build_Dispatching_Call_Equivalent))),
+
+ -- else
+ -- raise Program_Error;
+ -- end if;
+
+ Else_Statements => New_List (
+ Make_Raise_Program_Error (Loc,
+ Reason => PE_Explicit_Raise))));
+
+ -- Wrap everything into a block
+
+ return
+ Make_Block_Statement (Loc,
+ Declarations => Decls,
+ Handled_Statement_Sequence =>
+ Make_Handled_Sequence_Of_Statements (Loc,
+ Statements => Stmts));
+ end Build_Dispatching_Requeue_To_Any;
+
+ --------------------------
+ -- Build_Normal_Requeue --
+ --------------------------
+
+ function Build_Normal_Requeue return Node_Id is
+ Params : constant List_Id := New_List;
+ Param : Node_Id;
+ RT_Call : Node_Id;
+
+ begin
+ -- Process the "with abort" parameter
Prepend_To (Params,
- Entry_Index_Expression (Loc, Entity (Ename), Index, Conc_Typ));
+ New_Reference_To (Boolean_Literals (Abort_Present (N)), Loc));
- if Is_Protected_Type (Old_Typ) then
- Self_Param :=
- Make_Attribute_Reference (Loc,
- Prefix =>
- Concurrent_Ref (New_Occurrence_Of (Old_Typ, Loc)),
- Attribute_Name =>
- Name_Unchecked_Access);
+ -- Add the index expression to the parameters. It is common among all
+ -- four cases.
- -- Protected to protected requeue
+ Prepend_To (Params,
+ Entry_Index_Expression (Loc, Entity (Ename), Index, Conc_Typ));
- if Is_Protected_Type (Conc_Typ) then
- RTS_Call :=
- New_Reference_To (RTE (RE_Requeue_Protected_Entry), Loc);
+ if Is_Protected_Type (Old_Typ) then
+ declare
+ Self_Param : Node_Id;
- New_Param :=
+ begin
+ Self_Param :=
Make_Attribute_Reference (Loc,
Prefix =>
- New_Param,
+ Concurrent_Ref (New_Occurrence_Of (Old_Typ, Loc)),
Attribute_Name =>
Name_Unchecked_Access);
- -- Protected to task requeue
+ -- Protected to protected requeue
- else
- pragma Assert (Is_Task_Type (Conc_Typ));
- RTS_Call :=
- New_Reference_To (
- RTE (RE_Requeue_Protected_To_Task_Entry), Loc);
- end if;
+ if Is_Protected_Type (Conc_Typ) then
+ RT_Call :=
+ New_Reference_To (
+ RTE (RE_Requeue_Protected_Entry), Loc);
+
+ Param :=
+ Make_Attribute_Reference (Loc,
+ Prefix =>
+ Concurrent_Ref (Concval),
+ Attribute_Name =>
+ Name_Unchecked_Access);
- Prepend (New_Param, Params);
- Prepend (Self_Param, Params);
+ -- Protected to task requeue
- else
- pragma Assert (Is_Task_Type (Old_Typ));
+ else pragma Assert (Is_Task_Type (Conc_Typ));
+ RT_Call :=
+ New_Reference_To (
+ RTE (RE_Requeue_Protected_To_Task_Entry), Loc);
+
+ Param := Concurrent_Ref (Concval);
+ end if;
+
+ Prepend_To (Params, Param);
+ Prepend_To (Params, Self_Param);
+ end;
+
+ else pragma Assert (Is_Task_Type (Old_Typ));
-- Task to protected requeue
if Is_Protected_Type (Conc_Typ) then
- RTS_Call :=
+ RT_Call :=
New_Reference_To (
RTE (RE_Requeue_Task_To_Protected_Entry), Loc);
- New_Param :=
+ Param :=
Make_Attribute_Reference (Loc,
Prefix =>
- New_Param,
+ Concurrent_Ref (Concval),
Attribute_Name =>
Name_Unchecked_Access);
-- Task to task requeue
- else
- pragma Assert (Is_Task_Type (Conc_Typ));
- RTS_Call :=
+ else pragma Assert (Is_Task_Type (Conc_Typ));
+ RT_Call :=
New_Reference_To (RTE (RE_Requeue_Task_Entry), Loc);
+
+ Param := Concurrent_Ref (Concval);
end if;
- Prepend (New_Param, Params);
+ Prepend_To (Params, Param);
end if;
- end if;
- -- Create the GNARLI or predefined primitive call
-
- Rcall :=
- Make_Procedure_Call_Statement (Loc,
- Name => RTS_Call,
- Parameter_Associations => Params);
+ return
+ Make_Procedure_Call_Statement (Loc,
+ Name => RT_Call,
+ Parameter_Associations => Params);
+ end Build_Normal_Requeue;
- Rewrite (N, Rcall);
- Analyze (N);
+ --------------------------
+ -- Build_Skip_Statement --
+ --------------------------
- if Is_Protected_Type (Old_Typ) then
+ function Build_Skip_Statement (Search : Node_Id) return Node_Id is
+ Skip_Stmt : Node_Id;
- -- Build the return statement to skip the rest of the entry body
+ begin
+ -- Build a return statement to skip the rest of the entire body
- Skip_Stat := Make_Simple_Return_Statement (Loc);
+ if Is_Protected_Type (Old_Typ) then
+ Skip_Stmt := Make_Simple_Return_Statement (Loc);
- else
-- If the requeue is within a task, find the end label of the
- -- enclosing accept statement.
+ -- enclosing accept statement and create a goto statement to it.
- Acc_Stat := Parent (N);
- while Nkind (Acc_Stat) /= N_Accept_Statement loop
- Acc_Stat := Parent (Acc_Stat);
- end loop;
+ else
+ declare
+ Acc : Node_Id;
+ Label : Node_Id;
- -- The last statement is the second label, used for completing the
- -- rendezvous the usual way. The label we are looking for is right
- -- before it.
+ begin
+ -- Climb the parent chain looking for the enclosing accept
+ -- statement.
+
+ Acc := Parent (Search);
+ while Present (Acc)
+ and then Nkind (Acc) /= N_Accept_Statement
+ loop
+ Acc := Parent (Acc);
+ end loop;
- Lab_Node :=
- Prev (Last (Statements (Handled_Statement_Sequence (Acc_Stat))));
+ -- The last statement is the second label used for completing
+ -- the rendezvous the usual way. The label we are looking for
+ -- is right before it.
- pragma Assert (Nkind (Lab_Node) = N_Label);
+ Label :=
+ Prev (Last (Statements (Handled_Statement_Sequence (Acc))));
- -- Build the goto statement to skip the rest of the accept
- -- statement.
+ pragma Assert (Nkind (Label) = N_Label);
- Skip_Stat :=
- Make_Goto_Statement (Loc,
- Name => New_Occurrence_Of (Entity (Identifier (Lab_Node)), Loc));
- end if;
+ -- Generate a goto statement to skip the rest of the accept
+
+ Skip_Stmt :=
+ Make_Goto_Statement (Loc,
+ Name =>
+ New_Occurrence_Of (Entity (Identifier (Label)), Loc));
+ end;
+ end if;
+
+ Set_Analyzed (Skip_Stmt);
+
+ return Skip_Stmt;
+ end Build_Skip_Statement;
+
+ -- Start of processing for Expand_N_Requeue_Statement
+
+ begin
+ -- Extract the components of the entry call
+
+ Extract_Entry (N, Concval, Ename, Index);
+ Conc_Typ := Etype (Concval);
+
+ -- Examine the scope stack in order to find nearest enclosing protected
+ -- or task type. This will constitute our invocation source.
+
+ Old_Typ := Current_Scope;
+ while Present (Old_Typ)
+ and then not Is_Protected_Type (Old_Typ)
+ and then not Is_Task_Type (Old_Typ)
+ loop
+ Old_Typ := Scope (Old_Typ);
+ end loop;
+
+ -- Ada 2012 (AI05-0030): We have a dispatching requeue of the form
+ -- Concval.Ename where the type of Concval is class-wide concurrent
+ -- interface.
+
+ if Ada_Version >= Ada_2012
+ and then Present (Concval)
+ and then Is_Class_Wide_Type (Conc_Typ)
+ and then Is_Concurrent_Interface (Conc_Typ)
+ then
+ declare
+ Has_Impl : Boolean := False;
+ Impl_Kind : Name_Id := No_Name;
+
+ begin
+ -- Check whether the Ename is flagged by pragma Implemented
+
+ if Has_Rep_Pragma (Entity (Ename), Name_Implemented) then
+ Has_Impl := True;
+ Impl_Kind := Implementation_Kind (Entity (Ename));
+ end if;
+
+ -- The procedure_or_entry_NAME is guaranteed to be overridden by
+ -- an entry. Create a call to predefined primitive _Disp_Requeue.
+
+ if Has_Impl
+ and then Impl_Kind = Name_By_Entry
+ then
+ Rewrite (N, Build_Dispatching_Requeue);
+ Analyze (N);
+ Insert_After (N, Build_Skip_Statement (N));
+
+ -- The procedure_or_entry_NAME is guaranteed to be overridden by
+ -- a protected procedure. In this case the requeue is transformed
+ -- into a dispatching call.
+
+ elsif Has_Impl
+ and then Impl_Kind = Name_By_Protected_Procedure
+ then
+ Rewrite (N, Build_Dispatching_Call_Equivalent);
+ Analyze (N);
+
+ -- The procedure_or_entry_NAME's implementation kind is either
+ -- By_Any or pragma Implemented was not applied at all. In this
+ -- case a runtime test determines whether Ename denotes an entry
+ -- or a protected procedure and performs the appropriate call.
+
+ else
+ Rewrite (N, Build_Dispatching_Requeue_To_Any);
+ Analyze (N);
+ end if;
+ end;
- Set_Analyzed (Skip_Stat);
+ -- Processing for regular (non-dispatching) requeues
- Insert_After (N, Skip_Stat);
+ else
+ Rewrite (N, Build_Normal_Requeue);
+ Analyze (N);
+ Insert_After (N, Build_Skip_Statement (N));
+ end if;
end Expand_N_Requeue_Statement;
-------------------------------
Cond := Make_Op_Ne (Loc,
Left_Opnd =>
Make_Selected_Component (Loc,
- Prefix => Make_Indexed_Component (Loc,
- Prefix => New_Reference_To (Qnam, Loc),
- Expressions => New_List (New_Reference_To (J, Loc))),
- Selector_Name => Make_Identifier (Loc, Name_S)),
+ Prefix =>
+ Make_Indexed_Component (Loc,
+ Prefix => New_Reference_To (Qnam, Loc),
+ Expressions => New_List (New_Reference_To (J, Loc))),
+ Selector_Name => Make_Identifier (Loc, Name_S)),
Right_Opnd =>
New_Reference_To (RTE (RE_Null_Task_Entry), Loc));
-- Start of processing for Expand_N_Selective_Accept
begin
+ Process_Statements_For_Controlled_Objects (N);
+
-- First insert some declarations before the select. The first is:
-- Ann : Address
Alt := First (Alts);
while Present (Alt) loop
+ Process_Statements_For_Controlled_Objects (Alt);
if Nkind (Alt) = N_Accept_Alternative then
Add_Accept (Alt);
-- the task body. At this point all wrapper specs have been created,
-- frozen and included in the dispatch table for the task type.
- if Ada_Version >= Ada_05 then
+ if Ada_Version >= Ada_2005 then
if Nkind (Parent (N)) = N_Subunit then
Insert_Nod := Corresponding_Stub (Parent (N));
else
-- values of this task. The general form of this type declaration is
-- type taskV (discriminants) is record
- -- _Task_Id : Task_Id;
- -- entry_family : array (bounds) of Void;
- -- _Priority : Integer := priority_expression;
- -- _Size : Size_Type := Size_Type (size_expression);
- -- _Task_Info : Task_Info_Type := task_info_expression;
+ -- _Task_Id : Task_Id;
+ -- entry_family : array (bounds) of Void;
+ -- _Priority : Integer := priority_expression;
+ -- _Size : Size_Type := size_expression;
+ -- _Task_Info : Task_Info_Type := task_info_expression;
+ -- _CPU : Integer := cpu_range_expression;
+ -- _Relative_Deadline : Time_Span := time_span_expression;
+ -- _Domain : Dispatching_Domain := dd_expression;
-- end record;
-- The discriminants are present only if the corresponding task type has
-- present in the pragma, and is used to provide the Task_Image parameter
-- to the call to Create_Task.
+ -- The _CPU field is present only if a CPU pragma appears in the task
+ -- definition. The expression captures the argument that was present in
+ -- the pragma, and is used to provide the CPU parameter to the call to
+ -- Create_Task.
+
-- The _Relative_Deadline field is present only if a Relative_Deadline
-- pragma appears in the task definition. The expression captures the
-- argument that was present in the pragma, and is used to provide the
-- Relative_Deadline parameter to the call to Create_Task.
+ -- The _Domain field is present only if a Dispatching_Domain pragma or
+ -- aspect appears in the task definition. The expression captures the
+ -- argument that was present in the pragma or aspect, and is used to
+ -- provide the Dispatching_Domain parameter to the call to Create_Task.
+
-- When a task is declared, an instance of the task value record is
-- created. The elaboration of this declaration creates the correct bounds
-- for the entry families, and also evaluates the size, priority, and
Make_Defining_Identifier (Sloc (Tasktyp),
Chars => New_External_Name (Tasknm, 'Z')));
- if Present (Taskdef) and then Has_Storage_Size_Pragma (Taskdef) and then
- Is_Static_Expression (Expression (First (
- Pragma_Argument_Associations (Find_Task_Or_Protected_Pragma (
- Taskdef, Name_Storage_Size)))))
+ if Present (Taskdef)
+ and then Has_Storage_Size_Pragma (Taskdef)
+ and then
+ Is_Static_Expression
+ (Expression
+ (First (Pragma_Argument_Associations
+ (Find_Task_Or_Protected_Pragma
+ (Taskdef, Name_Storage_Size)))))
then
Size_Decl :=
Make_Object_Declaration (Loc,
Defining_Identifier => Storage_Size_Variable (Tasktyp),
- Object_Definition => New_Reference_To (RTE (RE_Size_Type), Loc),
- Expression =>
+ Object_Definition => New_Reference_To (RTE (RE_Size_Type), Loc),
+ Expression =>
Convert_To (RTE (RE_Size_Type),
- Relocate_Node (
- Expression (First (
- Pragma_Argument_Associations (
- Find_Task_Or_Protected_Pragma
- (Taskdef, Name_Storage_Size)))))));
+ Relocate_Node
+ (Expression (First (Pragma_Argument_Associations
+ (Find_Task_Or_Protected_Pragma
+ (Taskdef, Name_Storage_Size)))))));
else
Size_Decl :=
Make_Object_Declaration (Loc,
Defining_Identifier => Storage_Size_Variable (Tasktyp),
- Object_Definition => New_Reference_To (RTE (RE_Size_Type), Loc),
- Expression => New_Reference_To (RTE (RE_Unspecified_Size), Loc));
+ Object_Definition =>
+ New_Reference_To (RTE (RE_Size_Type), Loc),
+ Expression =>
+ New_Reference_To (RTE (RE_Unspecified_Size), Loc));
end if;
Insert_After (Elab_Decl, Size_Decl);
Append_To (Cdecls,
Make_Component_Declaration (Loc,
- Defining_Identifier =>
+ Defining_Identifier =>
Make_Defining_Identifier (Loc, Name_uTask_Id),
Component_Definition =>
Make_Component_Definition (Loc,
Make_Component_Definition (Loc,
Aliased_Present => True,
Subtype_Indication => Make_Subtype_Indication (Loc,
- Subtype_Mark => New_Occurrence_Of
- (RTE (RE_Ada_Task_Control_Block), Loc),
+ Subtype_Mark =>
+ New_Occurrence_Of (RTE (RE_Ada_Task_Control_Block), Loc),
Constraint =>
Make_Index_Or_Discriminant_Constraint (Loc,
-- Add the _Priority component if a Priority pragma is present
- if Present (Taskdef) and then Has_Priority_Pragma (Taskdef) then
+ if Present (Taskdef) and then Has_Pragma_Priority (Taskdef) then
declare
Prag : constant Node_Id :=
Find_Task_Or_Protected_Pragma (Taskdef, Name_Priority);
(Taskdef, Name_Task_Info)))))));
end if;
+ -- Add the _CPU component if a CPU pragma is present
+
+ if Present (Taskdef) and then Has_Pragma_CPU (Taskdef) then
+ Append_To (Cdecls,
+ Make_Component_Declaration (Loc,
+ Defining_Identifier =>
+ Make_Defining_Identifier (Loc, Name_uCPU),
+
+ Component_Definition =>
+ Make_Component_Definition (Loc,
+ Aliased_Present => False,
+ Subtype_Indication =>
+ New_Reference_To (RTE (RE_CPU_Range), Loc)),
+
+ Expression => New_Copy (
+ Expression (First (
+ Pragma_Argument_Associations (
+ Find_Task_Or_Protected_Pragma
+ (Taskdef, Name_CPU)))))));
+ end if;
+
-- Add the _Relative_Deadline component if a Relative_Deadline pragma is
-- present. If we are using a restricted run time this component will
-- not be added (deadlines are not allowed by the Ravenscar profile).
(Taskdef, Name_Relative_Deadline))))))));
end if;
+ -- Add the _Dispatching_Domain component if a Dispatching_Domain pragma
+ -- or aspect is present. If we are using a restricted run time this
+ -- component will not be added (dispatching domains are not allowed by
+ -- the Ravenscar profile).
+
+ if not Restricted_Profile
+ and then Present (Taskdef)
+ and then Has_Pragma_Dispatching_Domain (Taskdef)
+ then
+ Append_To (Cdecls,
+ Make_Component_Declaration (Loc,
+ Defining_Identifier =>
+ Make_Defining_Identifier (Loc, Name_uDispatching_Domain),
+
+ Component_Definition =>
+ Make_Component_Definition (Loc,
+ Aliased_Present => False,
+ Subtype_Indication =>
+ New_Reference_To
+ (RTE (RE_Dispatching_Domain_Access), Loc)),
+
+ Expression =>
+ Unchecked_Convert_To (RTE (RE_Dispatching_Domain_Access),
+ Relocate_Node
+ (Expression
+ (First
+ (Pragma_Argument_Associations
+ (Find_Task_Or_Protected_Pragma
+ (Taskdef, Name_Dispatching_Domain))))))));
+ end if;
+
Insert_After (Size_Decl, Rec_Decl);
-- Analyze the record declaration immediately after construction,
-- Ada 2005 (AI-345): Construct the primitive entry wrapper specs before
-- the corresponding record has been frozen.
- if Ada_Version >= Ada_05 then
+ if Ada_Version >= Ada_2005 then
Build_Wrapper_Specs (Loc, Tasktyp, Rec_Decl);
end if;
-- in time if we don't freeze now.
declare
- L : constant List_Id := Freeze_Entity (Rec_Ent, Loc);
+ L : constant List_Id := Freeze_Entity (Rec_Ent, N);
begin
if Is_Non_Empty_List (L) then
Insert_List_After (Body_Decl, L);
-- any were declared.
Expand_Previous_Access_Type (Tasktyp);
+
+ -- Create wrappers for entries that have pre/postconditions
+
+ declare
+ Ent : Entity_Id;
+
+ begin
+ Ent := First_Entity (Tasktyp);
+ while Present (Ent) loop
+ if Ekind_In (Ent, E_Entry, E_Entry_Family)
+ and then Present (Spec_PPC_List (Contract (Ent)))
+ then
+ Build_PPC_Wrapper (Ent, N);
+ end if;
+
+ Next_Entity (Ent);
+ end loop;
+ end;
end Expand_N_Task_Type_Declaration;
-------------------------------
-- Ada.Tags.Get_Tagged_Kind (Ada.Tags.Tag (<object>));
-- M : Integer :=...;
-- P : Parameters := (Param1 .. ParamN);
- -- S : Iteger;
+ -- S : Integer;
-- begin
-- if K = Ada.Tags.TK_Limited_Tagged then
-- end if;
-- end;
+ -- The triggering statement and the sequence of timed statements have not
+ -- been analyzed yet (see Analyzed_Timed_Entry_Call). They may contain
+ -- local declarations, and therefore the copies that are made during
+ -- expansion must be disjoint, as for any other inlining.
+
procedure Expand_N_Timed_Entry_Call (N : Node_Id) is
Loc : constant Source_Ptr := Sloc (N);
return;
end if;
+ Process_Statements_For_Controlled_Objects (Entry_Call_Alternative (N));
+ Process_Statements_For_Controlled_Objects (Delay_Alternative (N));
+
-- The arguments in the call may require dynamic allocation, and the
-- call statement may have been transformed into a block. The block
-- may contain additional declarations for internal entities, and the
end if;
Is_Disp_Select :=
- Ada_Version >= Ada_05
+ Ada_Version >= Ada_2005
and then Nkind (E_Call) = N_Procedure_Call_Statement;
if Is_Disp_Select then
Prepend_To (Decls,
Make_Object_Declaration (Loc,
- Defining_Identifier =>
- B,
- Object_Definition =>
- New_Reference_To (Standard_Boolean, Loc)));
+ Defining_Identifier => B,
+ Object_Definition => New_Reference_To (Standard_Boolean, Loc)));
end if;
-- Duration and mode processing
elsif Is_RTE (D_Type, RO_CA_Time) then
D_Disc := Make_Integer_Literal (Loc, 1);
- D_Conv := Make_Function_Call (Loc,
- New_Reference_To (RTE (RO_CA_To_Duration), Loc),
- New_List (New_Copy (Expression (D_Stat))));
+ D_Conv :=
+ Make_Function_Call (Loc,
+ Name => New_Reference_To (RTE (RO_CA_To_Duration), Loc),
+ Parameter_Associations =>
+ New_List (New_Copy (Expression (D_Stat))));
else pragma Assert (Is_RTE (D_Type, RO_RT_Time));
D_Disc := Make_Integer_Literal (Loc, 2);
- D_Conv := Make_Function_Call (Loc,
- New_Reference_To (RTE (RO_RT_To_Duration), Loc),
- New_List (New_Copy (Expression (D_Stat))));
+ D_Conv :=
+ Make_Function_Call (Loc,
+ Name => New_Reference_To (RTE (RO_RT_To_Duration), Loc),
+ Parameter_Associations =>
+ New_List (New_Copy (Expression (D_Stat))));
end if;
D := Make_Temporary (Loc, 'D');
Append_To (Decls,
Make_Object_Declaration (Loc,
- Defining_Identifier =>
- D,
- Object_Definition =>
- New_Reference_To (Standard_Duration, Loc)));
+ Defining_Identifier => D,
+ Object_Definition => New_Reference_To (Standard_Duration, Loc)));
M := Make_Temporary (Loc, 'M');
Append_To (Decls,
Make_Object_Declaration (Loc,
- Defining_Identifier =>
- M,
- Object_Definition =>
- New_Reference_To (Standard_Integer, Loc),
- Expression =>
- D_Disc));
+ Defining_Identifier => M,
+ Object_Definition => New_Reference_To (Standard_Integer, Loc),
+ Expression => D_Disc));
-- Do the assignment at this stage only because the evaluation of the
-- expression must not occur before (see ACVC C97302A).
Append_To (Stmts,
Make_Assignment_Statement (Loc,
- Name =>
- New_Reference_To (D, Loc),
- Expression =>
- D_Conv));
+ Name => New_Reference_To (D, Loc),
+ Expression => D_Conv));
-- Parameter block processing
K := Build_K (Loc, Decls, Obj);
Blk_Typ := Build_Parameter_Block (Loc, Actuals, Formals, Decls);
- P := Parameter_Block_Pack
- (Loc, Blk_Typ, Actuals, Formals, Decls, Stmts);
+ P :=
+ Parameter_Block_Pack (Loc, Blk_Typ, Actuals, Formals, Decls, Stmts);
-- Dispatch table slot processing, generate:
-- S : Integer;
Append_To (Params, New_Copy_Tree (Obj));
Append_To (Params, New_Reference_To (S, Loc));
- Append_To (Params, Make_Attribute_Reference (Loc,
- Prefix => New_Reference_To (P, Loc),
- Attribute_Name => Name_Address));
+ Append_To (Params,
+ Make_Attribute_Reference (Loc,
+ Prefix => New_Reference_To (P, Loc),
+ Attribute_Name => Name_Address));
Append_To (Params, New_Reference_To (D, Loc));
Append_To (Params, New_Reference_To (M, Loc));
Append_To (Params, New_Reference_To (C, Loc));
Append_To (Conc_Typ_Stmts,
Make_Procedure_Call_Statement (Loc,
Name =>
- New_Reference_To (
- Find_Prim_Op (Etype (Etype (Obj)),
- Name_uDisp_Timed_Select),
- Loc),
- Parameter_Associations =>
- Params));
+ New_Reference_To
+ (Find_Prim_Op
+ (Etype (Etype (Obj)), Name_uDisp_Timed_Select), Loc),
+ Parameter_Associations => Params));
-- Generate:
-- if C = POK_Protected_Entry
Append_To (Conc_Typ_Stmts,
Make_If_Statement (Loc,
- Condition =>
+ Condition =>
Make_Or_Else (Loc,
- Left_Opnd =>
+ Left_Opnd =>
Make_Op_Eq (Loc,
- Left_Opnd =>
- New_Reference_To (C, Loc),
+ Left_Opnd => New_Reference_To (C, Loc),
Right_Opnd =>
- New_Reference_To (RTE (
- RE_POK_Protected_Entry), Loc)),
+ New_Reference_To
+ (RTE (RE_POK_Protected_Entry), Loc)),
+
Right_Opnd =>
Make_Op_Eq (Loc,
- Left_Opnd =>
- New_Reference_To (C, Loc),
+ Left_Opnd => New_Reference_To (C, Loc),
Right_Opnd =>
New_Reference_To (RTE (RE_POK_Task_Entry), Loc))),
- Then_Statements =>
- Unpack));
+ Then_Statements => Unpack));
end if;
-- Generate:
-- <timed-statements>
-- end if;
- N_Stats := New_Copy_List_Tree (E_Stats);
+ N_Stats := Copy_Separate_List (E_Stats);
Prepend_To (N_Stats,
Make_If_Statement (Loc,
Make_Or_Else (Loc,
Left_Opnd =>
Make_Op_Eq (Loc,
- Left_Opnd =>
- New_Reference_To (C, Loc),
+ Left_Opnd => New_Reference_To (C, Loc),
Right_Opnd =>
New_Reference_To (RTE (RE_POK_Procedure), Loc)),
+
Right_Opnd =>
Make_Or_Else (Loc,
Left_Opnd =>
Make_Op_Eq (Loc,
- Left_Opnd =>
- New_Reference_To (C, Loc),
+ Left_Opnd => New_Reference_To (C, Loc),
Right_Opnd =>
New_Reference_To (RTE (
RE_POK_Protected_Procedure), Loc)),
Right_Opnd =>
Make_Op_Eq (Loc,
- Left_Opnd =>
- New_Reference_To (C, Loc),
+ Left_Opnd => New_Reference_To (C, Loc),
Right_Opnd =>
- New_Reference_To (RTE (
- RE_POK_Task_Procedure), Loc)))),
+ New_Reference_To
+ (RTE (RE_POK_Task_Procedure), Loc)))),
- Then_Statements =>
- New_List (E_Call)));
+ Then_Statements => New_List (E_Call)));
Append_To (Conc_Typ_Stmts,
Make_If_Statement (Loc,
- Condition => New_Reference_To (B, Loc),
+ Condition => New_Reference_To (B, Loc),
Then_Statements => N_Stats,
Else_Statements => D_Stats));
-- <dispatching-call>;
-- <triggering-statements>
- Lim_Typ_Stmts := New_Copy_List_Tree (E_Stats);
+ Lim_Typ_Stmts := Copy_Separate_List (E_Stats);
Prepend_To (Lim_Typ_Stmts, New_Copy_Tree (E_Call));
-- Generate:
Append_To (Stmts,
Make_If_Statement (Loc,
- Condition =>
+ Condition =>
Make_Op_Eq (Loc,
- Left_Opnd =>
- New_Reference_To (K, Loc),
+ Left_Opnd => New_Reference_To (K, Loc),
Right_Opnd =>
New_Reference_To (RTE (RE_TK_Limited_Tagged), Loc)),
-
- Then_Statements =>
- Lim_Typ_Stmts,
-
- Else_Statements =>
- Conc_Typ_Stmts));
+ Then_Statements => Lim_Typ_Stmts,
+ Else_Statements => Conc_Typ_Stmts));
else
-- Skip assignments to temporaries created for in-out parameters.
Insert_Before (Stmt,
Make_Assignment_Statement (Loc,
- Name => New_Reference_To (D, Loc),
+ Name => New_Reference_To (D, Loc),
Expression => D_Conv));
Call := Stmt;
Rewrite (Call,
Make_Procedure_Call_Statement (Loc,
- Name => New_Reference_To (
- RTE (RE_Timed_Protected_Single_Entry_Call), Loc),
+ Name =>
+ New_Reference_To
+ (RTE (RE_Timed_Protected_Single_Entry_Call), Loc),
Parameter_Associations => Params));
when others =>
Append_To (Stmts,
Make_Implicit_If_Statement (N,
- Condition => New_Reference_To (B, Loc),
+ Condition => New_Reference_To (B, Loc),
Then_Statements => E_Stats,
Else_Statements => D_Stats));
end if;
Rewrite (N,
Make_Block_Statement (Loc,
- Declarations => Decls,
+ Declarations => Decls,
Handled_Statement_Sequence =>
Make_Handled_Sequence_Of_Statements (Loc, Stmts)));
Error_Msg_CRT ("protected body", N);
return;
- elsif Expander_Active then
+ elsif Full_Expander_Active then
-- Associate discriminals with the first subprogram or entry body to
-- be expanded.
if Present (Original_Node (Object)) then
Object := Original_Node (Object);
end if;
+
+ -- If the type of the dispatching object is an access type then return
+ -- an explicit dereference.
+
+ if Is_Access_Type (Etype (Object)) then
+ Object := Make_Explicit_Dereference (Sloc (N), Object);
+ Analyze (Object);
+ end if;
end Extract_Dispatching_Call;
-------------------
Make_Integer_Literal (Loc, 0)));
end Family_Size;
+ ----------------------------
+ -- Find_Enclosing_Context --
+ ----------------------------
+
+ procedure Find_Enclosing_Context
+ (N : Node_Id;
+ Context : out Node_Id;
+ Context_Id : out Entity_Id;
+ Context_Decls : out List_Id)
+ is
+ begin
+ -- Traverse the parent chain looking for an enclosing body, block,
+ -- package or return statement.
+
+ Context := Parent (N);
+ while not Nkind_In (Context, N_Block_Statement,
+ N_Entry_Body,
+ N_Extended_Return_Statement,
+ N_Package_Body,
+ N_Package_Declaration,
+ N_Subprogram_Body,
+ N_Task_Body)
+ loop
+ Context := Parent (Context);
+ end loop;
+
+ -- Extract the constituents of the context
+
+ if Nkind (Context) = N_Extended_Return_Statement then
+ Context_Decls := Return_Object_Declarations (Context);
+ Context_Id := Return_Statement_Entity (Context);
+
+ -- Package declarations and bodies use a common library-level activation
+ -- chain or task master, therefore return the package declaration as the
+ -- proper carrier for the appropriate flag.
+
+ elsif Nkind (Context) = N_Package_Body then
+ Context_Decls := Declarations (Context);
+ Context_Id := Corresponding_Spec (Context);
+ Context := Parent (Context_Id);
+
+ if Nkind (Context) = N_Defining_Program_Unit_Name then
+ Context := Parent (Parent (Context));
+ else
+ Context := Parent (Context);
+ end if;
+
+ elsif Nkind (Context) = N_Package_Declaration then
+ Context_Decls := Visible_Declarations (Specification (Context));
+ Context_Id := Defining_Unit_Name (Specification (Context));
+
+ if Nkind (Context_Id) = N_Defining_Program_Unit_Name then
+ Context_Id := Defining_Identifier (Context_Id);
+ end if;
+
+ else
+ Context_Decls := Declarations (Context);
+
+ if Nkind (Context) = N_Block_Statement then
+ Context_Id := Entity (Identifier (Context));
+
+ elsif Nkind (Context) = N_Entry_Body then
+ Context_Id := Defining_Identifier (Context);
+
+ elsif Nkind (Context) = N_Subprogram_Body then
+ if Present (Corresponding_Spec (Context)) then
+ Context_Id := Corresponding_Spec (Context);
+ else
+ Context_Id := Defining_Unit_Name (Specification (Context));
+
+ if Nkind (Context_Id) = N_Defining_Program_Unit_Name then
+ Context_Id := Defining_Identifier (Context_Id);
+ end if;
+ end if;
+
+ elsif Nkind (Context) = N_Task_Body then
+ Context_Id := Corresponding_Spec (Context);
+
+ else
+ raise Program_Error;
+ end if;
+ end if;
+
+ pragma Assert (Present (Context));
+ pragma Assert (Present (Context_Id));
+ pragma Assert (Present (Context_Decls));
+ end Find_Enclosing_Context;
+
-----------------------
-- Find_Master_Scope --
-----------------------
S : Entity_Id;
begin
- -- In Ada2005, the master is the innermost enclosing scope that is not
+ -- In Ada 2005, the master is the innermost enclosing scope that is not
-- transient. If the enclosing block is the rewriting of a call or the
-- scope is an extended return statement this is valid master. The
-- master in an extended return is only used within the return, and is
S := Scope (E);
- if Ada_Version >= Ada_05 then
+ if Ada_Version >= Ada_2005 then
while Is_Internal (S) loop
if Nkind (Parent (S)) = N_Block_Statement
and then
if Has_Attach_Handler (Conc_Typ)
and then not Restricted_Profile
+ and then not Restriction_Active (No_Dynamic_Attachment)
then
Prot_Typ := RE_Static_Interrupt_Protection;
- elsif Has_Interrupt_Handler (Conc_Typ) then
+ elsif Has_Interrupt_Handler (Conc_Typ)
+ and then not Restriction_Active (No_Dynamic_Attachment)
+ then
Prot_Typ := RE_Dynamic_Interrupt_Protection;
-- The type has explicit entries or generated primitive entry
elsif Has_Entries (Conc_Typ)
or else
- (Ada_Version >= Ada_05
+ (Ada_Version >= Ada_2005
and then Present (Interface_List (Parent (Conc_Typ))))
then
case Corresponding_Runtime_Package (Conc_Typ) is
New_Reference_To (RTE (Prot_Typ), Loc),
Name =>
Make_Selected_Component (Loc,
- Prefix =>
- New_Reference_To (Obj_Ent, Loc),
- Selector_Name =>
- Make_Identifier (Loc, Name_uObject)));
+ Prefix => New_Reference_To (Obj_Ent, Loc),
+ Selector_Name => Make_Identifier (Loc, Name_uObject)));
Add (Decl);
end;
end if;
Make_Attribute_Reference (Loc,
Prefix =>
Make_Selected_Component (Loc,
- Prefix => Make_Identifier (Loc, Name_uInit),
+ Prefix => Make_Identifier (Loc, Name_uInit),
Selector_Name => Make_Identifier (Loc, Name_uObject)),
Attribute_Name => Name_Unchecked_Access));
-- defined value, see D.3(10).
if Present (Pdef)
- and then Has_Priority_Pragma (Pdef)
+ and then Has_Pragma_Priority (Pdef)
then
declare
Prio : constant Node_Id :=
-- When no priority is specified but an xx_Handler pragma is, we default
-- to System.Interrupts.Default_Interrupt_Priority, see D.3(10).
- elsif Has_Interrupt_Handler (Ptyp)
- or else Has_Attach_Handler (Ptyp)
+ elsif Has_Attach_Handler (Ptyp)
+ or else Has_Interrupt_Handler (Ptyp)
then
Append_To (Args,
New_Reference_To (RTE (RE_Default_Interrupt_Priority), Loc));
-- is a pointer to the record generated by the compiler to represent
-- the protected object.
+ -- A protected type without entries that covers an interface and
+ -- overrides the abstract routines with protected procedures is
+ -- considered equivalent to a protected type with entries in the
+ -- context of dispatching select statements.
+
if Has_Entry
- or else Has_Interrupt_Handler (Ptyp)
- or else Has_Attach_Handler (Ptyp)
or else Has_Interfaces (Protect_Rec)
+ or else
+ ((Has_Attach_Handler (Ptyp) or else Has_Interrupt_Handler (Ptyp))
+ and then not Restriction_Active (No_Dynamic_Attachment))
then
declare
- Pkg_Id : constant RTU_Id :=
- Corresponding_Runtime_Package (Ptyp);
+ Pkg_Id : constant RTU_Id := Corresponding_Runtime_Package (Ptyp);
+
Called_Subp : RE_Id;
begin
raise Program_Error;
end case;
- if Has_Entry or else not Restricted then
+ if Has_Entry
+ or else not Restricted
+ or else Has_Interfaces (Protect_Rec)
+ then
Append_To (Args,
Make_Attribute_Reference (Loc,
- Prefix => Make_Identifier (Loc, Name_uInit),
+ Prefix => Make_Identifier (Loc, Name_uInit),
Attribute_Name => Name_Address));
end if;
Append_To (Args,
Make_Attribute_Reference (Loc,
- Prefix =>
- New_Reference_To (P_Arr, Loc),
+ Prefix => New_Reference_To (P_Arr, Loc),
Attribute_Name => Name_Unrestricted_Access));
-- Build_Entry_Names generation flag. When set to true, the
Make_Attribute_Reference (Loc,
Prefix =>
Make_Selected_Component (Loc,
- Prefix => Make_Identifier (Loc, Name_uInit),
+ Prefix => Make_Identifier (Loc, Name_uInit),
Selector_Name => Make_Identifier (Loc, Name_uObject)),
Attribute_Name => Name_Unchecked_Access));
-- Priority parameter. Set to Unspecified_Priority unless there is a
-- priority pragma, in which case we take the value from the pragma.
- if Present (Tdef) and then Has_Priority_Pragma (Tdef) then
+ if Present (Tdef) and then Has_Pragma_Priority (Tdef) then
Append_To (Args,
Make_Selected_Component (Loc,
- Prefix => Make_Identifier (Loc, Name_uInit),
+ Prefix => Make_Identifier (Loc, Name_uInit),
Selector_Name => Make_Identifier (Loc, Name_uPriority)));
else
Append_To (Args,
if Preallocated_Stacks_On_Target then
Append_To (Args,
Make_Attribute_Reference (Loc,
- Prefix => Make_Selected_Component (Loc,
- Prefix => Make_Identifier (Loc, Name_uInit),
- Selector_Name =>
- Make_Identifier (Loc, Name_uStack)),
+ Prefix =>
+ Make_Selected_Component (Loc,
+ Prefix => Make_Identifier (Loc, Name_uInit),
+ Selector_Name => Make_Identifier (Loc, Name_uStack)),
Attribute_Name => Name_Address));
else
then
Append_To (Args,
Make_Selected_Component (Loc,
- Prefix => Make_Identifier (Loc, Name_uInit),
+ Prefix => Make_Identifier (Loc, Name_uInit),
Selector_Name => Make_Identifier (Loc, Name_uSize)));
else
then
Append_To (Args,
Make_Selected_Component (Loc,
- Prefix => Make_Identifier (Loc, Name_uInit),
+ Prefix => Make_Identifier (Loc, Name_uInit),
Selector_Name => Make_Identifier (Loc, Name_uTask_Info)));
else
New_Reference_To (RTE (RE_Unspecified_Task_Info), Loc));
end if;
+ -- CPU parameter. Set to Unspecified_CPU unless there is a CPU pragma,
+ -- in which case we take the value from the pragma. The parameter is
+ -- passed as an Integer because in the case of unspecified CPU the
+ -- value is not in the range of CPU_Range.
+
+ if Present (Tdef) and then Has_Pragma_CPU (Tdef) then
+ Append_To (Args,
+ Convert_To (Standard_Integer,
+ Make_Selected_Component (Loc,
+ Prefix => Make_Identifier (Loc, Name_uInit),
+ Selector_Name => Make_Identifier (Loc, Name_uCPU))));
+
+ else
+ Append_To (Args,
+ New_Reference_To (RTE (RE_Unspecified_CPU), Loc));
+ end if;
+
if not Restricted_Profile then
-- Deadline parameter. If no Relative_Deadline pragma is present,
if Present (Tdef) and then Has_Relative_Deadline_Pragma (Tdef) then
Append_To (Args,
Make_Selected_Component (Loc,
- Prefix => Make_Identifier (Loc, Name_uInit),
+ Prefix =>
+ Make_Identifier (Loc, Name_uInit),
Selector_Name =>
Make_Identifier (Loc, Name_uRelative_Deadline)));
New_Reference_To (RTE (RE_Time_Span_Zero), Loc));
end if;
+ -- Dispatching_Domain parameter. If no Dispatching_Domain pragma or
+ -- aspect is present, then the dispatching domain is null. If a
+ -- pragma or aspect is present, then the dispatching domain is taken
+ -- from the _Dispatching_Domain field of the task value record,
+ -- which was set from the pragma value. Note that this parameter
+ -- must not be generated for the restricted profiles since Ravenscar
+ -- does not allow dispatching domains.
+
+ -- Case where pragma or aspect Dispatching_Domain applies: use given
+ -- value.
+
+ if Present (Tdef) and then Has_Pragma_Dispatching_Domain (Tdef) then
+ Append_To (Args,
+ Make_Selected_Component (Loc,
+ Prefix =>
+ Make_Identifier (Loc, Name_uInit),
+ Selector_Name =>
+ Make_Identifier (Loc, Name_uDispatching_Domain)));
+
+ -- No pragma or aspect Dispatching_Domain apply to the task
+
+ else
+ Append_To (Args, Make_Null (Loc));
+ end if;
+
-- Number of entries. This is an expression of the form:
-- n + _Init.a'Length + _Init.a'B'Length + ...
Append_To (Args,
Make_Selected_Component (Loc,
- Prefix => Make_Identifier (Loc, Name_uInit),
+ Prefix => Make_Identifier (Loc, Name_uInit),
Selector_Name => Make_Identifier (Loc, Name_uTask_Id)));
-- Build_Entry_Names generation flag. When set to true, the runtime
Expression =>
Make_Explicit_Dereference (Loc,
Make_Selected_Component (Loc,
- Prefix =>
+ Prefix =>
New_Reference_To (P, Loc),
Selector_Name =>
Make_Identifier (Loc, Chars (Formal)))));