diff mbox

[Ada] Master entities in Ada2005

Message ID 20100909095144.GA20580@adacore.com
State New
Headers show

Commit Message

Arnaud Charlet Sept. 9, 2010, 9:51 a.m. UTC
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 immedidate
scope in which the type is declared, but in Ada2005, 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.

The following must compile quietly:

---
package Pack09 is

  type Node_Type is limited interface;
  type Node_Ref is access all Node_Type'Class;

  function Parent (Node : Node_Type) return Node_Ref is abstract;

  type Node_Cursor is limited interface;

  function Has_Element (Position : Node_Cursor) return Boolean is abstract;
  function Element (Position : Node_Cursor) return Node_Ref is abstract;
  function Next (Position : Node_Cursor) return Node_Cursor is abstract;

  function First_Child (Node : Node_Type) return Node_Cursor'Class is abstract;

  function F (Node : Node_Ref) return Boolean;

end Pack09;
---
package body Pack09 is

  function F (Node : Node_Ref) return Boolean is
  begin
     return Node.Parent.First_Child.Element = Node
       and then not Node.Parent.First_Child.Next.Has_Element;
  end F;
end Pack09; 

Tested on x86_64-pc-linux-gnu, committed on trunk

2010-09-09  Ed Schonberg  <schonberg@adacore.com>

	* exp_ch9.ads (Find_Master_Scope): New function, extracted from
	Build_Master_Entity, to find the proper scope for the master entity of
	a type that may contain tasks, in the presence of transient scopes.
	* exp_ch9.adb (Build_Master_Entity) Use new function.
	* exp_ch3.adb (Build_Class_Wide_Master): ditto.
diff mbox

Patch

Index: exp_ch9.adb
===================================================================
--- exp_ch9.adb	(revision 164055)
+++ exp_ch9.adb	(working copy)
@@ -2481,31 +2481,7 @@  package body Exp_Ch9 is
       S    : Entity_Id;
 
    begin
-      S := Scope (E);
-
-      --  Ada 2005 (AI-287): Do not set/get the has_master_entity reminder
-      --  in internal scopes, unless present already.. Required for nested
-      --  limited aggregates, where the expansion of task components may
-      --  generate inner blocks. If the 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.
-
-      if Ada_Version >= Ada_05 then
-         while Is_Internal (S) loop
-            if Nkind (Parent (S)) = N_Block_Statement
-              and then
-                Nkind (Original_Node (Parent (S))) = N_Procedure_Call_Statement
-            then
-               exit;
-            elsif Ekind (S) = E_Return_Statement then
-               exit;
-            else
-               S := Scope (S);
-            end if;
-         end loop;
-      end if;
+      S := Find_Master_Scope (E);
 
       --  Nothing to do if we already built a master entity for this scope
       --  or if there is no task hierarchy.
@@ -2534,14 +2510,7 @@  package body Exp_Ch9 is
       Insert_Before (P, Decl);
       Analyze (Decl);
 
-      --  Ada 2005 (AI-287): Set the has_master_entity reminder in the
-      --  non-internal scope selected above.
-
-      if Ada_Version >= Ada_05 then
-         Set_Has_Master_Entity (S);
-      else
-         Set_Has_Master_Entity (Scope (E));
-      end if;
+      Set_Has_Master_Entity (S);
 
       --  Now mark the containing scope as a task master
 
@@ -11136,6 +11105,43 @@  package body Exp_Ch9 is
             Make_Integer_Literal (Loc, 0)));
    end Family_Size;
 
+   -----------------------
+   -- Find_Master_Scope --
+   -----------------------
+
+   function Find_Master_Scope (E : Entity_Id) return Entity_Id is
+      S : Entity_Id;
+
+   begin
+      --  In Ada2005, 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_05 then
+         while Is_Internal (S) loop
+            if Nkind (Parent (S)) = N_Block_Statement
+              and then
+                Nkind (Original_Node (Parent (S))) = N_Procedure_Call_Statement
+            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;
+
    -----------------------------------
    -- Find_Task_Or_Protected_Pragma --
    -----------------------------------
Index: exp_ch9.ads
===================================================================
--- exp_ch9.ads	(revision 164000)
+++ exp_ch9.ads	(working copy)
@@ -263,6 +263,15 @@  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 Ada2005, 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.
Index: exp_ch3.adb
===================================================================
--- exp_ch3.adb	(revision 164059)
+++ exp_ch3.adb	(working copy)
@@ -41,8 +41,8 @@  with Exp_Strm; use Exp_Strm;
 with Exp_Tss;  use Exp_Tss;
 with Exp_Util; use Exp_Util;
 with Freeze;   use Freeze;
-with Nlists;   use Nlists;
 with Namet;    use Namet;
+with Nlists;   use Nlists;
 with Nmake;    use Nmake;
 with Opt;      use Opt;
 with Restrict; use Restrict;
@@ -792,6 +792,7 @@  package body Exp_Ch3 is
       Decl : Node_Id;
       P    : Node_Id;
       Par  : Node_Id;
+      Scop : Entity_Id;
 
    begin
       --  Nothing to do if there is no task hierarchy
@@ -810,9 +811,11 @@  package body Exp_Ch3 is
          P := Parent (T);
       end if;
 
+      Scop := Find_Master_Scope (T);
+
       --  Nothing to do if we already built a master entity for this scope
 
-      if not Has_Master_Entity (Scope (T)) then
+      if not Has_Master_Entity (Scop) then
 
          --  First build the master entity
          --    _Master : constant Master_Id := Current_Master.all;
@@ -828,9 +831,9 @@  package body Exp_Ch3 is
                Make_Explicit_Dereference (Loc,
                  New_Reference_To (RTE (RE_Current_Master), Loc)));
 
+         Set_Has_Master_Entity (Scop);
          Insert_Action (P, Decl);
          Analyze (Decl);
-         Set_Has_Master_Entity (Scope (T));
 
          --  Now mark the containing scope as a task master. Masters
          --  associated with return statements are already marked at