From: Eric Botcazou <[email protected]>
The problem is that the task returned by the call to the function is never
activated. This is fixed by creating a transient scope around the call, as
is done for controlled types, after making transient scopes compatible with
task types.
gcc/ada/ChangeLog:
PR ada/42413
* exp_ch4.adb (Process_Transients_In_Expression): Deal with a task
activation chain present in the statement list.
* exp_ch6.adb (Make_Build_In_Place_Call_In_Anonymous_Context): Also
establish a transient scope if the result type has tasks.
* exp_ch7.adb (Make_Transient_Block): Deal with Has_Master_Entity
and Has_Activation_Chain_Entity set on the transient scope.
* exp_ch9.ads (Make_Task_Activation_Call): New declaration from...
* exp_ch9.adb (Make_Task_Activation_Call): ...here.
(Build_Activation_Chain_Entity): Deal with transient scopes.
(Build_Master_Entity): Likewise.
(Find_Enclosing_Context): Likewise.
* sem_elab.adb (Activation_Processor.Process_Activation): Deal with
N_Expression_With_Actions nodes.
* sem_util.adb (Current_Entity_In_Scope): Prevent transient scopes
from being transparent for _Chain and _Master entities.
Tested on x86_64-pc-linux-gnu, committed on master.
---
gcc/ada/exp_ch4.adb | 16 +++++---
gcc/ada/exp_ch6.adb | 17 +++++----
gcc/ada/exp_ch7.adb | 50 +++++++++++++++++++++----
gcc/ada/exp_ch9.adb | 88 ++++++++++++++++++++++++++------------------
gcc/ada/exp_ch9.ads | 5 +++
gcc/ada/sem_elab.adb | 8 ++++
gcc/ada/sem_util.adb | 5 ++-
7 files changed, 133 insertions(+), 56 deletions(-)
diff --git a/gcc/ada/exp_ch4.adb b/gcc/ada/exp_ch4.adb
index f39c80337e7..2763aed4f9a 100644
--- a/gcc/ada/exp_ch4.adb
+++ b/gcc/ada/exp_ch4.adb
@@ -255,7 +255,8 @@ package body Exp_Ch4 is
-- case expressions. Inspect and process actions list Stmts of expression
-- Expr for transient objects. If such objects are found, the routine will
-- generate code to finalize them when the enclosing context is elaborated
- -- or evaluated.
+ -- or evaluated. Moreover, if the declaration of a _Chain entity is found,
+ -- the routine will append a call to Activate_Tasks on the entity to Stmts.
-- This specific processing is required for these expressions because the
-- management of transient objects for expressions implemented in Exp_Ch7
@@ -15226,10 +15227,15 @@ package body Exp_Ch4 is
Decl := First (Stmts);
while Present (Decl) loop
- if Nkind (Decl) = N_Object_Declaration
- and then Is_Finalizable_Transient (Decl, Expr)
- then
- Process_Transient_In_Expression (Decl);
+ if Nkind (Decl) = N_Object_Declaration then
+ if Is_Finalizable_Transient (Decl, Expr) then
+ Process_Transient_In_Expression (Decl);
+
+ elsif Chars (Defining_Identifier (Decl)) = Name_uChain then
+ Insert_After_And_Analyze (Last (Stmts),
+ Make_Task_Activation_Call
+ (Sloc (Decl), Defining_Identifier (Decl)));
+ end if;
end if;
Next (Decl);
diff --git a/gcc/ada/exp_ch6.adb b/gcc/ada/exp_ch6.adb
index e43e360ec7b..968a7db4914 100644
--- a/gcc/ada/exp_ch6.adb
+++ b/gcc/ada/exp_ch6.adb
@@ -8932,20 +8932,21 @@ package body Exp_Ch6 is
Warn_BIP (Func_Call);
- -- If the build-in-place function returns a controlled object, then the
- -- object needs to be finalized immediately after the context is exited,
- -- which requires the creation of a transient scope and a named object.
-
-- If the build-in-place function returns a definite subtype, then an
- -- object also needs to be created and an access value designating it
- -- passed as an actual.
+ -- object needs to be created and an access value designating it needs
+ -- to be passed as an actual.
+
+ -- If the build-in-place function returns either a controlled object or
+ -- an object that contains tasks, then the object needs to be finalized
+ -- immediately after the context is exited, which requires the creation
+ -- of a transient scope and a named object.
-- Insert a temporary before the call initialized with function call to
-- reuse the BIP machinery which takes care of adding the extra build-in
-- place actuals.
- if Needs_Fin or else Known_Size or else Has_Tasks then
- if Needs_Fin then
+ if Known_Size or else Needs_Fin or else Has_Tasks then
+ if Needs_Fin or else Has_Tasks then
Establish_Transient_Scope
(Func_Call, Manage_Sec_Stack => not Known_Size);
end if;
diff --git a/gcc/ada/exp_ch7.adb b/gcc/ada/exp_ch7.adb
index f4f30dcc85d..c303a6145df 100644
--- a/gcc/ada/exp_ch7.adb
+++ b/gcc/ada/exp_ch7.adb
@@ -499,11 +499,11 @@ package body Exp_Ch7 is
(Loc : Source_Ptr;
Action : Node_Id;
Par : Node_Id) return Node_Id;
- -- Action is a single statement or object declaration. Par is the proper
- -- parent of the generated block. Create a transient block whose name is
- -- the current scope and the only handled statement is Action. If Action
- -- involves controlled objects or secondary stack usage, the corresponding
- -- cleanup actions are performed at the end of the block.
+ -- Action is a single statement. Par is the proper parent of the generated
+ -- block. Create a transient block whose name is the current scope and the
+ -- only handled statement is Action. If Action involves controlled objects
+ -- or task objects or secondary stack usage, corresponding cleanup actions
+ -- are performed at the end of the block.
procedure Store_Actions_In_Scope (AK : Scope_Action_Kind; L : List_Id);
-- Shared processing for the Store_xxx_Actions_In_Scope routines: attach
@@ -8720,7 +8720,6 @@ package body Exp_Ch7 is
-- Local variables
- Decls : constant List_Id := New_List;
Instrs : constant List_Id := New_List (Action);
Trans_Id : constant Entity_Id := Current_Scope;
@@ -8819,12 +8818,49 @@ package body Exp_Ch7 is
Block :=
Make_Block_Statement (Loc,
Identifier => New_Occurrence_Of (Trans_Id, Loc),
- Declarations => Decls,
+ Declarations => New_List,
Handled_Statement_Sequence =>
Make_Handled_Sequence_Of_Statements (Loc, Statements => Instrs),
Has_Created_Identifier => True);
Set_Parent (Block, Par);
+ -- If the transient scope contains a _Master entity, mark it as being
+ -- a task master since Build_Master_Entity could not do it.
+
+ Set_Is_Task_Master (Block, Has_Master_Entity (Trans_Id));
+
+ -- If the transient scope contains a _Chain entity, try to find its
+ -- declaration in the actions to be executed before the main action.
+ -- If found, generate a call to Activate_Tasks on the entity and, in
+ -- either case, set Is_Task_Allocation_Block to block the subsequent
+ -- generation of the same call by Build_Task_Activation_Call.
+
+ if Has_Activation_Chain_Entity (Trans_Id) then
+ declare
+ Before_Actions : List_Id
+ renames Scope_Stack.Table (Scope_Stack.Last).
+ Actions_To_Be_Wrapped (Before);
+ Act : Node_Id;
+
+ begin
+ Act := First (Before_Actions);
+ while Present (Act) loop
+ if Nkind (Act) = N_Object_Declaration
+ and then Chars (Defining_Identifier (Act)) = Name_uChain
+ then
+ Append_To (Before_Actions,
+ Make_Task_Activation_Call
+ (Loc, Defining_Identifier (Act)));
+ exit;
+ end if;
+
+ Next (Act);
+ end loop;
+
+ Set_Is_Task_Allocation_Block (Block);
+ end;
+ end if;
+
-- Insert actions stuck in the transient scopes as well as all freezing
-- nodes needed by those actions. Do not insert cleanup actions here,
-- they will be transferred to the newly created block.
diff --git a/gcc/ada/exp_ch9.adb b/gcc/ada/exp_ch9.adb
index 22c3515a46d..7c875448dc2 100644
--- a/gcc/ada/exp_ch9.adb
+++ b/gcc/ada/exp_ch9.adb
@@ -34,6 +34,7 @@ with Elists; use Elists;
with Errout; use Errout;
with Exp_Ch3; use Exp_Ch3;
with Exp_Ch6; use Exp_Ch6;
+with Exp_Ch7; use Exp_Ch7;
with Exp_Ch11; use Exp_Ch11;
with Exp_Dbug; use Exp_Dbug;
with Exp_Sel; use Exp_Sel;
@@ -427,10 +428,12 @@ package body Exp_Ch9 is
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.
+ -- enclosing body, block, package, or return statement and return its
+ -- constituents. Context is the enclosing construct, Context_Id is the
+ -- scope of Context and Context_Decls is the list of declarations of
+ -- Context. When the current scope is transient and will give rise to
+ -- a block, Context is the node to be wrapped, Context_Id is the scope
+ -- and Context_Decls is No_List.
function First_Protected_Operation (D : List_Id) return Node_Id;
-- Given the declarations list for a protected body, find the
@@ -454,11 +457,6 @@ package body Exp_Ch9 is
-- Determine whether Id is a function or a procedure and is marked as a
-- private primitive.
- function Make_Task_Activation_Call
- (Loc : Source_Ptr;
- Chain : Entity_Id) return Node_Id;
- -- Build a call to Activate_Tasks with Chain as the single parameter
-
function Make_Unlock_Statement
(Prot_Type : E_Protected_Type_Id;
Op_Spec : N_Subprogram_Specification_Id;
@@ -1013,16 +1011,21 @@ package body Exp_Ch9 is
Object_Definition =>
New_Occurrence_Of (RTE (RE_Activation_Chain), Sloc (N)));
- Prepend_To (Context_Decls, Decl);
+ if Present (Context_Decls) then
+ Prepend_To (Context_Decls, Decl);
- -- Ensure that _chain appears in the proper scope of the context
+ -- Ensure that _Chain appears in the proper scope of the context
+
+ if Context_Id /= Current_Scope then
+ Push_Scope (Context_Id);
+ Analyze (Decl);
+ Pop_Scope;
+ else
+ Analyze (Decl);
+ end if;
- if Context_Id /= Current_Scope then
- Push_Scope (Context_Id);
- Analyze (Decl);
- Pop_Scope;
else
- Analyze (Decl);
+ Insert_Action (N, Decl);
end if;
Set_Has_Activation_Chain_Entity (Context_Id);
@@ -3073,32 +3076,35 @@ package body Exp_Ch9 is
Decl := Build_Master_Declaration (Sloc (N));
- -- The master is inserted at the start of the declarative list of the
- -- context.
+ if Present (Context_Decls) then
+ -- The master is inserted at the start of the declarative list of the
+ -- context.
- Prepend_To (Context_Decls, Decl);
+ Prepend_To (Context_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.
+ -- Ensure that _Master appears in the proper scope of the context
+
+ if Context_Id /= Current_Scope then
+ Push_Scope (Context_Id);
+ Analyze (Decl);
+ Pop_Scope;
+ else
+ Analyze (Decl);
+ end if;
+
+ -- Mark its associated construct as being a task master, but masters
+ -- associated with return statements are already marked at this stage
+ -- (see Analyze_Subprogram_Body_Helper).
+
+ if Nkind (Context) /= N_Extended_Return_Statement then
+ Mark_Construct_As_Task_Master (Context);
+ end if;
- if Context_Id /= Current_Scope then
- Push_Scope (Context_Id);
- Analyze (Decl);
- Pop_Scope;
else
- Analyze (Decl);
+ Insert_Action (N, Decl);
end if;
Set_Has_Master_Entity (Context_Id);
-
- -- Mark its associated construct as being a task master, but masters
- -- associated with return statements are already marked at this stage
- -- (see Analyze_Subprogram_Body_Helper).
-
- if Nkind (Context) /= N_Extended_Return_Statement then
- Mark_Construct_As_Task_Master (Context);
- end if;
end Build_Master_Entity;
---------------------------------------
@@ -13008,6 +13014,18 @@ package body Exp_Ch9 is
Context_Decls : out List_Id)
is
begin
+ -- First deal with a transient scope that will give rise to a block
+
+ if Scope_Is_Transient
+ and then Nkind (Node_To_Be_Wrapped) not in N_Declaration
+ | N_Renaming_Declaration
+ then
+ Context := Node_To_Be_Wrapped;
+ Context_Id := Current_Scope;
+ Context_Decls := No_List;
+ return;
+ end if;
+
-- Traverse the parent chain looking for an enclosing body, block,
-- package or return statement.
diff --git a/gcc/ada/exp_ch9.ads b/gcc/ada/exp_ch9.ads
index 8101636610e..41b809f94aa 100644
--- a/gcc/ada/exp_ch9.ads
+++ b/gcc/ada/exp_ch9.ads
@@ -308,6 +308,11 @@ package Exp_Ch9 is
-- All the above declarations are inserted in the order shown to the front
-- of Decls.
+ function Make_Task_Activation_Call
+ (Loc : Source_Ptr;
+ Chain : Entity_Id) return Node_Id;
+ -- Build a call to Activate_Tasks with Chain as the single parameter
+
function Make_Task_Create_Call (Task_Rec : Entity_Id) return Node_Id;
-- Given the entity of the record type created for a task type, build
-- the call to Create_Task
diff --git a/gcc/ada/sem_elab.adb b/gcc/ada/sem_elab.adb
index 5e3823c3649..22adac2186b 100644
--- a/gcc/ada/sem_elab.adb
+++ b/gcc/ada/sem_elab.adb
@@ -2936,6 +2936,14 @@ package body Sem_Elab is
(List => Private_Declarations (Context),
Task_Objs => Task_Objs);
+ -- Process all task objects in the actions when the activation
+ -- call appears in an EWA node.
+
+ elsif Nkind (Context) = N_Expression_With_Actions then
+ Traverse_List
+ (List => Actions (Context),
+ Task_Objs => Task_Objs);
+
-- Otherwise the context must be a block or a body. Process all
-- task objects found in the declarations.
diff --git a/gcc/ada/sem_util.adb b/gcc/ada/sem_util.adb
index f53fe30da69..6f28f1cc4cd 100644
--- a/gcc/ada/sem_util.adb
+++ b/gcc/ada/sem_util.adb
@@ -6762,7 +6762,10 @@ package body Sem_Util is
elsif Scope_Is_Transient then
while Present (E) loop
- exit when Scope (E) = CS or else Scope (E) = Scope (CS);
+ exit when Scope (E) = CS
+ or else (Scope (E) = Scope (CS)
+ and then N /= Name_uChain
+ and then N /= Name_uMaster);
E := Homonym (E);
end loop;
--
2.53.0