diff mbox

[Ada] Indirect calls are always external

Message ID 20150220143607.GA5338@adacore.com
State New
Headers show

Commit Message

Arnaud Charlet Feb. 20, 2015, 2:36 p.m. UTC
an indirect call through an access-to-protected-subprogram value is always
considered an external call. This patch makes that happen (previously, the
compiler was using internal calls in some cases).

The following test should run to completion, silently. (Before the bug fix, it
would hang, because the call "V_Acc.all;" was not reevaluating the barriers,
so the call "PO.P;" would never proceed.)

package External_Indirect_Calls is

   protected PO is

      procedure Init;
      entry P;
      procedure V;

   private
      B : Boolean := True;
   end PO;

   V_Acc : access protected procedure;

end External_Indirect_Calls;

package body External_Indirect_Calls is

   protected body PO is

      procedure Init is
      begin
         V_Acc := V'Access;
      end Init;

      entry P when not B is
      begin
         B := True;
      end P;

      procedure V is
      begin
         B := False;
      end V;

   end PO;

end External_Indirect_Calls;

procedure External_Indirect_Calls.Main is
   task T;
   task body T is
   begin
      PO.P;
   end T;
begin
   PO.Init;
   delay 0.001;
   V_Acc.all;
end External_Indirect_Calls.Main;

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

2015-02-20  Bob Duff  <duff@adacore.com>

	* exp_attr.adb (May_Be_External_Call): Remove this. There is no need
	for the compiler to guess whether the call is internal or external --
	it is always external.
	(Expand_Access_To_Protected_Op): For P'Access, where P
	is a protected subprogram, always create a pointer to the
	External_Subprogram.
diff mbox

Patch

Index: exp_attr.adb
===================================================================
--- exp_attr.adb	(revision 220835)
+++ exp_attr.adb	(working copy)
@@ -6,7 +6,7 @@ 
 --                                                                          --
 --                                 B o d y                                  --
 --                                                                          --
---          Copyright (C) 1992-2014, Free Software Foundation, Inc.         --
+--          Copyright (C) 1992-2015, 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- --
@@ -690,41 +690,6 @@ 
       Obj_Ref : Node_Id;
       Curr    : Entity_Id;
 
-      function May_Be_External_Call return Boolean;
-      --  If the 'Access is to a local operation, but appears in a context
-      --  where it may lead to a call from outside the object, we must treat
-      --  this as an external call. Clearly we cannot tell without full
-      --  flow analysis, and a subsequent call that uses this 'Access may
-      --  lead to a bounded error (trying to seize locks twice, e.g.). For
-      --  now we treat 'Access as a potential external call if it is an actual
-      --  in a call to an outside subprogram.
-
-      --------------------------
-      -- May_Be_External_Call --
-      --------------------------
-
-      function May_Be_External_Call return Boolean is
-         Subp : Entity_Id;
-         Par  : Node_Id := Parent (N);
-
-      begin
-         --  Account for the case where the Access attribute is part of a
-         --  named parameter association.
-
-         if Nkind (Par) = N_Parameter_Association then
-            Par := Parent (Par);
-         end if;
-
-         if Nkind (Par) in N_Subprogram_Call
-            and then Is_Entity_Name (Name (Par))
-         then
-            Subp := Entity (Name (Par));
-            return not In_Open_Scopes (Scope (Subp));
-         else
-            return False;
-         end if;
-      end May_Be_External_Call;
-
    --  Start of processing for Expand_Access_To_Protected_Op
 
    begin
@@ -733,15 +698,15 @@ 
       --  protected body of the current enclosing operation.
 
       if Is_Entity_Name (Pref) then
-         if May_Be_External_Call then
-            Sub :=
-              New_Occurrence_Of (External_Subprogram (Entity (Pref)), Loc);
-         else
-            Sub :=
-              New_Occurrence_Of
-                (Protected_Body_Subprogram (Entity (Pref)), Loc);
-         end if;
+         --  All indirect calls are external calls, so must do locking and
+         --  barrier reevaluation, even if the 'Access occurs within the
+         --  protected body. Hence the call to External_Subprogram, as opposed
+         --  to Protected_Body_Subprogram, below. See RM-9.5(5). This means
+         --  that indirect calls from within the same protected body will
+         --  deadlock, as allowed by RM-9.5.1(8,15,17).
 
+         Sub := New_Occurrence_Of (External_Subprogram (Entity (Pref)), Loc);
+
          --  Don't traverse the scopes when the attribute occurs within an init
          --  proc, because we directly use the _init formal of the init proc in
          --  that case.