From: Eric Botcazou <[email protected]>

The incidental discovery of an old issue and its resolution has exposed the
convoluted handling of masters in Exp_Ch9, which uses two totally different
approaches to achieve the same goal, respectively in Build_Master_Entity and
Build_Class_Wide_Master, the latter being quite hard to follow. The handling
of activation chains for extended return statements is also a bit complex.

This gets rid of the second approach entirely for masters, as well as makes
the handling of activation chains uniform for all nodes.

No functional changes.

gcc/ada/ChangeLog:

        * gen_il-gen-gen_nodes.adb (N_Extended_Return_Statement): Add
        Activation_Chain_Entity semantic field.
        * exp_ch3.adb (Build_Master): Use Build_Master_{Entity,Renaming} in
        all cases.
        (Expand_N_Object_Declaration): Small tweak.
        * exp_ch6.adb (Make_Build_In_Place_Iface_Call_In_Allocator): Use
        Build_Master_{Entity,Renaming} to build the master.
        * exp_ch7.adb (Expand_N_Package_Declaration): Do not guard the call
        to Build_Task_Activation_Call for the sake of consistency.
        * exp_ch9.ads (Build_Class_Wide_Master): Delete.
        (Find_Master_Scope): Likewise.
        (Build_Protected_Subprogram_Call_Cleanup): Move to...
        (First_Protected_Operation): Move to...
        (Mark_Construct_As_Task_Master): New procedure.
        * exp_ch9.adb (Build_Protected_Subprogram_Call_Cleanup): ...here.
        (First_Protected_Operation): ...here.
        (Build_Activation_Chain_Entity): Streamline handling of extended
        return statements.
        (Build_Class_Wide_Master): Delete.
        (Build_Master_Entity): Streamline handling of extended return
        statements and call Mark_Construct_As_Task_Master on the context.
        (Build_Task_Activation_Call): Assert that the owner is not an
        extended return statement.
        (Find_Master_Scope): Delete.
        (Mark_Construct_As_Task_Master): New procedure.
        * sem_ch3.adb (Access_Definition): Use Build_Master_{Entity,Renaming}
        in all cases to build a master.
        * sem_ch6.adb (Check_Anonymous_Return): Rename to...
        (Check_Anonymous_Access_Return_With_Tasks): ...this.  At the end,
        call Mark_Construct_As_Task_Master on the parent node.
        (Analyze_Subprogram_Body_Helper): Adjust to above renaming.
        (Create_Extra_Formals): Do not set Has_Master_Entity here.
        * sinfo.ads (Activation_Chain_Entity): Adjust description.

Tested on x86_64-pc-linux-gnu, committed on master.

---
 gcc/ada/exp_ch3.adb              |  14 +-
 gcc/ada/exp_ch6.adb              |   4 +-
 gcc/ada/exp_ch7.adb              |   4 +-
 gcc/ada/exp_ch9.adb              | 351 +++++--------------------------
 gcc/ada/exp_ch9.ads              |  35 +--
 gcc/ada/gen_il-gen-gen_nodes.adb |   1 +
 gcc/ada/sem_ch3.adb              |   3 +-
 gcc/ada/sem_ch6.adb              |  53 ++---
 gcc/ada/sinfo.ads                |   4 +-
 9 files changed, 97 insertions(+), 372 deletions(-)

diff --git a/gcc/ada/exp_ch3.adb b/gcc/ada/exp_ch3.adb
index fbc7060a744..57d2ec39974 100644
--- a/gcc/ada/exp_ch3.adb
+++ b/gcc/ada/exp_ch3.adb
@@ -6684,7 +6684,8 @@ package body Exp_Ch3 is
          elsif not Is_Param_Block_Component_Type (Ptr_Typ)
            and then Is_Limited_Class_Wide_Type (Desig_Typ)
          then
-            Build_Class_Wide_Master (Ptr_Typ);
+            Build_Master_Entity (Ptr_Typ);
+            Build_Master_Renaming (Ptr_Typ);
          end if;
       end Build_Master;
 
@@ -7651,7 +7652,9 @@ package body Exp_Ch3 is
       --  If tasks are being declared, make sure we have an activation chain
       --  defined for the tasks (has no effect if we already have one), and
       --  also that a Master variable is established (and that the appropriate
-      --  enclosing construct is established as a task master).
+      --  enclosing construct is established as a task master). And also deal
+      --  with objects initialized with a call to a BIP function that has task
+      --  formal parameters.
 
       if Has_Task (Typ)
         or else Might_Have_Tasks (Typ)
@@ -7660,12 +7663,7 @@ package body Exp_Ch3 is
       then
          Build_Activation_Chain_Entity (N);
 
-         if Has_Task (Typ) then
-            Build_Master_Entity (Def_Id);
-
-         --  Handle objects initialized with BIP function calls
-
-         elsif Has_BIP_Init_Expr then
+         if Has_Task (Typ) or else Has_BIP_Init_Expr then
             Build_Master_Entity (Def_Id);
          end if;
       end if;
diff --git a/gcc/ada/exp_ch6.adb b/gcc/ada/exp_ch6.adb
index 42111a416de..b388044fb3c 100644
--- a/gcc/ada/exp_ch6.adb
+++ b/gcc/ada/exp_ch6.adb
@@ -9954,7 +9954,6 @@ package body Exp_Ch6 is
       Anon_Type := Create_Itype (E_Anonymous_Access_Type, Function_Call);
       Set_Directly_Designated_Type (Anon_Type, Etype (BIP_Func_Call));
       Set_Etype (Anon_Type, Anon_Type);
-      Build_Class_Wide_Master (Anon_Type);
 
       Tmp_Decl :=
         Make_Object_Declaration (Loc,
@@ -9978,6 +9977,9 @@ package body Exp_Ch6 is
       Insert_Action (Allocator, Tmp_Decl);
       Expander_Mode_Restore;
 
+      Build_Master_Entity (Anon_Type);
+      Build_Master_Renaming (Anon_Type);
+
       Make_Build_In_Place_Call_In_Allocator
         (Allocator     => Expression (Tmp_Decl),
          Function_Call => Expression (Expression (Tmp_Decl)));
diff --git a/gcc/ada/exp_ch7.adb b/gcc/ada/exp_ch7.adb
index c170c23451d..e3cde2e3f30 100644
--- a/gcc/ada/exp_ch7.adb
+++ b/gcc/ada/exp_ch7.adb
@@ -5067,9 +5067,7 @@ package body Exp_Ch7 is
 
          --  Generate task activation call as last step of elaboration
 
-         if Present (Activation_Chain_Entity (N)) then
-            Build_Task_Activation_Call (N);
-         end if;
+         Build_Task_Activation_Call (N);
 
          --  Verify the run-time semantics of pragma Initial_Condition at the
          --  end of the private declarations when the package lacks a body.
diff --git a/gcc/ada/exp_ch9.adb b/gcc/ada/exp_ch9.adb
index 4c63ec978ff..f23df88a5b8 100644
--- a/gcc/ada/exp_ch9.adb
+++ b/gcc/ada/exp_ch9.adb
@@ -243,6 +243,16 @@ package body Exp_Ch9 is
    --  cleanup handler that unlocks the object in all cases. For details,
    --  see Exp_Ch7.Expand_Cleanup_Actions.
 
+   procedure Build_Protected_Subprogram_Call_Cleanup
+     (Op_Spec   : Node_Id;
+      Conc_Typ  : Node_Id;
+      Loc       : Source_Ptr;
+      Stmts     : List_Id);
+   --  Append to Stmts the cleanups after a call to a protected subprogram
+   --  whose specification is Op_Spec. Conc_Typ is the concurrent type and Loc
+   --  the sloc for appended statements. The cleanup will either unlock the
+   --  protected object or serve pending entries.
+
    function Build_Renamed_Formal_Declaration
      (New_F          : Entity_Id;
       Formal         : Entity_Id;
@@ -424,6 +434,10 @@ package body Exp_Ch9 is
    --  the scope of Context_Id and Context_Decls is the declarative list of
    --  Context.
 
+   function First_Protected_Operation (D : List_Id) return Node_Id;
+   --  Given the declarations list for a protected body, find the
+   --  first protected operation body.
+
    function Index_Object (Spec_Id : Entity_Id) return Entity_Id;
    --  Given a subprogram identifier, return the entity which is associated
    --  with the protection entry index in the Protected_Body_Subprogram or
@@ -959,33 +973,6 @@ package body Exp_Ch9 is
    -----------------------------------
 
    procedure Build_Activation_Chain_Entity (N : Node_Id) is
-      function Has_Activation_Chain (Stmt : Node_Id) return Boolean;
-      --  Determine whether an extended return statement has activation chain
-
-      --------------------------
-      -- Has_Activation_Chain --
-      --------------------------
-
-      function Has_Activation_Chain (Stmt : Node_Id) return Boolean is
-         Decl : Node_Id;
-
-      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;
-
-            Next (Decl);
-         end loop;
-
-         return False;
-      end Has_Activation_Chain;
-
-      --  Local variables
-
       Context    : Node_Id;
       Context_Id : Entity_Id;
       Decls      : List_Id;
@@ -1010,19 +997,7 @@ package body Exp_Ch9 is
 
       --  If 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
-         --  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;
-
+      if No (Activation_Chain_Entity (Context)) then
          declare
             Loc   : constant Source_Ptr := Sloc (Context);
             Chain : Entity_Id;
@@ -1031,18 +1006,7 @@ package body Exp_Ch9 is
          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;
+            Set_Activation_Chain_Entity (Context, Chain);
 
             Decl :=
               Make_Object_Declaration (Loc,
@@ -1184,155 +1148,6 @@ package body Exp_Ch9 is
           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_Decl  : Node_Id;
-      Master_Id    : Entity_Id;
-      Master_Scope : Entity_Id;
-      Name_Id      : Node_Id;
-      Related_Node : Node_Id;
-      Ren_Decl     : Node_Id;
-
-   begin
-      --  No action needed if the run-time has no tasking support
-
-      if Global_No_Tasking then
-         return;
-      end if;
-
-      --  Find the declaration that created the access type, which 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);
-      Master_Decl := Empty;
-
-      if not Has_Master_Entity (Master_Scope)
-        or else No (Current_Entity_In_Scope (Name_Id))
-      then
-         declare
-            Ins_Nod : Node_Id;
-            Par_Nod : Node_Id;
-
-         begin
-            Master_Decl := Build_Master_Declaration (Loc);
-
-            --  Ensure that the master declaration is placed before its use
-
-            Ins_Nod := Find_Hook_Context (Related_Node);
-            while not Is_List_Member (Ins_Nod) loop
-               Ins_Nod := Parent (Ins_Nod);
-            end loop;
-
-            Par_Nod := Parent (List_Containing (Ins_Nod));
-
-            --  For internal blocks created by Wrap_Loop_Statement, Wrap_
-            --  Statements_In_Block, and Build_Abort_Undefer_Block, remember
-            --  that they have a task master entity declaration; required by
-            --  Build_Master_Entity to avoid creating another master entity,
-            --  and also ensures that subsequent calls to Find_Master_Scope
-            --  return this scope as the master scope of Typ.
-
-            if Is_Internal_Block (Par_Nod) then
-               Set_Has_Master_Entity (Entity (Identifier (Par_Nod)));
-
-            elsif Nkind (Par_Nod) = N_Handled_Sequence_Of_Statements
-              and then Is_Internal_Block (Parent (Par_Nod))
-            then
-               Set_Has_Master_Entity (Entity (Identifier (Parent (Par_Nod))));
-
-            --  Otherwise remember that this scope has an associated task
-            --  master entity declaration.
-
-            else
-               Set_Has_Master_Entity (Master_Scope);
-            end if;
-
-            Insert_Before (First (List_Containing (Ins_Nod)), 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 (Par) in
-                          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:
-      --    typeMnn renames _master;
-
-      Ren_Decl :=
-        Make_Object_Renaming_Declaration (Loc,
-          Defining_Identifier => Master_Id,
-          Subtype_Mark        => New_Occurrence_Of (Standard_Integer, Loc),
-          Name                => Name_Id);
-
-      --  If the master is declared locally, add the renaming declaration
-      --  immediately after it, to prevent access-before-elaboration in the
-      --  back-end.
-
-      if Present (Master_Decl) then
-         Insert_After (Master_Decl, Ren_Decl);
-         Analyze (Ren_Decl);
-
-      else
-         Insert_Action (Related_Node, Ren_Decl);
-      end if;
-
-      Set_Master_Id (Typ, Master_Id);
-   end Build_Class_Wide_Master;
-
    --------------------------------
    -- Build_Corresponding_Record --
    --------------------------------
@@ -3256,47 +3071,11 @@ package body Exp_Ch9 is
          Find_Enclosing_Context (Par, Context, Context_Id, Decls);
       end if;
 
-      --  When the enclosing context is a BIP function whose result type has
-      --  tasks, the function has an extra formal that is the master of the
-      --  tasks to be created by its returned object (that is, when its
-      --  enclosing context is a return statement). However, if the body of
-      --  the function creates tasks before its return statements, such tasks
-      --  need their own master.
+      pragma Assert (not Is_Finalizer (Context_Id));
 
-      if Has_Master_Entity (Context_Id)
-        and then Ekind (Context_Id) = E_Function
-        and then Is_Build_In_Place_Function (Context_Id)
-        and then Needs_BIP_Task_Actuals (Context_Id)
-      then
-         --  No need to add it again if previously added
+      --  Nothing to do if the context already has a master
 
-         declare
-            Master_Present : Boolean;
-
-         begin
-            --  Handle transient scopes
-
-            if Context_Id /= Current_Scope then
-               Push_Scope (Context_Id);
-               Master_Present :=
-                 Present (Current_Entity_In_Scope (Name_uMaster));
-               Pop_Scope;
-            else
-               Master_Present :=
-                 Present (Current_Entity_In_Scope (Name_uMaster));
-            end if;
-
-            if Master_Present then
-               return;
-            end if;
-         end;
-
-      --  Nothing to do if the context already has a master; internally built
-      --  finalizers don't need a master.
-
-      elsif Has_Master_Entity (Context_Id)
-        or else Is_Finalizer (Context_Id)
-      then
+      if Has_Master_Entity (Context_Id) then
          return;
       end if;
 
@@ -3319,26 +3098,15 @@ package body Exp_Ch9 is
          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 (Context) in
-              N_Block_Statement | N_Subprogram_Body | N_Task_Body
-         then
-            Set_Is_Task_Master (Context);
-            exit;
+      --  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).
 
-         elsif Nkind (Parent (Context)) = N_Subunit then
-            Context := Corresponding_Stub (Parent (Context));
-         end if;
-
-         Context := Parent (Context);
-      end loop;
+      if Nkind (Context) /= N_Extended_Return_Statement then
+         Mark_Construct_As_Task_Master (Context);
+      end if;
    end Build_Master_Entity;
 
    ---------------------------
@@ -4680,6 +4448,13 @@ package body Exp_Ch9 is
          Owner := Unit_Declaration_Node (Corresponding_Spec (Owner));
       end if;
 
+      --  An extended return statement is not really a task activator, but it
+      --  does have an activation chain on which to store tasks temporarily.
+      --  On successful return, the tasks on this chain are moved to the chain
+      --  passed in by the caller.
+
+      pragma Assert (Nkind (Owner) /= N_Extended_Return_Statement);
+
       Chain := Activation_Chain_Entity (Owner);
 
       --  Nothing to do when there are no tasks to activate. This is indicated
@@ -13298,42 +13073,6 @@ package body Exp_Ch9 is
       pragma Assert (Present (Context_Decls));
    end Find_Enclosing_Context;
 
-   -----------------------
-   -- Find_Master_Scope --
-   -----------------------
-
-   function Find_Master_Scope (E : Entity_Id) return Entity_Id is
-      S : Entity_Id;
-
-   begin
-      --  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
-      --  subsequently overwritten in Move_Activation_Chain, but it must exist
-      --  now before that overwriting occurs.
-
-      S := Scope (E);
-
-      if Ada_Version >= Ada_2005 then
-         while Is_Internal (S) loop
-            if Nkind (Parent (S)) = N_Block_Statement
-              and then Has_Master_Entity (S)
-            then
-               exit;
-
-            elsif Ekind (S) = E_Return_Statement then
-               exit;
-
-            else
-               S := Scope (S);
-            end if;
-         end loop;
-      end if;
-
-      return S;
-   end Find_Master_Scope;
-
    -------------------------------
    -- First_Protected_Operation --
    -------------------------------
@@ -14650,6 +14389,32 @@ package body Exp_Ch9 is
                Attribute_Name => Name_Unchecked_Access)));
    end Make_Unlock_Statement;
 
+   -----------------------------------
+   -- Mark_Construct_As_Task_Master --
+   -----------------------------------
+
+   procedure Mark_Construct_As_Task_Master (N : Node_Id) is
+      Nod : Node_Id := N;
+
+   begin
+      --  If we fall off the top, we are at the outer level, and the
+      --  environment task is our effective master, so nothing to mark.
+
+      while Nkind (Nod) /= N_Compilation_Unit loop
+         if Nkind (Nod) in N_Block_Statement | N_Subprogram_Body | N_Task_Body
+         then
+            Set_Is_Task_Master (Nod);
+            exit;
+
+         elsif Nkind (Parent (Nod)) = N_Subunit then
+            Nod := Corresponding_Stub (Parent (Nod));
+
+         else
+            Nod := Parent (Nod);
+         end if;
+      end loop;
+   end Mark_Construct_As_Task_Master;
+
    ------------------------------
    -- Next_Protected_Operation --
    ------------------------------
diff --git a/gcc/ada/exp_ch9.ads b/gcc/ada/exp_ch9.ads
index 681114133fe..4e5bdcc6434 100644
--- a/gcc/ada/exp_ch9.ads
+++ b/gcc/ada/exp_ch9.ads
@@ -50,11 +50,6 @@ package Exp_Ch9 is
    --  Task_Id of the associated task as the parameter. The caller is
    --  responsible for analyzing and resolving the resulting tree.
 
-   procedure Build_Class_Wide_Master (Typ : Entity_Id);
-   --  Given an access-to-limited class-wide type or an access-to-limited
-   --  interface, ensure that the designated type has a _master and generate
-   --  a renaming of the said master to service the access type.
-
    function Build_Master_Declaration (Loc : Source_Ptr) return Node_Id;
    --  For targets supporting tasks, generate:
    --      _Master : constant Integer := Current_Master.all;
@@ -99,16 +94,6 @@ package Exp_Ch9 is
    --  External is False if the call is to another protected subprogram within
    --  the same object.
 
-   procedure Build_Protected_Subprogram_Call_Cleanup
-     (Op_Spec   : Node_Id;
-      Conc_Typ  : Node_Id;
-      Loc       : Source_Ptr;
-      Stmts     : List_Id);
-   --  Append to Stmts the cleanups after a call to a protected subprogram
-   --  whose specification is Op_Spec. Conc_Typ is the concurrent type and Loc
-   --  the sloc for appended statements. The cleanup will either unlock the
-   --  protected object or serve pending entries.
-
    procedure Build_Task_Activation_Call (N : Node_Id);
    --  This procedure is called for constructs that can be task activators,
    --  i.e. task bodies, subprogram bodies, package bodies and blocks. If the
@@ -185,8 +170,7 @@ package Exp_Ch9 is
      (Sloc  : Source_Ptr;
       Ent   : Entity_Id;
       Index : Node_Id;
-      Ttyp  : Entity_Id)
-      return  Node_Id;
+      Ttyp  : Entity_Id) return  Node_Id;
    --  Returns an expression to compute a task entry index given the name of
    --  the entry or entry family. For the case of a task entry family, the
    --  Index parameter contains the expression for the subscript. Ttyp is the
@@ -267,19 +251,6 @@ package Exp_Ch9 is
    --  Return the external version of a protected operation, which locks
    --  the object before invoking the internal protected subprogram body.
 
-   function Find_Master_Scope (E : Entity_Id) return Entity_Id;
-   --  When a type includes tasks, a master entity is created in the scope, to
-   --  be used by the runtime during activation. In general the master is the
-   --  immediate scope in which the type is declared, but in Ada 2005, in the
-   --  presence of synchronized classwide interfaces, the immediate scope of
-   --  an anonymous access type may be a transient scope, which has no run-time
-   --  presence. In this case, the scope of the master is the innermost scope
-   --  that comes from source.
-
-   function First_Protected_Operation (D : List_Id) return Node_Id;
-   --  Given the declarations list for a protected body, find the
-   --  first protected operation body.
-
    procedure Install_Private_Data_Declarations
      (Loc      : Source_Ptr;
       Spec_Id  : Entity_Id;
@@ -345,6 +316,10 @@ package Exp_Ch9 is
    --  Given the entity of the record type created for a protected type, build
    --  a list of statements needed for proper initialization of the object.
 
+   procedure Mark_Construct_As_Task_Master (N : Node_Id);
+   --  Mark the innermost N_Block_Statement, N_Subprogram_Body or N_Task_Body
+   --  that is either N or enclosing N as being a task master.
+
    function Next_Protected_Operation (N : Node_Id) return Node_Id;
    --  Given a protected operation node (a subprogram or entry body), find the
    --  following node in the declarations list.
diff --git a/gcc/ada/gen_il-gen-gen_nodes.adb b/gcc/ada/gen_il-gen-gen_nodes.adb
index 9334c98e394..750287f771b 100644
--- a/gcc/ada/gen_il-gen-gen_nodes.adb
+++ b/gcc/ada/gen_il-gen-gen_nodes.adb
@@ -1015,6 +1015,7 @@ begin -- Gen_IL.Gen.Gen_Nodes
    Cc (N_Extended_Return_Statement, N_Statement_Other_Than_Procedure_Call,
        (Sy (Return_Object_Declarations, List_Id),
         Sy (Handled_Statement_Sequence, Node_Id, Default_Empty),
+        Sm (Activation_Chain_Entity, Node_Id),
         Sm (Procedure_To_Call, Node_Id),
         Sm (Return_Statement_Entity, Node_Id),
         Sm (Storage_Pool, Node_Id)));
diff --git a/gcc/ada/sem_ch3.adb b/gcc/ada/sem_ch3.adb
index cc26ecab6ae..e302908e9db 100644
--- a/gcc/ada/sem_ch3.adb
+++ b/gcc/ada/sem_ch3.adb
@@ -958,7 +958,8 @@ package body Sem_Ch3 is
          if Is_Limited_Record (Desig_Type)
            and then Is_Class_Wide_Type (Desig_Type)
          then
-            Build_Class_Wide_Master (Anon_Type);
+            Build_Master_Entity (Defining_Identifier (Related_Nod));
+            Build_Master_Renaming (Anon_Type);
 
          --  Similarly, if the type is an anonymous access that designates
          --  tasks, create a master entity for it in the current context.
diff --git a/gcc/ada/sem_ch6.adb b/gcc/ada/sem_ch6.adb
index 1235ea453b6..3b7e61ed11e 100644
--- a/gcc/ada/sem_ch6.adb
+++ b/gcc/ada/sem_ch6.adb
@@ -2434,11 +2434,11 @@ package body Sem_Ch6 is
       procedure Build_Subprogram_Declaration;
       --  Create a matching subprogram declaration for subprogram body N
 
-      procedure Check_Anonymous_Return;
-      --  Ada 2005: if a function returns an access type that denotes a task,
-      --  or a type that contains tasks, we must create a master entity for
-      --  the anonymous type, which typically will be used in an allocator
-      --  in the body of the function.
+      procedure Check_Anonymous_Access_Return_With_Tasks;
+      --  If a function returns an anonymous access type that designates a task
+      --  or a type that contains tasks, create a master entity in the function
+      --  for the anonymous access type, and also mark the construct enclosing
+      --  the function as a task master.
 
       procedure Check_Inline_Pragma (Spec : in out Node_Id);
       --  Look ahead to recognize a pragma that may appear after the body.
@@ -2795,13 +2795,12 @@ package body Sem_Ch6 is
          Body_Id := Analyze_Subprogram_Specification (Body_Spec);
       end Build_Subprogram_Declaration;
 
-      ----------------------------
-      -- Check_Anonymous_Return --
-      ----------------------------
+      ----------------------------------------------
+      -- Check_Anonymous_Access_Return_With_Tasks --
+      ----------------------------------------------
 
-      procedure Check_Anonymous_Return is
+      procedure Check_Anonymous_Access_Return_With_Tasks is
          Decl : Node_Id;
-         Par  : Node_Id;
          Scop : Entity_Id;
 
       begin
@@ -2837,29 +2836,14 @@ package body Sem_Ch6 is
                Set_Declarations (N, New_List (Decl));
             end if;
 
-            Set_Master_Id (Etype (Scop), Defining_Identifier (Decl));
             Set_Has_Master_Entity (Scop);
+            Set_Master_Id (Etype (Scop), Defining_Identifier (Decl));
 
-            --  Now mark the containing scope as a task master
+            --  Now mark the enclosing construct as a task master
 
-            Par := N;
-            while Nkind (Par) /= N_Compilation_Unit loop
-               Par := Parent (Par);
-               pragma Assert (Present (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 (Par)
-                    in N_Task_Body | N_Block_Statement | N_Subprogram_Body
-               then
-                  Set_Is_Task_Master (Par, True);
-                  exit;
-               end if;
-            end loop;
+            Mark_Construct_As_Task_Master (Parent (N));
          end if;
-      end Check_Anonymous_Return;
+      end Check_Anonymous_Access_Return_With_Tasks;
 
       -------------------------
       -- Check_Inline_Pragma --
@@ -4476,7 +4460,12 @@ package body Sem_Ch6 is
          Install_Private_With_Clauses (Body_Id);
       end if;
 
-      Check_Anonymous_Return;
+      --  If a function returns an anonymous access type that designates a task
+      --  or a type that contains tasks, we must create a master entity for the
+      --  anonymous access type, which typically will be used for an allocator
+      --  in the body of the function.
+
+      Check_Anonymous_Access_Return_With_Tasks;
 
       --  Set the Protected_Formal field of each extra formal of the protected
       --  subprogram to reference the corresponding extra formal of the
@@ -9420,10 +9409,6 @@ package body Sem_Ch6 is
                    (E, Standard_Integer,
                     E, BIP_Formal_Suffix (BIP_Task_Master));
 
-               if Needs_BIP_Task_Actuals (Ref_E) then
-                  Set_Has_Master_Entity (E);
-               end if;
-
                Discard :=
                  Add_Extra_Formal
                    (E, RTE (RE_Activation_Chain_Access),
diff --git a/gcc/ada/sinfo.ads b/gcc/ada/sinfo.ads
index c5d981d5302..34777c01cfb 100644
--- a/gcc/ada/sinfo.ads
+++ b/gcc/ada/sinfo.ads
@@ -757,8 +757,8 @@ package Sinfo is
    --    When tasks are declared in the corresponding declarative region this
    --    entity is located by name (its name is always _Chain) and the declared
    --    tasks are added to the chain. Note that N_Extended_Return_Statement
-   --    does not have this attribute, although it does have an activation
-   --    chain. This chain is used to store the tasks temporarily, and is not
+   --    also has this attribute, although it is not really a task activator:
+   --    this chain is only used to store the tasks temporarily, and is not
    --    used for activating them. On successful completion of the return
    --    statement, the tasks are moved to the caller's chain, and the caller
    --    activates them.
-- 
2.51.0


Reply via email to