This patch allows the uses of aspect/pragma SPARK_Mode in generic units. It also implements the following rule concerning the interplay between instances and SPARK_Mode "off":
However, if an instance of a generic unit is enclosed by code where SPARK_Mode is Off and if any SPARK_Mode specifications occur within the generic unit, then the corresponding SPARK_Mode specifications occurring within the instance have no semantic effect. ------------ -- Source -- ------------ -- pack_gen_pragmas.ads generic package Pack_Gen_Pragmas with SPARK_Mode => On is Var_1 : Integer := 1 with Volatile, Async_Readers, Effective_Reads; procedure Force_Body; private pragma SPARK_Mode (Off); Var_2 : Integer := 2 with Volatile, Async_Readers, Effective_Reads; end Pack_Gen_Pragmas; -- pack_gen_pragmas.adb package body Pack_Gen_Pragmas is procedure Force_Body is begin null; end Force_Body; end Pack_Gen_Pragmas; -- pack_pragmas_inst_4.ads with Pack_Gen_Pragmas; package Pack_Pragmas_Inst_4 is package Inst is new Pack_Gen_Pragmas with SPARK_Mode => Off; end Pack_Pragmas_Inst_4; -- pack_pragmas_inst_5.ads with Pack_Gen_Pragmas; package Pack_Pragmas_Inst_5 is new Pack_Gen_Pragmas; pragma SPARK_Mode (On); ---------------------------- -- Compilation and output -- ---------------------------- $ gcc -c pack_pragmas_inst_4.ads $ gcc -c pack_pragmas_inst_5.ads pack_pragmas_inst_5.ads:3:01: instantiation error at pack_gen_pragmas.ads:3 pack_pragmas_inst_5.ads:3:01: illegal combination of external properties (SPARK RM 7.1.2(6)) Tested on x86_64-pc-linux-gnu, committed on trunk 2014-08-04 Hristian Kirtchev <kirtc...@adacore.com> * opt.ads Alphabetize various global flags. New flag Ignore_Pragma_SPARK_Mode along with a comment on usage. * sem_ch6.adb (Analyze_Generic_Subprogram_Body): Pragma SPARK_Mode is now allowed in generic units. (Analyze_Subprogram_Body_Helper): Do not verify the compatibility between the SPARK_Mode of a spec and that of a body when inside a generic. * sem_ch7.adb (Analyze_Package_Body_Helper): Do not verify the compatibility between the SPARK_Mode of a spec and that of a body when inside a generic. * sem_ch12.adb (Analyze_Generic_Subprogram_Declaration): Pragma SPARK_Mode is now allowed in generic units. (Analyze_Package_Instantiation): Save and restore the value of flag Ignore_ Pragma_SPARK_Mode in a stack-like fasion. Set the governing SPARK_Mode before analyzing the instance. (Analyze_Subprogram_Instantiation): Save and restore the value of flag Ignore_ Pragma_SPARK_Mode in a stack-like fasion. Set the governing SPARK_Mode before analyzing the instance. * sem_ch13.adb (Analyze_Aspect_Specifications): Emulate the placement of a source pragma when inserting the generated pragma for aspect SPARK_Mode. * sem_prag.adb (Analyze_Pragma): Reimplement the handling of pragma SPARK_Mode to allow for generics and their respective instantiations. * sem_util.ads, sem_util.adb (Check_SPARK_Mode_In_Generic): Removed. (Set_Ignore_Pragma_SPARK_Mode): New routine.
Index: sem_ch7.adb =================================================================== --- sem_ch7.adb (revision 213553) +++ sem_ch7.adb (working copy) @@ -437,11 +437,9 @@ Inspect_Deferred_Constant_Completion (Declarations (N)); end if; - -- After declarations have been analyzed, the body has been set to have - -- the final value of SPARK_Mode. Check that the SPARK_Mode for the body - -- is consistent with the SPARK_Mode for the spec. + -- Verify that the SPARK_Mode of the body agrees with that of its spec - if Present (SPARK_Pragma (Body_Id)) then + if not Inside_A_Generic and then Present (SPARK_Pragma (Body_Id)) then if Present (SPARK_Aux_Pragma (Spec_Id)) then if Get_SPARK_Mode_From_Pragma (SPARK_Aux_Pragma (Spec_Id)) = Off and then Index: sem_prag.adb =================================================================== --- sem_prag.adb (revision 213566) +++ sem_prag.adb (working copy) @@ -19116,13 +19116,6 @@ -- pragma SPARK_Mode [(On | Off)]; when Pragma_SPARK_Mode => Do_SPARK_Mode : declare - Body_Id : Entity_Id; - Context : Node_Id; - Mode : Name_Id; - Mode_Id : SPARK_Mode_Type; - Spec_Id : Entity_Id; - Stmt : Node_Id; - procedure Check_Pragma_Conformance (Context_Pragma : Node_Id; Entity_Pragma : Node_Id; @@ -19163,7 +19156,7 @@ -- New mode less restrictive than the established mode if Get_SPARK_Mode_From_Pragma (Context_Pragma) = Off - and then Mode_Id = On + and then Get_SPARK_Mode_From_Pragma (N) = On then Error_Msg_N ("cannot change SPARK_Mode from Off to On", Arg1); @@ -19176,7 +19169,7 @@ if Present (Entity) then if Present (Entity_Pragma) then if Get_SPARK_Mode_From_Pragma (Entity_Pragma) = Off - and then Mode_Id = On + and then Get_SPARK_Mode_From_Pragma (N) = On then Error_Msg_N ("incorrect use of SPARK_Mode", Arg1); Error_Msg_Sloc := Sloc (Entity_Pragma); @@ -19224,9 +19217,36 @@ end if; end Check_Library_Level_Entity; + -- Local variables + + Body_Id : Entity_Id; + Context : Node_Id; + Inst_Id : Entity_Id; + Mode : Name_Id; + Mode_Id : SPARK_Mode_Type; + Spec_Id : Entity_Id; + Stmt : Node_Id; + -- Start of processing for Do_SPARK_Mode begin + -- When a SPARK_Mode pragma appears inside an instantiation whose + -- enclosing context has SPARK_Mode set to "off", the pragma has + -- no semantic effect. + + if Ignore_Pragma_SPARK_Mode then + Rewrite (N, Make_Null_Statement (Loc)); + Analyze (N); + return; + + -- Do not analyze the pragma when it appears inside a generic + -- because the semantic information of the related context is + -- scarce. + + elsif Inside_A_Generic then + return; + end if; + GNAT_Pragma; Check_No_Identifiers; Check_At_Most_N_Arguments (1); @@ -19243,15 +19263,15 @@ Mode_Id := Get_SPARK_Mode_Type (Mode); Context := Parent (N); - -- Packages and subprograms declared in a generic unit cannot be - -- subject to the pragma. + -- Handle a compilation unit with configuration pragmas - if Inside_A_Generic then - Error_Pragma ("incorrect placement of pragma% in a generic"); + if Nkind (Context) = N_Compilation_Unit_Aux then + Context := Parent (Context); + end if; -- The pragma appears in a configuration pragmas file - elsif No (Context) then + if No (Context) then Check_Valid_Configuration_Pragma; if Present (SPARK_Mode_Pragma) then @@ -19263,29 +19283,63 @@ SPARK_Mode_Pragma := N; SPARK_Mode := Mode_Id; - -- When the pragma is placed before the declaration of a unit, it - -- configures the whole unit. + -- The pragma applies to a compilation unit elsif Nkind (Context) = N_Compilation_Unit then - Check_Valid_Configuration_Pragma; - if Nkind (Unit (Context)) in N_Generic_Declaration - or else (Present (Library_Unit (Context)) - and then Nkind (Unit (Library_Unit (Context))) in - N_Generic_Declaration) - then - Error_Pragma ("incorrect placement of pragma% in a generic"); + -- The pragma acts as a configuration pragma + + -- pragma SPARK_Mode ...; + -- package Pack is ...; + + if List_Containing (N) = Context_Items (Context) then + Check_Valid_Configuration_Pragma; + SPARK_Mode_Pragma := N; + SPARK_Mode := Mode_Id; + + -- The pragma applies to a package instantiation that acts as a + -- compilation unit. + + -- package Inst is new Gen ...; + -- pragma SPARK_Mode ...; + + elsif Nkind (Unit (Context)) = N_Package_Instantiation then + Inst_Id := Defining_Entity (Instance_Spec (Unit (Context))); + Check_Library_Level_Entity (Inst_Id); + Check_Pragma_Conformance + (Context_Pragma => SPARK_Mode_Pragma, + Entity_Pragma => Empty, + Entity => Empty); + + Set_SPARK_Pragma (Inst_Id, N); + Set_SPARK_Pragma_Inherited (Inst_Id, False); + + -- Otherwise the pragma applies to a subprogram instantiation + -- that acts as a compilation unit. + + else + Spec_Id := Defining_Entity (Unit (Context)); + Inst_Id := Related_Instance (Spec_Id); + Check_Library_Level_Entity (Spec_Id); + Check_Pragma_Conformance + (Context_Pragma => SPARK_Mode_Pragma, + Entity_Pragma => Empty, + Entity => Empty); + + Set_SPARK_Pragma (Spec_Id, N); + Set_SPARK_Pragma_Inherited (Spec_Id, False); + + if Present (Inst_Id) then + Set_SPARK_Pragma (Inst_Id, N); + Set_SPARK_Pragma_Inherited (Inst_Id, False); + end if; end if; - SPARK_Mode_Pragma := N; - SPARK_Mode := Mode_Id; + -- Otherwise the placement of the pragma within the tree dictates + -- its associated construct. Inspect the declarative list where + -- the pragma resides to find a potential construct. - -- The pragma applies to a [library unit] subprogram or package - else - -- Verify the placement of the pragma with respect to package - -- or subprogram declarations and detect duplicates. - Stmt := Prev (N); while Present (Stmt) loop @@ -19299,28 +19353,32 @@ raise Pragma_Exit; end if; - elsif Nkind (Stmt) in N_Generic_Declaration then - Error_Pragma - ("incorrect placement of pragma% on a generic"); + -- The pragma is associated with a package or subprogram + -- instantiation that does not act as a compilation unit. - -- The pragma applies to a package declaration + -- package Inst is new Gen ...; + -- pragma SPARK_Mode ...; - elsif Nkind (Stmt) = N_Package_Declaration then - Spec_Id := Defining_Entity (Stmt); - Check_Library_Level_Entity (Spec_Id); + elsif Nkind_In (Stmt, N_Function_Instantiation, + N_Package_Instantiation, + N_Procedure_Instantiation) + then + Inst_Id := Defining_Entity (Instance_Spec (Stmt)); + Check_Library_Level_Entity (Inst_Id); Check_Pragma_Conformance - (Context_Pragma => SPARK_Pragma (Spec_Id), + (Context_Pragma => SPARK_Mode_Pragma, Entity_Pragma => Empty, Entity => Empty); - Set_SPARK_Pragma (Spec_Id, N); - Set_SPARK_Pragma_Inherited (Spec_Id, False); - Set_SPARK_Aux_Pragma (Spec_Id, N); - Set_SPARK_Aux_Pragma_Inherited (Spec_Id, True); + Set_SPARK_Pragma (Inst_Id, N); + Set_SPARK_Pragma_Inherited (Inst_Id, False); return; -- The pragma applies to a subprogram declaration + -- procedure Proc ...; + -- pragma SPARK_Mode ..; + elsif Nkind (Stmt) = N_Subprogram_Declaration then Spec_Id := Defining_Entity (Stmt); Check_Library_Level_Entity (Spec_Id); @@ -19338,8 +19396,9 @@ elsif not Comes_From_Source (Stmt) then null; - -- The pragma does not apply to a legal construct, issue an - -- error and stop the analysis. + -- Otherwise the pragma does not apply to a legal construct + -- or it does not appear at the top of a declarative or a + -- statement list. Issue an error and stop the analysis. else Pragma_Misplaced; @@ -19349,59 +19408,18 @@ Stmt := Prev (Stmt); end loop; - -- Handle all cases where the pragma is actually an aspect and - -- applies to a library-level package spec, body or subprogram. + -- The pragma appears within package declarations - -- function F ... with SPARK_Mode => ...; - -- package P with SPARK_Mode => ...; - -- package body P with SPARK_Mode => ... is - - -- The following circuitry simply prepares the proper context - -- for the general pragma processing mechanism below. - - if Nkind (Context) = N_Compilation_Unit_Aux then - Context := Unit (Parent (Context)); - - if Nkind_In (Context, N_Package_Declaration, - N_Subprogram_Declaration) - then - Context := Specification (Context); - end if; - end if; - - -- The pragma is at the top level of a package spec - - -- package P is - -- pragma SPARK_Mode; - - -- or - - -- package P is - -- ... - -- private - -- pragma SPARK_Mode; - if Nkind (Context) = N_Package_Specification then Spec_Id := Defining_Entity (Context); + Check_Library_Level_Entity (Spec_Id); - -- Pragma applies to private part + -- The pragma is at the top of the visible declarations - if List_Containing (N) = Private_Declarations (Context) then - Check_Library_Level_Entity (Spec_Id); - Check_Pragma_Conformance - (Context_Pragma => Empty, - Entity_Pragma => SPARK_Pragma (Spec_Id), - Entity => Spec_Id); - SPARK_Mode_Pragma := N; - SPARK_Mode := Mode_Id; + -- package Pack is + -- pragma SPARK_Mode ...; - Set_SPARK_Aux_Pragma (Spec_Id, N); - Set_SPARK_Aux_Pragma_Inherited (Spec_Id, False); - - -- Pragma applies to public part - - else - Check_Library_Level_Entity (Spec_Id); + if List_Containing (N) = Visible_Declarations (Context) then Check_Pragma_Conformance (Context_Pragma => SPARK_Pragma (Spec_Id), Entity_Pragma => Empty, @@ -19413,29 +19431,30 @@ Set_SPARK_Pragma_Inherited (Spec_Id, False); Set_SPARK_Aux_Pragma (Spec_Id, N); Set_SPARK_Aux_Pragma_Inherited (Spec_Id, True); - end if; - -- The pragma appears as an aspect on a subprogram. + -- The pragma is at the top of the private declarations - -- function F ... with SPARK_Mode => ...; + -- package Pack is + -- private + -- pragma SPARK_Mode ...; - elsif Nkind_In (Context, N_Function_Specification, - N_Procedure_Specification) - then - Spec_Id := Defining_Entity (Context); - Check_Library_Level_Entity (Spec_Id); - Check_Pragma_Conformance - (Context_Pragma => SPARK_Pragma (Spec_Id), - Entity_Pragma => Empty, - Entity => Empty); - Set_SPARK_Pragma (Spec_Id, N); - Set_SPARK_Pragma_Inherited (Spec_Id, False); + else + Check_Pragma_Conformance + (Context_Pragma => Empty, + Entity_Pragma => SPARK_Pragma (Spec_Id), + Entity => Spec_Id); + SPARK_Mode_Pragma := N; + SPARK_Mode := Mode_Id; - -- Pragma is immediately within a package body + Set_SPARK_Aux_Pragma (Spec_Id, N); + Set_SPARK_Aux_Pragma_Inherited (Spec_Id, False); + end if; - -- package body P is - -- pragma SPARK_Mode; + -- The pragma appears at the top of package body declarations + -- package body Pack is + -- pragma SPARK_Mode ...; + elsif Nkind (Context) = N_Package_Body then Spec_Id := Corresponding_Spec (Context); Body_Id := Defining_Entity (Context); @@ -19452,11 +19471,35 @@ Set_SPARK_Aux_Pragma (Body_Id, N); Set_SPARK_Aux_Pragma_Inherited (Body_Id, True); - -- Pragma is immediately within a subprogram body + -- The pragma appears at the top of package body statements - -- function F ... is + -- package body Pack is + -- begin -- pragma SPARK_Mode; + elsif Nkind (Context) = N_Handled_Sequence_Of_Statements + and then Nkind (Parent (Context)) = N_Package_Body + then + Context := Parent (Context); + Spec_Id := Corresponding_Spec (Context); + Body_Id := Defining_Entity (Context); + Check_Library_Level_Entity (Body_Id); + Check_Pragma_Conformance + (Context_Pragma => Empty, + Entity_Pragma => SPARK_Pragma (Body_Id), + Entity => Body_Id); + SPARK_Mode_Pragma := N; + SPARK_Mode := Mode_Id; + + Set_SPARK_Aux_Pragma (Body_Id, N); + Set_SPARK_Aux_Pragma_Inherited (Body_Id, False); + + -- The pragma appears at the top of subprogram body + -- declarations. + + -- procedure Proc ... is + -- pragma SPARK_Mode; + elsif Nkind (Context) = N_Subprogram_Body then Spec_Id := Corresponding_Spec (Context); Context := Specification (Context); @@ -19471,11 +19514,16 @@ Check_Library_Level_Entity (Body_Id); + -- The body is a completion of a previous declaration + if Present (Spec_Id) then Check_Pragma_Conformance (Context_Pragma => SPARK_Pragma (Body_Id), Entity_Pragma => SPARK_Pragma (Spec_Id), Entity => Spec_Id); + + -- The body acts as spec + else Check_Pragma_Conformance (Context_Pragma => SPARK_Pragma (Body_Id), @@ -19489,29 +19537,6 @@ Set_SPARK_Pragma (Body_Id, N); Set_SPARK_Pragma_Inherited (Body_Id, False); - -- The pragma applies to the statements of a package body - - -- package body P is - -- begin - -- pragma SPARK_Mode; - - elsif Nkind (Context) = N_Handled_Sequence_Of_Statements - and then Nkind (Parent (Context)) = N_Package_Body - then - Context := Parent (Context); - Spec_Id := Corresponding_Spec (Context); - Body_Id := Defining_Entity (Context); - Check_Library_Level_Entity (Body_Id); - Check_Pragma_Conformance - (Context_Pragma => Empty, - Entity_Pragma => SPARK_Pragma (Body_Id), - Entity => Body_Id); - SPARK_Mode_Pragma := N; - SPARK_Mode := Mode_Id; - - Set_SPARK_Aux_Pragma (Body_Id, N); - Set_SPARK_Aux_Pragma_Inherited (Body_Id, False); - -- The pragma does not apply to a legal construct, issue error else Index: sem_ch12.adb =================================================================== --- sem_ch12.adb (revision 213547) +++ sem_ch12.adb (working copy) @@ -3342,8 +3342,6 @@ Set_Parent_Spec (New_N, Save_Parent); Rewrite (N, New_N); - Check_SPARK_Mode_In_Generic (N); - -- The aspect specifications are not attached to the tree, and must -- be copied and attached to the generic copy explicitly. @@ -3532,6 +3530,9 @@ Needs_Body : Boolean; Inline_Now : Boolean := False; + Save_IPSM : constant Boolean := Ignore_Pragma_SPARK_Mode; + -- Save flag Ignore_Pragma_SPARK_Mode for restore on exit + Save_Style_Check : constant Boolean := Style_Check; -- Save style check mode for restore on exit @@ -3771,6 +3772,12 @@ goto Leave; else + -- If the instance or its context is subject to SPARK_Mode "off", + -- set the global flag which signals Analyze_Pragma to ignore all + -- SPARK_Mode pragmas within the instance. + + Set_Ignore_Pragma_SPARK_Mode (N); + Gen_Decl := Unit_Declaration_Node (Gen_Unit); -- Initialize renamings map, for error checking, and the list that @@ -3835,9 +3842,7 @@ Set_Visible_Declarations (Act_Spec, Renaming_List); end if; - Act_Decl := - Make_Package_Declaration (Loc, - Specification => Act_Spec); + Act_Decl := Make_Package_Declaration (Loc, Specification => Act_Spec); -- Propagate the aspect specifications from the package declaration -- template to the instantiated version of the package declaration. @@ -4277,6 +4282,7 @@ Set_Defining_Identifier (N, Act_Decl_Id); end if; + Ignore_Pragma_SPARK_Mode := Save_IPSM; Style_Check := Save_Style_Check; -- Check that if N is an instantiation of System.Dim_Float_IO or @@ -4311,6 +4317,7 @@ Restore_Env; end if; + Ignore_Pragma_SPARK_Mode := Save_IPSM; Style_Check := Save_Style_Check; end Analyze_Package_Instantiation; @@ -4865,6 +4872,9 @@ -- Local variables + Save_IPSM : constant Boolean := Ignore_Pragma_SPARK_Mode; + -- Save flag Ignore_Pragma_SPARK_Mode for restore on exit + Vis_Prims_List : Elist_Id := No_Elist; -- List of primitives made temporarily visible in the instantiation -- to match the visibility of the formal type @@ -4929,6 +4939,12 @@ Error_Msg_NE ("instantiation of & within itself", N, Gen_Unit); else + -- If the instance or its context is subject to SPARK_Mode "off", + -- set the global flag which signals Analyze_Pragma to ignore all + -- SPARK_Mode pragmas within the instance. + + Set_Ignore_Pragma_SPARK_Mode (N); + Set_Entity (Gen_Id, Gen_Unit); Set_Is_Instantiated (Gen_Unit); @@ -5139,6 +5155,8 @@ Env_Installed := False; Generic_Renamings.Set_Last (0); Generic_Renamings_HTable.Reset; + + Ignore_Pragma_SPARK_Mode := Save_IPSM; end if; <<Leave>> @@ -5155,6 +5173,8 @@ if Env_Installed then Restore_Env; end if; + + Ignore_Pragma_SPARK_Mode := Save_IPSM; end Analyze_Subprogram_Instantiation; ------------------------- Index: sem_util.adb =================================================================== --- sem_util.adb (revision 213568) +++ sem_util.adb (working copy) @@ -3078,31 +3078,6 @@ end if; end Check_Result_And_Post_State; - --------------------------------- - -- Check_SPARK_Mode_In_Generic -- - --------------------------------- - - procedure Check_SPARK_Mode_In_Generic (N : Node_Id) is - Aspect : Node_Id; - - begin - -- Try to find aspect SPARK_Mode and flag it as illegal - - if Has_Aspects (N) then - Aspect := First (Aspect_Specifications (N)); - while Present (Aspect) loop - if Get_Aspect_Id (Aspect) = Aspect_SPARK_Mode then - Error_Msg_Name_1 := Name_SPARK_Mode; - Error_Msg_N - ("incorrect placement of aspect % on a generic", Aspect); - exit; - end if; - - Next (Aspect); - end loop; - end if; - end Check_SPARK_Mode_In_Generic; - ------------------------------ -- Check_Unprotected_Access -- ------------------------------ @@ -16481,6 +16456,128 @@ Set_Entity (N, Val); end Set_Entity_With_Checks; + ---------------------------------- + -- Set_Ignore_Pragma_SPARK_Mode -- + ---------------------------------- + + procedure Set_Ignore_Pragma_SPARK_Mode (N : Node_Id) is + procedure Set_SPARK_Mode (Expr : Node_Id); + -- Set flag Ignore_Pragma_SPARK_Mode based on the argument of aspect or + -- pragma SPARK_Mode denoted by Expr. + + -------------------- + -- Set_SPARK_Mode -- + -------------------- + + procedure Set_SPARK_Mode (Expr : Node_Id) is + begin + -- When pragma SPARK_Mode with argument "off" applies to an instance, + -- all SPARK_Mode pragmas within the instance are ignored. + + if Present (Expr) + and then Nkind (Expr) = N_Identifier + and then Chars (Expr) = Name_Off + then + Ignore_Pragma_SPARK_Mode := True; + end if; + end Set_SPARK_Mode; + + -- Local variables + + Aspects : constant List_Id := Aspect_Specifications (N); + Context : constant Node_Id := Parent (N); + Args : List_Id; + Aspect : Node_Id; + Decl : Node_Id; + + -- Start of processing for Set_Ignore_Pragma_SPARK_Mode + + begin + -- When the enclosing context of the instance has SPARK_Mode "off", all + -- SPARK_Mode pragmas within the instance are ignored. Note that there + -- is no point in checking whether the instantiation itself carries + -- aspect/pragma SPARK_Mode because it is either illegal ("on") or has + -- no effect ("off"). + + if SPARK_Mode = Off then + Ignore_Pragma_SPARK_Mode := True; + return; + end if; + + -- Inspect the aspects of the instantiation and locate SPARK_Mode. Note + -- that the aspect form of SPARK_Mode precedes a potentially duplicate + -- pragma. + + if Present (Aspects) then + Aspect := First (Aspects); + while Present (Aspect) loop + if Get_Aspect_Id (Aspect) = Aspect_SPARK_Mode then + Set_SPARK_Mode (Expression (Aspect)); + return; + end if; + + Next (Aspect); + end loop; + end if; + + -- Peek ahead of the instance and locate pragma SPARK_Mode. Even though + -- the pragma is analyzed after the instance, its mode must be known now + -- as it governs the legality of SPARK_Mode pragmas within the instance. + + Decl := Empty; + + -- The instance is a compilation unit, the pragma appears on the + -- Pragmas_After list. + + if Present (Context) + and then Nkind (Context) = N_Compilation_Unit + and then Present (Aux_Decls_Node (Context)) + and then Present (Pragmas_After (Aux_Decls_Node (Context))) + then + Decl := First (Pragmas_After (Aux_Decls_Node (Context))); + + -- The instance is part of a declarative list, the pragma appears after + -- the instance. + + elsif Is_List_Member (N) then + Decl := Next (N); + end if; + + -- Inspect all declarations following the instance + + while Present (Decl) loop + if Nkind (Decl) = N_Pragma then + if Get_Pragma_Id (Decl) = Pragma_SPARK_Mode then + Args := Pragma_Argument_Associations (Decl); + + -- The pragma argument dictates the mode + + if Present (Args) then + Set_SPARK_Mode (Get_Pragma_Arg (First (Args))); + end if; + + -- Only the first SPARK_Mode following the instance is + -- considered, any extra (illegal) pragmas are ignored. + + exit; + end if; + + -- Skip internally generated code + + elsif not Comes_From_Source (Decl) then + null; + + -- Otherwise a source construct exhaust the range where the pragma + -- may appear. + + else + exit; + end if; + + Next (Decl); + end loop; + end Set_Ignore_Pragma_SPARK_Mode; + ------------------------ -- Set_Name_Entity_Id -- ------------------------ Index: sem_util.ads =================================================================== --- sem_util.ads (revision 213552) +++ sem_util.ads (working copy) @@ -327,10 +327,6 @@ -- and post-state. Prag is a [refined] postcondition or a contract-cases -- pragma. Result_Seen is set when the pragma mentions attribute 'Result. - procedure Check_SPARK_Mode_In_Generic (N : Node_Id); - -- Given a generic package [body] or a generic subprogram [body], inspect - -- the aspect specifications (if any) and flag SPARK_Mode as illegal. - procedure Check_Unprotected_Access (Context : Node_Id; Expr : Node_Id); @@ -1841,6 +1837,11 @@ -- If restriction No_Implementation_Identifiers is set, then it checks -- that the entity is not implementation defined. + procedure Set_Ignore_Pragma_SPARK_Mode (N : Node_Id); + -- Determine whether [the enclosing context of] package or subprogram N is + -- subject to pragma SPARK_Mode with mode "off". If this is the case, set + -- global flag Ignore_Pragma_SPARK_Mode to True. + procedure Set_Name_Entity_Id (Id : Name_Id; Val : Entity_Id); pragma Inline (Set_Name_Entity_Id); -- Sets the Entity_Id value associated with the given name, which is the Index: sem_ch6.adb =================================================================== --- sem_ch6.adb (revision 213537) +++ sem_ch6.adb (working copy) @@ -1251,8 +1251,6 @@ end loop; end; - Check_SPARK_Mode_In_Generic (N); - Set_SPARK_Pragma (Body_Id, SPARK_Mode_Pragma); Set_SPARK_Pragma_Inherited (Body_Id, True); @@ -3743,11 +3741,12 @@ Analyze_Declarations (Declarations (N)); - -- After declarations have been analyzed, the body has been set - -- its final value of SPARK_Mode. Check that SPARK_Mode for body - -- is consistent with SPARK_Mode for spec. + -- Verify that the SPARK_Mode of the body agrees with that of its spec - if Present (Spec_Id) and then Present (SPARK_Pragma (Body_Id)) then + if not Inside_A_Generic + and then Present (Spec_Id) + and then Present (SPARK_Pragma (Body_Id)) + then if Present (SPARK_Pragma (Spec_Id)) then if Get_SPARK_Mode_From_Pragma (SPARK_Pragma (Spec_Id)) = Off and then @@ -3757,7 +3756,7 @@ Error_Msg_N ("incorrect application of SPARK_Mode#", N); Error_Msg_Sloc := Sloc (SPARK_Pragma (Spec_Id)); Error_Msg_NE - ("\value Off was set for SPARK_Mode on&#", N, Spec_Id); + ("\value Off was set for SPARK_Mode on & #", N, Spec_Id); end if; elsif Nkind (Parent (Parent (Spec_Id))) = N_Subprogram_Body_Stub then @@ -3767,7 +3766,8 @@ Error_Msg_Sloc := Sloc (SPARK_Pragma (Body_Id)); Error_Msg_N ("incorrect application of SPARK_Mode#", N); Error_Msg_Sloc := Sloc (Spec_Id); - Error_Msg_NE ("\no value was set for SPARK_Mode on&#", N, Spec_Id); + Error_Msg_NE + ("\no value was set for SPARK_Mode on & #", N, Spec_Id); end if; end if; Index: opt.ads =================================================================== --- opt.ads (revision 213536) +++ opt.ads (working copy) @@ -648,6 +648,20 @@ -- GNAT -- Disable generation of ALI file + Follow_Links_For_Files : Boolean := False; + -- PROJECT MANAGER + -- Set to True (-eL) to process the project files in trusted mode. If + -- Follow_Links is False, it is assumed that the project doesn't contain + -- any file duplicated through symbolic links (although the latter are + -- still valid if they point to a file which is outside of the project), + -- and that no directory has a name which is a valid source name. + + Follow_Links_For_Dirs : Boolean := False; + -- PROJECT MANAGER + -- Set to True if directories can be links in this project, and therefore + -- additional system calls must be performed to ensure that we always see + -- the same full name for each directory. + Force_Checking_Of_Elaboration_Flags : Boolean := False; -- GNATBIND -- True if binding with forced checking of the elaboration flags @@ -657,6 +671,13 @@ -- GNATMAKE, GPRMAKE, GPRBUILD -- Set to force recompilations even when the objects are up-to-date. + Front_End_Inlining : Boolean := False; + -- GNAT + -- Set True to activate inlining by front-end expansion (even on GCC + -- targets, where inlining is normally handled by the back end). Set by + -- the flag -gnatN (which is now considered obsolescent, since the GCC + -- back end can do a better job of inlining than the front end these days. + Full_Path_Name_For_Brief_Errors : Boolean := False; -- PROJECT MANAGER -- When True, in Brief_Output mode, each error message line @@ -684,6 +705,10 @@ -- True when switch -gnateG is used. When True, create in a file -- <source>.prep, if the source is preprocessed. + Generate_SCIL : Boolean := False; + -- GNAT + -- Set True to activate SCIL code generation. + Generate_SCO : Boolean := False; -- GNAT -- True when switch -fdump-scos (or -gnateS) is used. When True, Source @@ -728,6 +753,12 @@ -- default value appropriate to the system (in Osint.Initialize), and then -- reset if a command line switch is used to change the setting. + Ignore_Pragma_SPARK_Mode : Boolean := False; + -- GNAT + -- Set True to ignore the semantics and effects of pragma SPARK_Mode when + -- the pragma appears inside an instance whose enclosing context is subject + -- to SPARK_Mode "off". + Ignore_Rep_Clauses : Boolean := False; -- GNAT -- Set True to ignore all representation clauses. Useful when compiling @@ -798,35 +829,10 @@ -- then elaboration flag checks are to be generated in the binder -- generated file. - Generate_SCIL : Boolean := False; - -- GNAT - -- Set True to activate SCIL code generation. - Invalid_Value_Used : Boolean := False; -- GNAT -- Set True if a valid Invalid_Value attribute is encountered - Follow_Links_For_Files : Boolean := False; - -- PROJECT MANAGER - -- Set to True (-eL) to process the project files in trusted mode. If - -- Follow_Links is False, it is assumed that the project doesn't contain - -- any file duplicated through symbolic links (although the latter are - -- still valid if they point to a file which is outside of the project), - -- and that no directory has a name which is a valid source name. - - Follow_Links_For_Dirs : Boolean := False; - -- PROJECT MANAGER - -- Set to True if directories can be links in this project, and therefore - -- additional system calls must be performed to ensure that we always see - -- the same full name for each directory. - - Front_End_Inlining : Boolean := False; - -- GNAT - -- Set True to activate inlining by front-end expansion (even on GCC - -- targets, where inlining is normally handled by the back end). Set by - -- the flag -gnatN (which is now considered obsolescent, since the GCC - -- back end can do a better job of inlining than the front end these days. - Inline_Processing_Required : Boolean := False; -- GNAT -- Set True if inline processing is required. Inline processing is required Index: sem_ch13.adb =================================================================== --- sem_ch13.adb (revision 213552) +++ sem_ch13.adb (working copy) @@ -2418,11 +2418,11 @@ Expression => Relocate_Node (Expr))), Pragma_Name => Name_SPARK_Mode); - -- When the aspect appears on a package body, insert the - -- generated pragma at the top of the body declarations to - -- emulate the behavior of a source pragma. + -- When the aspect appears on a package or a subprogram + -- body, insert the generated pragma at the top of the body + -- declarations to emulate the behavior of a source pragma. - if Nkind (N) = N_Package_Body then + if Nkind_In (N, N_Package_Body, N_Subprogram_Body) then Decorate (Aspect, Aitem); Decls := Declarations (N); @@ -2435,11 +2435,14 @@ Prepend_To (Decls, Aitem); goto Continue; - -- When the aspect is associated with package declaration, - -- insert the generated pragma at the top of the visible - -- declarations to emulate the behavior of a source pragma. + -- When the aspect is associated with a [generic] package + -- declaration, insert the generated pragma at the top of + -- the visible declarations to emulate the behavior of a + -- source pragma. - elsif Nkind (N) = N_Package_Declaration then + elsif Nkind_In (N, N_Generic_Package_Declaration, + N_Package_Declaration) + then Decorate (Aspect, Aitem); Decls := Visible_Declarations (Specification (N));