diff mbox series

[Ada] Spurious warnings and errors on calls on synchronized interfaces

Message ID 20171020170340.GA112594@adacore.com
State New
Headers show
Series [Ada] Spurious warnings and errors on calls on synchronized interfaces | expand

Commit Message

Pierre-Marie de Rodat Oct. 20, 2017, 5:03 p.m. UTC
This patch fixes some spurious warnings and errors on dispatching calls to
synchronized operations when the controlling formal of the operation is an
access to interface type.

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

gcc/ada/

2017-10-20  Ed Schonberg  <schonberg@adacore.com>

	* sem_util.adb (Is_Controlling_Limited_Procedure): Handle properly the
	case where the controlling formal is an anonymous access to interface
	type.
	* exp_ch9.adb (Extract_Dispatching_Call): If controlling actual is an
	access type, handle properly the the constructed dereference that
	designates the object used in the rewritten synchronized call.
	(Parameter_Block_Pack): If the type of the actual is by-copy, its
	generated declaration in the parameter block does not need an
	initialization even if the type is a null-excluding access type,
	because it will be initialized with the value of the actual later on.
	(Parameter_Block_Pack): Do not add controlling actual to parameter
	block when its type is by-copy.

gcc/testsuite/

2017-10-20  Ed Schonberg  <schonberg@adacore.com>

	* gnat.dg/sync_iface_call.adb, gnat.dg/sync_iface_call_pkg.ads,
	gnat.dg/sync_iface_call_pkg2.adb, gnat.dg/sync_iface_call_pkg2.ads:
	New testcase.
diff mbox series

Patch

Index: sem_util.adb
===================================================================
--- sem_util.adb	(revision 253947)
+++ sem_util.adb	(working copy)
@@ -13186,18 +13186,30 @@ 
    function Is_Controlling_Limited_Procedure
      (Proc_Nam : Entity_Id) return Boolean
    is
+      Param     : Node_Id;
       Param_Typ : Entity_Id := Empty;
 
    begin
       if Ekind (Proc_Nam) = E_Procedure
         and then Present (Parameter_Specifications (Parent (Proc_Nam)))
       then
-         Param_Typ := Etype (Parameter_Type (First (
-                        Parameter_Specifications (Parent (Proc_Nam)))));
+         Param := Parameter_Type (First (
+                    Parameter_Specifications (Parent (Proc_Nam))));
 
-      --  In this case where an Itype was created, the procedure call has been
-      --  rewritten.
+         --  The formal may be an anonymous access type.
 
+         if Nkind (Param) = N_Access_Definition then
+            Param_Typ := Entity (Subtype_Mark (Param));
+
+         else
+            Param_Typ := Etype (Param);
+         end if;
+
+      --  In the case where an Itype was created for a dispatchin call, the
+      --  procedure call has been rewritten. The actual may be an access to
+      --  interface type in which case it is the designated type that is the
+      --  controlling type.
+
       elsif Present (Associated_Node_For_Itype (Proc_Nam))
         and then Present (Original_Node (Associated_Node_For_Itype (Proc_Nam)))
         and then
@@ -13207,6 +13219,10 @@ 
          Param_Typ :=
            Etype (First (Parameter_Associations
                           (Associated_Node_For_Itype (Proc_Nam))));
+
+         if Ekind (Param_Typ) = E_Anonymous_Access_Type then
+            Param_Typ := Directly_Designated_Type (Param_Typ);
+         end if;
       end if;
 
       if Present (Param_Typ) then
Index: exp_ch9.adb
===================================================================
--- exp_ch9.adb	(revision 253941)
+++ exp_ch9.adb	(working copy)
@@ -12909,11 +12909,14 @@ 
       end if;
 
       --  If the type of the dispatching object is an access type then return
-      --  an explicit dereference.
+      --  an explicit dereference  of a copy of the object, and note that
+      --  this is the controlling actual of the call.
 
       if Is_Access_Type (Etype (Object)) then
-         Object := Make_Explicit_Dereference (Sloc (N), Object);
+         Object :=
+           Make_Explicit_Dereference (Sloc (N), New_Copy_Tree (Object));
          Analyze (Object);
+         Set_Is_Controlling_Actual (Object);
       end if;
    end Extract_Dispatching_Call;
 
@@ -14561,6 +14564,12 @@ 
                 Object_Definition   =>
                   New_Occurrence_Of (Etype (Formal), Loc)));
 
+            --  The object is initialized with an explicit assignment
+            --  later. Indicate that it does not need an initialization
+            --  to prevent spurious warnings if the type excludes null.
+
+            Set_No_Initialization (Last (Decls));
+
             if Ekind (Formal) /= E_Out_Parameter then
 
                --  Generate:
@@ -14577,16 +14586,23 @@ 
                    Expression => New_Copy_Tree (Actual)));
             end if;
 
-            --  Generate:
+            --  If the actual is not controlling, generate:
+
             --    Jnn'unchecked_access
 
-            Append_To (Params,
-              Make_Attribute_Reference (Loc,
-                Attribute_Name => Name_Unchecked_Access,
-                Prefix         => New_Occurrence_Of (Temp_Nam, Loc)));
+            --  and add it to aggegate for access to formals. Note that
+            --  the actual may be by-copy but still be a controlling actual
+            --  if it is an access to class-wide interface.
 
-            Has_Param := True;
+            if not Is_Controlling_Actual (Actual) then
+               Append_To (Params,
+                 Make_Attribute_Reference (Loc,
+                   Attribute_Name => Name_Unchecked_Access,
+                   Prefix         => New_Occurrence_Of (Temp_Nam, Loc)));
 
+               Has_Param := True;
+            end if;
+
          --  The controlling parameter is omitted
 
          else
Index: ../testsuite/gnat.dg/sync_iface_call.adb
===================================================================
--- ../testsuite/gnat.dg/sync_iface_call.adb	(revision 0)
+++ ../testsuite/gnat.dg/sync_iface_call.adb	(revision 0)
@@ -0,0 +1,34 @@ 
+--  { dg-do compile }
+
+with Sync_Iface_Call_Pkg;
+with Sync_Iface_Call_Pkg2;
+
+procedure Sync_Iface_Call is
+
+   Impl : access Sync_Iface_Call_Pkg.IFace'Class :=
+       new Sync_Iface_Call_Pkg2.Impl;
+   Val : aliased Integer := 10;
+begin
+   select
+      Impl.Do_Stuff (Val);
+   or
+      delay 10.0;
+   end select;
+   select
+      Impl.Do_Stuff_Access (Val'Access);
+   or
+      delay 10.0;
+   end select;
+
+   select
+      Impl.Do_Stuff_2 (Val);
+   or
+      delay 10.0;
+   end select;
+
+   select
+      Impl.Do_Stuff_2_Access (Val'Access);
+   or
+      delay 10.0;
+   end select;
+end Sync_Iface_Call;
Index: ../testsuite/gnat.dg/sync_iface_call_pkg.ads
===================================================================
--- ../testsuite/gnat.dg/sync_iface_call_pkg.ads	(revision 0)
+++ ../testsuite/gnat.dg/sync_iface_call_pkg.ads	(revision 0)
@@ -0,0 +1,21 @@ 
+package Sync_Iface_Call_Pkg is
+
+   type IFace is synchronized interface;
+
+   procedure Do_Stuff
+     (This  : in out IFace;
+      Value : in Integer) is null;
+
+   procedure Do_Stuff_Access
+     (This  : in out IFace;
+      Value : not null access Integer) is null;
+
+   procedure Do_Stuff_2
+     (This  : not null access IFace;
+      Value : in Integer) is null;
+
+   procedure Do_Stuff_2_Access
+     (This  : not null access IFace;
+      Value : not null access Integer) is null;
+
+end Sync_Iface_Call_Pkg;
Index: ../testsuite/gnat.dg/sync_iface_call_pkg2.adb
===================================================================
--- ../testsuite/gnat.dg/sync_iface_call_pkg2.adb	(revision 0)
+++ ../testsuite/gnat.dg/sync_iface_call_pkg2.adb	(revision 0)
@@ -0,0 +1,8 @@ 
+package body Sync_Iface_Call_Pkg2 is
+
+   task body Impl is
+   begin
+      null;
+   end Impl;
+
+end Sync_Iface_Call_Pkg2;
Index: ../testsuite/gnat.dg/sync_iface_call_pkg2.ads
===================================================================
--- ../testsuite/gnat.dg/sync_iface_call_pkg2.ads	(revision 0)
+++ ../testsuite/gnat.dg/sync_iface_call_pkg2.ads	(revision 0)
@@ -0,0 +1,7 @@ 
+with Sync_Iface_Call_Pkg;
+
+package Sync_Iface_Call_Pkg2 is
+
+   task type Impl is new Sync_Iface_Call_Pkg.IFace with end;
+
+end Sync_Iface_Call_Pkg2;