This patch implements the following SPARK rules from SPARK RM 6.1.1(3): A subprogram_renaming_declaration shall not declare a primitive operation of a tagged type.
------------ -- Source -- ------------ -- renamings.ads package Renamings with SPARK_Mode is type T is tagged null record; procedure Null_Proc (Obj : in out T) is null; procedure Proc_1 (Obj : in out T); procedure Proc_2 (Obj : in out T); function Func_1 (Obj : T) return Integer; function Func_2 (Obj : T) return Integer; function Func_3 return T; function Func_4 return T; procedure Error_1 (Obj : in out T) renames Null_Proc; -- Error procedure Error_2 (Obj : in out T) renames Proc_1; -- Error function Error_3 (Obj : T) return Integer renames Func_1; -- Error function Error_4 return T renames Func_3; -- Error package Nested is procedure OK_1 (Obj : in out T) renames Null_Proc; -- OK procedure OK_2 (Obj : in out T) renames Proc_1; -- OK function OK_3 (Obj : T) return Integer renames Func_1; -- OK function OK_4 return T renames Func_3; -- OK end Nested; end Renamings; -- renamings.adb package body Renamings with SPARK_Mode is procedure Proc_1 (Obj : in out T) is begin null; end Proc_1; procedure Proc_2 (Obj : in out T) renames Proc_1; -- OK function Func_1 (Obj : T) return Integer is begin return 0; end Func_1; function Func_2 (Obj : T) return Integer renames Func_1; -- OK function Func_3 return T is Result : T; begin return Result; end Func_3; function Func_4 return T renames Func_3; -- OK end Renamings; ---------------------------- -- Compilation and output -- ---------------------------- $ gcc -c renamings.adb renamings.ads:15:39: subprogram renaming "Error_1" cannot declare primitive of type "T" (SPARK RM 6.1.1(3)) renamings.ads:16:39: subprogram renaming "Error_2" cannot declare primitive of type "T" (SPARK RM 6.1.1(3)) renamings.ads:17:47: subprogram renaming "Error_3" cannot declare primitive of type "T" (SPARK RM 6.1.1(3)) renamings.ads:18:31: subprogram renaming "Error_4" cannot declare primitive of type "T" (SPARK RM 6.1.1(3)) Tested on x86_64-pc-linux-gnu, committed on trunk 2017-11-16 Hristian Kirtchev <kirtc...@adacore.com> * sem_ch8.adb (Analyze_Subprogram_Renaming): Ensure that a renaming declaration does not define a primitive operation of a tagged type for SPARK. (Check_SPARK_Primitive_Operation): New routine.
Index: sem_ch8.adb =================================================================== --- sem_ch8.adb (revision 254797) +++ sem_ch8.adb (working copy) @@ -59,6 +59,7 @@ with Sem_Dist; use Sem_Dist; with Sem_Elab; use Sem_Elab; with Sem_Eval; use Sem_Eval; +with Sem_Prag; use Sem_Prag; with Sem_Res; use Sem_Res; with Sem_Util; use Sem_Util; with Sem_Type; use Sem_Type; @@ -1924,6 +1925,10 @@ -- have one. Otherwise the subtype of Sub's return profile must -- exclude null. + procedure Check_SPARK_Primitive_Operation (Subp_Id : Entity_Id); + -- Ensure that a SPARK renaming denoted by its entity Subp_Id does not + -- declare a primitive operation of a tagged type (SPARK RM 6.1.1(3)). + procedure Freeze_Actual_Profile; -- In Ada 2012, enforce the freezing rule concerning formal incomplete -- types: a callable entity freezes its profile, unless it has an @@ -2519,6 +2524,52 @@ end if; end Check_Null_Exclusion; + ------------------------------------- + -- Check_SPARK_Primitive_Operation -- + ------------------------------------- + + procedure Check_SPARK_Primitive_Operation (Subp_Id : Entity_Id) is + Prag : constant Node_Id := SPARK_Pragma (Subp_Id); + Typ : Entity_Id; + + begin + -- Nothing to do when the subprogram appears within an instance + + if In_Instance then + return; + + -- Nothing to do when the subprogram is not subject to SPARK_Mode On + -- because this check applies to SPARK code only. + + elsif not (Present (Prag) + and then Get_SPARK_Mode_From_Annotation (Prag) = On) + then + return; + + -- Nothing to do when the subprogram is not a primitive operation + + elsif not Is_Primitive (Subp_Id) then + return; + end if; + + Typ := Find_Dispatching_Type (Subp_Id); + + -- Nothing to do when the subprogram is a primitive operation of an + -- untagged type. + + if No (Typ) then + return; + end if; + + -- At this point a renaming declaration introduces a new primitive + -- operation for a tagged type. + + Error_Msg_Node_2 := Typ; + Error_Msg_NE + ("subprogram renaming & cannot declare primitive for type & " + & "(SPARK RM 6.1.1(3))", N, Subp_Id); + end Check_SPARK_Primitive_Operation; + --------------------------- -- Freeze_Actual_Profile -- --------------------------- @@ -2899,7 +2950,7 @@ -- Set SPARK mode from current context - Set_SPARK_Pragma (New_S, SPARK_Mode_Pragma); + Set_SPARK_Pragma (New_S, SPARK_Mode_Pragma); Set_SPARK_Pragma_Inherited (New_S); Rename_Spec := Find_Corresponding_Spec (N); @@ -3009,13 +3060,16 @@ Generate_Definition (New_S); New_Overloaded_Entity (New_S); - if Is_Entity_Name (Nam) - and then Is_Intrinsic_Subprogram (Entity (Nam)) + if not (Is_Entity_Name (Nam) + and then Is_Intrinsic_Subprogram (Entity (Nam))) then - null; - else Check_Delayed_Subprogram (New_S); end if; + + -- Verify that a SPARK renaming does not declare a primitive + -- operation of a tagged type. + + Check_SPARK_Primitive_Operation (New_S); end if; -- There is no need for elaboration checks on the new entity, which may @@ -3205,10 +3259,9 @@ elsif Requires_Overriding (Old_S) or else - (Is_Abstract_Subprogram (Old_S) - and then Present (Find_Dispatching_Type (Old_S)) - and then - not Is_Abstract_Type (Find_Dispatching_Type (Old_S))) + (Is_Abstract_Subprogram (Old_S) + and then Present (Find_Dispatching_Type (Old_S)) + and then not Is_Abstract_Type (Find_Dispatching_Type (Old_S))) then Error_Msg_N ("renamed entity cannot be subprogram that requires overriding "