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 <schonb...@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 <schonb...@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.
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;