This patch suppresses the transformation of references to renamings into
references to renamed names when the reference appears within a pragma of
no significance to SPARK.

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

--  uname.adb

procedure Uname is
   type Bounded_String is record
      Length : Natural;
   end record;

   Global_Name_Buffer : Bounded_String := (Length => 0);
   Right_Length       : Natural renames Global_Name_Buffer.Length;

begin
   pragma Warnings (Off, Right_Length);
   pragma Assert (Right_Length = 0);
end Uname;

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

$ gcc -c -gnatdg -gnatd.F uname.adb
with system;

procedure uname is
   type bounded_string is record
      length : natural;
   end record;
   freeze bounded_string []
   global_name_buffer : bounded_string := (
      length => 0);
   right_length : natural renames global_name_buffer.length;
begin
   pragma warnings (off, right_length);
   pragma check (assert, global_name_buffer.length = 0);
   null;
end uname;

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

2017-09-25  Hristian Kirtchev  <kirtc...@adacore.com>

        * exp_spark.adb (Expand_SPARK_Potential_Renaming): Do not process a
        reference when it appears within a pragma of no significance to SPARK.
        (In_Insignificant_Pragma): New routine.
        * sem_prag.ads: Add new table Pragma_Significant_In_SPARK.

Index: sem_prag.ads
===================================================================
--- sem_prag.ads        (revision 253134)
+++ sem_prag.ads        (working copy)
@@ -175,6 +175,25 @@
       Pragma_Warnings        => True,
       others                 => False);
 
+   --  The following table lists all pragmas which are significant in SPARK and
+   --  as a result get translated into verification conditions. The table is an
+   --  amalgamation of the pragmas listed in SPARK RM 16.1 and internally added
+   --  entries.
+
+   Pragma_Significant_In_SPARK : constant array (Pragma_Id) of Boolean :=
+     (Pragma_All_Calls_Remote              => False,
+      Pragma_Asynchronous                  => False,
+      Pragma_Default_Storage_Pool          => False,
+      Pragma_Discard_Names                 => False,
+      Pragma_Dispatching_Domain            => False,
+      Pragma_Priority_Specific_Dispatching => False,
+      Pragma_Remote_Call_Interface         => False,
+      Pragma_Remote_Types                  => False,
+      Pragma_Shared_Passive                => False,
+      Pragma_Task_Dispatching_Policy       => False,
+      Pragma_Warnings                      => False,
+      others                               => True);
+
    -----------------
    -- Subprograms --
    -----------------
Index: exp_spark.adb
===================================================================
--- exp_spark.adb       (revision 253134)
+++ exp_spark.adb       (working copy)
@@ -36,6 +36,7 @@
 with Rtsfind;  use Rtsfind;
 with Sem;      use Sem;
 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 Sinfo;    use Sinfo;
@@ -368,11 +369,46 @@
    -------------------------------------
 
    procedure Expand_SPARK_Potential_Renaming (N : Node_Id) is
+      function In_Insignificant_Pragma (Nod : Node_Id) return Boolean;
+      --  Determine whether arbitrary node Nod appears within a significant
+      --  pragma for SPARK.
+
+      -----------------------------
+      -- In_Insignificant_Pragma --
+      -----------------------------
+
+      function In_Insignificant_Pragma (Nod : Node_Id) return Boolean is
+         Par : Node_Id;
+
+      begin
+         --  Climb the parent chain looking for an enclosing pragma
+
+         Par := Nod;
+         while Present (Par) loop
+            if Nkind (Par) = N_Pragma then
+               return not Pragma_Significant_In_SPARK (Get_Pragma_Id (Par));
+
+            --  Prevent the search from going too far
+
+            elsif Is_Body_Or_Package_Declaration (Par) then
+               exit;
+            end if;
+
+            Par := Parent (Par);
+         end loop;
+
+         return False;
+      end In_Insignificant_Pragma;
+
+      --  Local variables
+
       Loc    : constant Source_Ptr := Sloc (N);
       Obj_Id : constant Entity_Id  := Entity (N);
       Typ    : constant Entity_Id  := Etype (N);
       Ren    : Node_Id;
 
+   --  Start of processing for Expand_SPARK_Potential_Renaming
+
    begin
       --  Replace a reference to a renaming with the actual renamed object
 
@@ -381,12 +417,20 @@
 
          if Present (Ren) then
 
+            --  Do not process a reference when it appears within a pragma of
+            --  no significance to SPARK. It is assumed that the replacement
+            --  will violate the semantics of the pragma and cause a spurious
+            --  error.
+
+            if In_Insignificant_Pragma (N) then
+               return;
+
             --  Instantiations and inlining of subprograms employ "prologues"
             --  which map actual to formal parameters by means of renamings.
             --  Replace a reference to a formal by the corresponding actual
             --  parameter.
 
-            if Nkind (Ren) in N_Entity then
+            elsif Nkind (Ren) in N_Entity then
                Rewrite (N, New_Occurrence_Of (Ren, Loc));
 
             --  Otherwise the renamed object denotes a name

Reply via email to