[Ada] Interaction between 'Loop_Entry, 'Old, 'Update and Extensions_Visible

Arnaud Charlet charlet@adacore.com
Thu Nov 20 11:28:00 GMT 2014


This patch the following SPARK rule (the part about 'Loop_Entry, 'Old, 'Update)

   If the Extensions_Visible aspect is False for a subprogram, then certain
   restrictions are imposed on the use of any parameter of the subprogram which
   is of a specific tagged type. Such a parameter shall not be converted to a
   class-wide type. Such a parameter shall not be passed as an actual parameter
   in a call to a subprogram whose Extensions_Visible aspect is True. These
   restrictions also apply to any parenthesized expression, qualified
   expression, or type conversion whose operand is subject to these
   restrictions, to any Old, Update, or Loop_Entry attribute_reference whose
   prefix is subject to these restrictions, and to any conditional expression
   having at least one dependent_expression which is subjec to these
   restrictions.

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

--  test_loop_entry_old_update.adb

procedure Test_Loop_Entry_Old_Update is

   -- Test that Extensions_Visible restrictions are enforced for
   -- Old, Update, and Loop_Entry attribute references.

   pragma Assertion_Policy (Check);

   package Pkg is
      type T is abstract tagged record Int1, Int2, Int3 : Integer; end record;
      function Is_Bodacious (X : T) return Boolean is abstract;
   end Pkg;
   use Pkg;

   procedure P1 (X : in out T) with
     Post => Is_Bodacious (T'Class (X'Old)),                         --  ERROR
     Extensions_Visible => False;
   procedure P1 (X : in out T) is begin null; end P1;

   procedure P2 (X : in out T) with Extensions_Visible => False;
   procedure P2 (X : in out T) is
   begin
      if Is_Bodacious (T'Class (X'Update (Int1 => 123))) then        --  ERROR
         X.Int1 := 123;
      end if;
   end P2;

   procedure P3 (X : in out T) with Extensions_Visible => False;
   procedure P3 (X : in out T) is
   begin
      for I in 1 .. 10 loop
         X.Int1 := X.Int1 + 1;
         pragma Assert ((X.Int1 /= X.Int2)
           or else Is_Bodacious (T'Class (X'Loop_Entry)));           --  ERROR
      end loop;
   end P3;

   procedure P4 (X : in out T; Y : T'Class) with Extensions_Visible => False;
   procedure P4 (X : in out T; Y : T'Class) is
   begin
      if Is_Bodacious
        (T'Class
          (T'(if X.Int1 = X.Int2                                     --  ERROR
              then X'Update (Int1 => X.Int1 + 1)
              else T (Y)))) then
          X.Int1 := 456;
      end if;
   end P4;

begin null; end Test_Loop_Entry_Old_Update;

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

$ gcc -c test_loop_entry_old_update.adb
test_loop_entry_old_update.adb:15:38: formal parameter with Extensions_Visible
  False cannot be converted to class-wide type
test_loop_entry_old_update.adb:22:34: formal parameter with Extensions_Visible
  False cannot be converted to class-wide type
test_loop_entry_old_update.adb:33:44: formal parameter with Extensions_Visible
  False cannot be converted to class-wide type
test_loop_entry_old_update.adb:42:13: formal parameter with Extensions_Visible
  False cannot be converted to class-wide type

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

2014-11-20  Hristian Kirtchev  <kirtchev@adacore.com>

	* sem_util.adb (Is_EVF_Expression): Include
	attributes 'Loop_Entry, 'Old and 'Update to the logic.

-------------- next part --------------
Index: sem_util.adb
===================================================================
--- sem_util.adb	(revision 217835)
+++ sem_util.adb	(working copy)
@@ -10846,6 +10846,16 @@
                          N_Type_Conversion)
       then
          return Is_EVF_Expression (Expression (N));
+
+      --  Attributes 'Loop_Entry, 'Old and 'Update are an EVF expression when
+      --  their prefix denotes an EVF expression.
+
+      elsif Nkind (N) = N_Attribute_Reference
+        and then Nam_In (Attribute_Name (N), Name_Loop_Entry,
+                                             Name_Old,
+                                             Name_Update)
+      then
+         return Is_EVF_Expression (Prefix (N));
       end if;
 
       return False;


More information about the Gcc-patches mailing list