This patch ensures that all delayed SPARK aspects are analyzed with the proper
SPARK mode of their related construct.

------------
-- Source --
------------

--  modes.ads

package Modes
  with SPARK_Mode => On,
       Abstract_State => State
is
   Var : Integer := 1;

   procedure Disabled_1 (Formal : Integer)
     with SPARK_Mode => Off,
          Global  => (Input => (Formal, State, Var)),  --  suppressed
          Depends => (null  => (Formal, Var));         --  suppressed

   procedure Enabled_1 (Formal : Integer)
     with SPARK_Mode => On,
          Global  => (Input => (Formal, State, Var)),  --  error
          Depends => (null  => (Formal, Var));         --  error
end Modes;

----------------------------
-- Compilation and output --
----------------------------

$ gcc -c modes.ads
modes.ads:14:33: global item cannot reference parameter of subprogram
modes.ads:14:41: state "State" must appear in at least one input dependence
  list

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

2014-07-17  Hristian Kirtchev  <kirtc...@adacore.com>

        * sem_ch6.adb (Analyze_Subprogram_Body_Contract,
        Analyze_Subprogram_Contract): Add new local variable Mode. Save
        and restore the SPARK mode of the related construct in a
        stack-like fashion.
        * sem_ch7.adb (Analyze_Package_Body_Contract,
        Analyze_Package_Contract): Add new local variable Mode. Save and
        restore the SPARK mode of the related construct in a stack-like fashion.
        * sem_util.adb Remove with and use clause for Opt.
        (Restore_SPARK_Mode): New routine.
        (Save_SPARK_Mode_And_Set): New routine.
        * sem_util.ads Add with and use clause for Opt.
        (Restore_SPARK_Mode): New routine.
        (Save_SPARK_Mode_And_Set): New routine.

Index: sem_ch7.adb
===================================================================
--- sem_ch7.adb (revision 212640)
+++ sem_ch7.adb (working copy)
@@ -180,9 +180,12 @@
 
    procedure Analyze_Package_Body_Contract (Body_Id : Entity_Id) is
       Spec_Id : constant Entity_Id := Spec_Entity (Body_Id);
+      Mode    : SPARK_Mode_Type;
       Prag    : Node_Id;
 
    begin
+      Save_SPARK_Mode_And_Set (Body_Id, Mode);
+
       Prag := Get_Pragma (Body_Id, Pragma_Refined_State);
 
       --  The analysis of pragma Refined_State detects whether the spec has
@@ -200,6 +203,8 @@
       then
          Error_Msg_N ("package & requires state refinement", Spec_Id);
       end if;
+
+      Restore_SPARK_Mode (Mode);
    end Analyze_Package_Body_Contract;
 
    ---------------------------------
@@ -839,9 +844,12 @@
    ------------------------------
 
    procedure Analyze_Package_Contract (Pack_Id : Entity_Id) is
+      Mode : SPARK_Mode_Type;
       Prag : Node_Id;
 
    begin
+      Save_SPARK_Mode_And_Set (Pack_Id, Mode);
+
       --  Analyze the initialization related pragmas. Initializes must come
       --  before Initial_Condition due to item dependencies.
 
@@ -867,6 +875,8 @@
             Check_Missing_Part_Of (Pack_Id);
          end if;
       end if;
+
+      Restore_SPARK_Mode (Mode);
    end Analyze_Package_Contract;
 
    ---------------------------------
Index: sem_util.adb
===================================================================
--- sem_util.adb        (revision 212656)
+++ sem_util.adb        (working copy)
@@ -41,7 +41,6 @@
 with Nlists;   use Nlists;
 with Nmake;    use Nmake;
 with Output;   use Output;
-with Opt;      use Opt;
 with Restrict; use Restrict;
 with Rident;   use Rident;
 with Rtsfind;  use Rtsfind;
@@ -15321,6 +15320,15 @@
       Reset_Analyzed (N);
    end Reset_Analyzed_Flags;
 
+   ------------------------
+   -- Restore_SPARK_Mode --
+   ------------------------
+
+   procedure Restore_SPARK_Mode (Mode : SPARK_Mode_Type) is
+   begin
+      SPARK_Mode := Mode;
+   end Restore_SPARK_Mode;
+
    --------------------------------
    -- Returns_Unconstrained_Type --
    --------------------------------
@@ -15624,6 +15632,28 @@
       end if;
    end Same_Value;
 
+   -----------------------------
+   -- Save_SPARK_Mode_And_Set --
+   -----------------------------
+
+   procedure Save_SPARK_Mode_And_Set
+     (Context : Entity_Id;
+      Mode    : out SPARK_Mode_Type)
+   is
+      Prag : constant Node_Id := SPARK_Pragma (Context);
+
+   begin
+      --  Save the current mode in effect
+
+      Mode := SPARK_Mode;
+
+      --  Set the mode of the context as the current SPARK mode
+
+      if Present (Prag) then
+         SPARK_Mode := Get_SPARK_Mode_From_Pragma (Prag);
+      end if;
+   end Save_SPARK_Mode_And_Set;
+
    ------------------------
    -- Scope_Is_Transient --
    ------------------------
Index: sem_util.ads
===================================================================
--- sem_util.ads        (revision 212640)
+++ sem_util.ads        (working copy)
@@ -28,6 +28,7 @@
 with Einfo;   use Einfo;
 with Exp_Tss; use Exp_Tss;
 with Namet;   use Namet;
+with Opt;     use Opt;
 with Snames;  use Snames;
 with Types;   use Types;
 with Uintp;   use Uintp;
@@ -1689,6 +1690,10 @@
    procedure Reset_Analyzed_Flags (N : Node_Id);
    --  Reset the Analyzed flags in all nodes of the tree whose root is N
 
+   procedure Restore_SPARK_Mode (Mode : SPARK_Mode_Type);
+   --  Set the current SPARK_Mode to whatever Mode denotes. This routime must
+   --  be used in tandem with Save_SPARK_Mode_And_Set.
+
    function Returns_Unconstrained_Type (Subp : Entity_Id) return Boolean;
    --  Return true if Subp is a function that returns an unconstrained type
 
@@ -1740,6 +1745,13 @@
    --  A result of False does not necessarily mean they have different values,
    --  just that it is not possible to determine they have the same value.
 
+   procedure Save_SPARK_Mode_And_Set
+     (Context : Entity_Id;
+      Mode    : out SPARK_Mode_Type);
+   --  Save the current SPARK_Mode in effect in Mode. Establish the SPARK_Mode
+   --  (if any) of a package or a subprogram denoted by Context. This routine
+   --  must be used in tandem with Restore_SPARK_Mode.
+
    function Scope_Within_Or_Same (Scope1, Scope2 : Entity_Id) return Boolean;
    --  Determines if the entity Scope1 is the same as Scope2, or if it is
    --  inside it, where both entities represent scopes. Note that scopes
Index: sem_ch6.adb
===================================================================
--- sem_ch6.adb (revision 212640)
+++ sem_ch6.adb (working copy)
@@ -2033,12 +2033,15 @@
 
    procedure Analyze_Subprogram_Body_Contract (Body_Id : Entity_Id) is
       Body_Decl   : constant Node_Id := Parent (Parent (Body_Id));
+      Mode        : SPARK_Mode_Type;
       Prag        : Node_Id;
       Ref_Depends : Node_Id := Empty;
       Ref_Global  : Node_Id := Empty;
       Spec_Id     : Entity_Id;
 
    begin
+      Save_SPARK_Mode_And_Set (Body_Id, Mode);
+
       --  When a subprogram body declaration is illegal, its defining entity is
       --  left unanalyzed. There is nothing left to do in this case because the
       --  body lacks a contract, or even a proper Ekind.
@@ -2112,6 +2115,8 @@
                Body_Decl, Spec_Id);
          end if;
       end if;
+
+      Restore_SPARK_Mode (Mode);
    end Analyze_Subprogram_Body_Contract;
 
    ------------------------------------
@@ -3680,6 +3685,7 @@
       Case_Prag    : Node_Id := Empty;
       Depends      : Node_Id := Empty;
       Global       : Node_Id := Empty;
+      Mode         : SPARK_Mode_Type;
       Nam          : Name_Id;
       Post_Prag    : Node_Id := Empty;
       Prag         : Node_Id;
@@ -3687,6 +3693,8 @@
       Seen_In_Post : Boolean := False;
 
    begin
+      Save_SPARK_Mode_And_Set (Subp, Mode);
+
       if Present (Items) then
 
          --  Analyze pre- and postconditions
@@ -3808,6 +3816,8 @@
               ("function postcondition does not mention result?T?", Post_Prag);
          end if;
       end if;
+
+      Restore_SPARK_Mode (Mode);
    end Analyze_Subprogram_Contract;
 
    ------------------------------------

Reply via email to