This patch implements SPARK property "effectively volatile" which states:

   In SPARK 2014, the terms volatile type and volatile object are defined as
   per Ada RM C.6(8/3). An effectively volatile type is a volatile type or an
   array type to which the Volatile_Components aspect has been applied. An
   effectively volatile object is a volatile object or an object of an array
   type to which Volatile_Components has been applied.

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

--  volatile_comps.ads

package Volatile_Comps with SPARK_Mode is
   type I is range 1 .. 10;

   type VC_Array  is array (I) of Integer with Volatile_Components;
   type NVC_Array is array (I) of Integer;

   Obj_1 : VC_Array  with Async_Readers;
   Obj_2 : VC_Array  with Async_Readers, Effective_Reads;
   Obj_3 : NVC_Array with Volatile, Async_Readers;
   Obj_4 : NVC_Array with Volatile, Async_Readers, Effective_Reads;
end Volatile_Comps;

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

$ gcc -c volatile_comps.ads
volatile_comps.ads:8:04: illegal combination of external properties (SPARK RM
  7.1.2(6))
volatile_comps.ads:10:04: illegal combination of external properties (SPARK RM
  7.1.2(6))

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

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

        * freeze.adb (Freeze_Record_Type): Replace all calls to
        Is_SPARK_Volatile with Is_Effectively_Volatile and update
        related comments.
        * sem_ch3.adb (Analyze_Object_Contract, Process_Discriminants):
        Replace all calls to Is_SPARK_Volatile with
        Is_Effectively_Volatile and update related comments.
        * sem_ch5.adb (Analyze_Iterator_Specification,
        Analyze_Loop_Parameter_Specification): Replace all calls to
        Is_SPARK_Volatile with Is_Effectively_Volatile and update
        related comments.
        * sem_ch6.adb (Process_Formals): Replace all calls to
        Is_SPARK_Volatile with Is_Effectively_Volatile and update
        related comments.
        * sem_ch12.adb (Instantiate_Object): Replace the call to
        Is_SPARK_Volatile_Object with Is_Effectively_Volatile_Object
        and update related comment.
        * sem_prag.adb (Analyze_External_Property_In_Decl_Part,
        Analyze_Global_Item): Replace all calls to Is_SPARK_Volatile
        with Is_Effectively_Volatile and update related comments.
        * sem_res.adb (Resolve_Actuals, Resolve_Entity_Name): Replace
        all calls to Is_SPARK_Volatile with Is_Effectively_Volatile and
        update related comments.
        * sem_util.adb (Has_Enabled_Property,
        Variable_Has_Enabled_Property): Replace all calls
        to Is_SPARK_Volatile with Is_Effectively_Volatile and
        update related comments.
        (Is_Effectively_Volatile): New routine.
        (Is_Effectively_Volatile_Object): New routine.
        (Is_SPARK_Volatile): Removed.
        (Is_SPARK_Volatile_Object): Removed.
        * sem_util.ads (Is_Effectively_Volatile): New routine.
        (Is_Effectively_Volatile_Object): New routine.
        (Is_SPARK_Volatile): Removed.
        (Is_SPARK_Volatile_Object): Removed.

Index: freeze.adb
===================================================================
--- freeze.adb  (revision 213350)
+++ freeze.adb  (working copy)
@@ -3472,27 +3472,29 @@
          --  they are not standard Ada legality rules.
 
          if SPARK_Mode = On then
-            if Is_SPARK_Volatile (Rec) then
+            if Is_Effectively_Volatile (Rec) then
 
-               --  A discriminated type cannot be volatile (SPARK RM C.6(4))
+               --  A discriminated type cannot be effectively volatile
+               --  (SPARK RM C.6(4)).
 
                if Has_Discriminants (Rec) then
                   Error_Msg_N ("discriminated type & cannot be volatile", Rec);
 
-               --  A tagged type cannot be volatile (SPARK RM C.6(5))
+               --  A tagged type cannot be effectively volatile
+               --  (SPARK RM C.6(5)).
 
                elsif Is_Tagged_Type (Rec) then
                   Error_Msg_N ("tagged type & cannot be volatile", Rec);
                end if;
 
-            --  A non-volatile record type cannot contain volatile components
-            --  (SPARK RM C.6(2))
+            --  A non-effectively volatile record type cannot contain
+            --  effectively volatile components (SPARK RM C.6(2)).
 
             else
                Comp := First_Component (Rec);
                while Present (Comp) loop
                   if Comes_From_Source (Comp)
-                    and then Is_SPARK_Volatile (Etype (Comp))
+                    and then Is_Effectively_Volatile (Etype (Comp))
                   then
                      Error_Msg_Name_1 := Chars (Rec);
                      Error_Msg_N
Index: sem_ch12.adb
===================================================================
--- sem_ch12.adb        (revision 213263)
+++ sem_ch12.adb        (working copy)
@@ -9905,13 +9905,13 @@
            ("actual must exclude null to match generic formal#", Actual);
       end if;
 
-      --  A volatile object cannot be used as an actual in a generic instance.
-      --  The following check is only relevant when SPARK_Mode is on as it is
-      --  not a standard Ada legality rule.
+      --  An effectively volatile object cannot be used as an actual in
+      --  a generic instance. The following check is only relevant when
+      --  SPARK_Mode is on as it is not a standard Ada legality rule.
 
       if SPARK_Mode = On
         and then Present (Actual)
-        and then Is_SPARK_Volatile_Object (Actual)
+        and then Is_Effectively_Volatile_Object (Actual)
       then
          Error_Msg_N
            ("volatile object cannot act as actual in generic instantiation "
Index: sem_ch3.adb
===================================================================
--- sem_ch3.adb (revision 213351)
+++ sem_ch3.adb (working copy)
@@ -3018,13 +3018,13 @@
    begin
       if Ekind (Obj_Id) = E_Constant then
 
-         --  A constant cannot be volatile. This check is only relevant when
-         --  SPARK_Mode is on as it is not standard Ada legality rule. Do not
-         --  flag internally-generated constants that map generic formals to
-         --  actuals in instantiations (SPARK RM 7.1.3(6)).
+         --  A constant cannot be effectively volatile. This check is only
+         --  relevant with SPARK_Mode on as it is not a standard Ada legality
+         --  rule. Do not flag internally-generated constants that map generic
+         --  formals to actuals in instantiations (SPARK RM 7.1.3(6)).
 
          if SPARK_Mode = On
-           and then Is_SPARK_Volatile (Obj_Id)
+           and then Is_Effectively_Volatile (Obj_Id)
            and then No (Corresponding_Generic_Association (Parent (Obj_Id)))
          then
             Error_Msg_N ("constant cannot be volatile", Obj_Id);
@@ -3036,37 +3036,37 @@
          --  they are not standard Ada legality rules.
 
          if SPARK_Mode = On then
-            if Is_SPARK_Volatile (Obj_Id) then
+            if Is_Effectively_Volatile (Obj_Id) then
 
-               --  The declaration of a volatile object must appear at the
-               --  library level (SPARK RM 7.1.3(7), C.6(6)).
+               --  The declaration of an effectively volatile object must
+               --  appear at the library level (SPARK RM 7.1.3(7), C.6(6)).
 
                if not Is_Library_Level_Entity (Obj_Id) then
                   Error_Msg_N
                     ("volatile variable & must be declared at library level",
                      Obj_Id);
 
-               --  An object of a discriminated type cannot be volatile
-               --  (SPARK RM C.6(4)).
+               --  An object of a discriminated type cannot be effectively
+               --  volatile (SPARK RM C.6(4)).
 
                elsif Has_Discriminants (Obj_Typ) then
                   Error_Msg_N
                     ("discriminated object & cannot be volatile", Obj_Id);
 
-               --  An object of a tagged type cannot be volatile
+               --  An object of a tagged type cannot be effectively volatile
                --  (SPARK RM C.6(5)).
 
                elsif Is_Tagged_Type (Obj_Typ) then
                   Error_Msg_N ("tagged object & cannot be volatile", Obj_Id);
                end if;
 
-            --  The object is not volatile
+            --  The object is not effectively volatile
 
             else
-               --  A non-volatile object cannot have volatile components
-               --  (SPARK RM 7.1.3(7)).
+               --  A non-effectively volatile object cannot have effectively
+               --  volatile components (SPARK RM 7.1.3(7)).
 
-               if not Is_SPARK_Volatile (Obj_Id)
+               if not Is_Effectively_Volatile (Obj_Id)
                  and then Has_Volatile_Component (Obj_Typ)
                then
                   Error_Msg_N
@@ -18123,12 +18123,12 @@
             end if;
          end if;
 
-         --  A discriminant cannot be volatile. This check is only relevant
-         --  when SPARK_Mode is on as it is not standard Ada legality rule
-         --  (SPARK RM 7.1.3(6)).
+         --  A discriminant cannot be effectively volatile. This check is only
+         --  relevant when SPARK_Mode is on as it is not standard Ada legality
+         --  rule (SPARK RM 7.1.3(6)).
 
          if SPARK_Mode = On
-           and then Is_SPARK_Volatile (Defining_Identifier (Discr))
+           and then Is_Effectively_Volatile (Defining_Identifier (Discr))
          then
             Error_Msg_N ("discriminant cannot be volatile", Discr);
          end if;
Index: sem_ch5.adb
===================================================================
--- sem_ch5.adb (revision 213333)
+++ sem_ch5.adb (working copy)
@@ -2007,16 +2007,16 @@
          end if;
       end if;
 
-      --  A loop parameter cannot be volatile. This check is peformed only
-      --  when SPARK_Mode is on as it is not a standard Ada legality check
-      --  (SPARK RM 7.1.3(6)).
+      --  A loop parameter cannot be effectively volatile. This check is
+      --  peformed only when SPARK_Mode is on as it is not a standard Ada
+      --  legality check (SPARK RM 7.1.3(6)).
 
       --  Not clear whether this applies to element iterators, where the
       --  cursor is not an explicit entity ???
 
       if SPARK_Mode = On
         and then not Of_Present (N)
-        and then Is_SPARK_Volatile (Ent)
+        and then Is_Effectively_Volatile (Ent)
       then
          Error_Msg_N ("loop parameter cannot be volatile", Ent);
       end if;
@@ -2732,11 +2732,11 @@
          end;
       end if;
 
-      --  A loop parameter cannot be volatile. This check is peformed only
-      --  when SPARK_Mode is on as it is not a standard Ada legality check
-      --  (SPARK RM 7.1.3(6)).
+      --  A loop parameter cannot be effectively volatile. This check is
+      --  peformed only when SPARK_Mode is on as it is not a standard Ada
+      --  legality check (SPARK RM 7.1.3(6)).
 
-      if SPARK_Mode = On and then Is_SPARK_Volatile (Id) then
+      if SPARK_Mode = On and then Is_Effectively_Volatile (Id) then
          Error_Msg_N ("loop parameter cannot be volatile", Id);
       end if;
    end Analyze_Loop_Parameter_Specification;
Index: sem_ch6.adb
===================================================================
--- sem_ch6.adb (revision 213338)
+++ sem_ch6.adb (working copy)
@@ -10095,21 +10095,22 @@
                     ("function cannot have parameter of mode `OUT` or "
                      & "`IN OUT`", Formal);
 
-               --  A function cannot have a volatile formal parameter
-               --  (SPARK RM 7.1.3(10)).
+               --  A function cannot have an effectively volatile formal
+               --  parameter (SPARK RM 7.1.3(10)).
 
-               elsif Is_SPARK_Volatile (Formal) then
+               elsif Is_Effectively_Volatile (Formal) then
                   Error_Msg_N
                     ("function cannot have a volatile formal parameter",
                      Formal);
                end if;
 
-            --  A procedure cannot have a formal parameter of mode IN because
-            --  it behaves as a constant (SPARK RM 7.1.3(6)).
+            --  A procedure cannot have an effectively volatile formal
+            --  parameter of mode IN because it behaves as a constant
+            --  (SPARK RM 7.1.3(6)).
 
             elsif Ekind (Scope (Formal)) = E_Procedure
               and then Ekind (Formal) = E_In_Parameter
-              and then Is_SPARK_Volatile (Formal)
+              and then Is_Effectively_Volatile (Formal)
             then
                Error_Msg_N
                  ("formal parameter of mode `IN` cannot be volatile", Formal);
Index: sem_prag.adb
===================================================================
--- sem_prag.adb        (revision 213351)
+++ sem_prag.adb        (working copy)
@@ -1830,16 +1830,16 @@
    begin
       Error_Msg_Name_1 := Pragma_Name (N);
 
-      --  An external property pragma must apply to a volatile object other
-      --  than a formal subprogram parameter (SPARK RM 7.1.3(2)). The check
-      --  is performed at the end of the declarative region due to a possible
-      --  out-of-order arrangement of pragmas:
+      --  An external property pragma must apply to an effectively volatile
+      --  object other than a formal subprogram parameter (SPARK RM 7.1.3(2)).
+      --  The check is performed at the end of the declarative region due to a
+      --  possible out-of-order arrangement of pragmas:
 
       --    Obj : ...;
       --    pragma Async_Readers (Obj);
       --    pragma Volatile (Obj);
 
-      if not Is_SPARK_Volatile (Obj_Id) then
+      if not Is_Effectively_Volatile (Obj_Id) then
          SPARK_Msg_N
            ("external property % must apply to a volatile object", N);
       end if;
@@ -2021,19 +2021,21 @@
                --  SPARK_Mode is on as they are not standard Ada legality
                --  rules.
 
-               elsif SPARK_Mode = On and then Is_SPARK_Volatile (Item_Id) then
+               elsif SPARK_Mode = On
+                 and then Is_Effectively_Volatile (Item_Id)
+               then
+                  --  An effectively volatile object cannot appear as a global
+                  --  item of a function (SPARK RM 7.1.3(9)).
 
-                  --  A volatile object cannot appear as a global item of a
-                  --  function (SPARK RM 7.1.3(9)).
-
                   if Ekind_In (Spec_Id, E_Function, E_Generic_Function) then
                      Error_Msg_NE
                        ("volatile object & cannot act as global item of a "
                         & "function", Item, Item_Id);
                      return;
 
-                  --  A volatile object with property Effective_Reads set to
-                  --  True must have mode Output or In_Out.
+                  --  An effectively volatile object with external property
+                  --  Effective_Reads set to True must have mode Output or
+                  --  In_Out.
 
                   elsif Effective_Reads_Enabled (Item_Id)
                     and then Global_Mode = Name_Input
Index: sem_res.adb
===================================================================
--- sem_res.adb (revision 213299)
+++ sem_res.adb (working copy)
@@ -4329,18 +4329,19 @@
             --  they are not standard Ada legality rule.
 
             if SPARK_Mode = On
-              and then Is_SPARK_Volatile_Object (A)
+              and then Is_Effectively_Volatile_Object (A)
             then
-               --  A volatile object may act as an actual parameter when the
-               --  corresponding formal is of a non-scalar volatile type.
+               --  An effectively volatile object may act as an actual
+               --  parameter when the corresponding formal is of a non-scalar
+               --  volatile type.
 
                if Is_Volatile (Etype (F))
                  and then not Is_Scalar_Type (Etype (F))
                then
                   null;
 
-               --  A volatile object may act as an actual parameter in a call
-               --  to an instance of Unchecked_Conversion.
+               --  An effectively volatile object may act as an actual
+               --  parameter in a call to an instance of Unchecked_Conversion.
 
                elsif Is_Unchecked_Conversion_Instance (Nam) then
                   null;
@@ -6785,33 +6786,33 @@
          Eval_Entity_Name (N);
       end if;
 
-      --  A volatile object subject to enabled properties Async_Writers or
-      --  Effective_Reads must appear in a specific context. The following
-      --  checks are only relevant when SPARK_Mode is on as they are not
-      --  standard Ada legality rules.
+      --  An effectively volatile object subject to enabled properties
+      --  Async_Writers or Effective_Reads must appear in a specific context.
+      --  The following checks are only relevant when SPARK_Mode is on as they
+      --  are not standard Ada legality rules.
 
       if SPARK_Mode = On
         and then Is_Object (E)
-        and then Is_SPARK_Volatile (E)
+        and then Is_Effectively_Volatile (E)
         and then Comes_From_Source (E)
         and then
           (Async_Writers_Enabled (E) or else Effective_Reads_Enabled (E))
       then
-         --  The volatile objects appears in a "non-interfering context" as
-         --  defined in SPARK RM 7.1.3(13).
+         --  The effectively volatile objects appears in a "non-interfering
+         --  context" as defined in SPARK RM 7.1.3(13).
 
          if Is_OK_Volatile_Context (Par, N) then
             null;
 
-         --  Assume that references to volatile objects that appear as actual
-         --  parameters in a procedure call are always legal. The full legality
-         --  check is done when the actuals are resolved.
+         --  Assume that references to effectively volatile objects that appear
+         --  as actual parameters in a procedure call are always legal. The
+         --  full legality check is done when the actuals are resolved.
 
          elsif Nkind (Par) = N_Procedure_Call_Statement then
             null;
 
          --  Otherwise the context causes a side effect with respect to the
-         --  volatile object.
+         --  effectively volatile object.
 
          else
             Error_Msg_N
Index: sem_util.adb
===================================================================
--- sem_util.adb        (revision 213345)
+++ sem_util.adb        (working copy)
@@ -7605,9 +7605,10 @@
       --  Start of processing for Variable_Has_Enabled_Property
 
       begin
-         --  A non-volatile object can never possess external properties
+         --  A non-effectively volatile object can never possess external
+         --  properties.
 
-         if not Is_SPARK_Volatile (Item_Id) then
+         if not Is_Effectively_Volatile (Item_Id) then
             return False;
 
          --  External properties related to variables come in two flavors -
@@ -7650,10 +7651,11 @@
       elsif Ekind (Item_Id) = E_Variable then
          return Variable_Has_Enabled_Property;
 
-      --  Otherwise a property is enabled when the related object is volatile
+      --  Otherwise a property is enabled when the related item is effectively
+      --  volatile.
 
       else
-         return Is_SPARK_Volatile (Item_Id);
+         return Is_Effectively_Volatile (Item_Id);
       end if;
    end Has_Enabled_Property;
 
@@ -10117,6 +10119,67 @@
       end if;
    end Is_Descendent_Of;
 
+   -----------------------------
+   -- Is_Effectively_Volatile --
+   -----------------------------
+
+   function Is_Effectively_Volatile (Id : Entity_Id) return Boolean is
+   begin
+      if Is_Type (Id) then
+
+         --  An arbitrary type is effectively volatile when it is subject to
+         --  pragma Atomic or Volatile.
+
+         if Is_Volatile (Id) then
+            return True;
+
+         --  An array type is effectively volatile when it is subject to pragma
+         --  Atomic_Components or Volatile_Components or its compolent type is
+         --  effectively volatile.
+
+         elsif Is_Array_Type (Id) then
+            return
+              Has_Volatile_Components (Id)
+                or else
+              Is_Effectively_Volatile (Component_Type (Base_Type (Id)));
+
+         else
+            return False;
+         end if;
+
+      --  Otherwise Id denotes an object
+
+      else
+         return Is_Volatile (Id) or else Is_Effectively_Volatile (Etype (Id));
+      end if;
+   end Is_Effectively_Volatile;
+
+   ------------------------------------
+   -- Is_Effectively_Volatile_Object --
+   ------------------------------------
+
+   function Is_Effectively_Volatile_Object (N : Node_Id) return Boolean is
+   begin
+      if Is_Entity_Name (N) then
+         return Is_Effectively_Volatile (Entity (N));
+
+      elsif Nkind (N) = N_Expanded_Name then
+         return Is_Effectively_Volatile (Entity (N));
+
+      elsif Nkind (N) = N_Indexed_Component then
+         return Is_Effectively_Volatile_Object (Prefix (N));
+
+      elsif Nkind (N) = N_Selected_Component then
+         return
+           Is_Effectively_Volatile_Object (Prefix (N))
+             or else
+           Is_Effectively_Volatile_Object (Selector_Name (N));
+
+      else
+         return False;
+      end if;
+   end Is_Effectively_Volatile_Object;
+
    ----------------------------
    -- Is_Expression_Function --
    ----------------------------
@@ -11491,41 +11554,6 @@
       end if;
    end Is_SPARK_Object_Reference;
 
-   -----------------------
-   -- Is_SPARK_Volatile --
-   -----------------------
-
-   function Is_SPARK_Volatile (Id : Entity_Id) return Boolean is
-   begin
-      return Is_Volatile (Id) or else Is_Volatile (Etype (Id));
-   end Is_SPARK_Volatile;
-
-   ------------------------------
-   -- Is_SPARK_Volatile_Object --
-   ------------------------------
-
-   function Is_SPARK_Volatile_Object (N : Node_Id) return Boolean is
-   begin
-      if Is_Entity_Name (N) then
-         return Is_SPARK_Volatile (Entity (N));
-
-      elsif Nkind (N) = N_Expanded_Name then
-         return Is_SPARK_Volatile (Entity (N));
-
-      elsif Nkind (N) = N_Indexed_Component then
-         return Is_SPARK_Volatile_Object (Prefix (N));
-
-      elsif Nkind (N) = N_Selected_Component then
-         return
-           Is_SPARK_Volatile_Object (Prefix (N))
-             or else
-           Is_SPARK_Volatile_Object (Selector_Name (N));
-
-      else
-         return False;
-      end if;
-   end Is_SPARK_Volatile_Object;
-
    ------------------
    -- Is_Statement --
    ------------------
Index: sem_util.ads
===================================================================
--- sem_util.ads        (revision 213345)
+++ sem_util.ads        (working copy)
@@ -1171,6 +1171,15 @@
    --  This is the RM definition, a type is a descendent of another type if it
    --  is the same type or is derived from a descendent of the other type.
 
+   function Is_Effectively_Volatile (Id : Entity_Id) return Boolean;
+   --  The SPARK property "effectively volatile" applies to both types and
+   --  objects. To qualify as such, an entity must be either volatile or be
+   --  (of) an array type subject to aspect Volatile_Components.
+
+   function Is_Effectively_Volatile_Object (N : Node_Id) return Boolean;
+   --  Determine whether an arbitrary node denotes an effectively volatile
+   --  object.
+
    function Is_Expression_Function (Subp : Entity_Id) return Boolean;
    --  Predicate to determine whether a scope entity comes from a rewritten
    --  expression function call, and should be inlined unconditionally. Also
@@ -1310,18 +1319,6 @@
    function Is_SPARK_Object_Reference (N : Node_Id) return Boolean;
    --  Determines if the tree referenced by N represents an object in SPARK
 
-   function Is_SPARK_Volatile (Id : Entity_Id) return Boolean;
-   --  This routine is similar to predicate Is_Volatile, but it takes SPARK
-   --  semantics into account. In SPARK volatile components to not render a
-   --  type volatile.
-
-   function Is_SPARK_Volatile_Object (N : Node_Id) return Boolean;
-   --  Determine whether an arbitrary node denotes a volatile object reference
-   --  according to the semantics of SPARK. To qualify as volatile, an object
-   --  must be subject to aspect/pragma Volatile or Atomic, or have a [sub]type
-   --  subject to the same attributes. Note that volatile components do not
-   --  render an object volatile.
-
    function Is_Statement (N : Node_Id) return Boolean;
    pragma Inline (Is_Statement);
    --  Check if the node N is a statement node. Note that this includes

Reply via email to