]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
ada: Check ghost level dependencies inside assignments
authorViljar Indus <indus@adacore.com>
Mon, 25 Aug 2025 07:13:02 +0000 (10:13 +0300)
committerMarc Poulhiès <dkm@gcc.gnu.org>
Thu, 11 Sep 2025 09:10:49 +0000 (11:10 +0200)
Check that entities on the RHS are ghost level dependent on the
entities on the LHS of the assignemnt.

gcc/ada/ChangeLog:

* ghost.adb (Is_OK_Statement): Check the levels of the
assignee with the levels of the entity are ghost level dependent.
(Check_Assignement_Levels): New function for checking the level
dependencies.

gcc/ada/ghost.adb

index bc646b22fbe528f5478b6a966d1881e607cff562..0fbcf20da7c1e10cc22719e8f6184a50d4db5d69 100644 (file)
@@ -515,6 +515,10 @@ package body Ghost is
          function Is_OK_Statement
            (Stmt : Node_Id; Id : Entity_Id; Call_Arg : Node_Id) return Boolean
          is
+            procedure Check_Assignment_Levels (Assignee : Entity_Id);
+            --  Check that a ghost entity on the RHS of the assignment is
+            --  assertion level dependent on the LHS.
+
             procedure Check_Procedure_Call_Policies (Callee : Entity_Id);
             --  Check that
             --  * the a checked call argument is not modified by an ignored
@@ -528,6 +532,39 @@ package body Ghost is
             --  Check that Call_Arg was used in the call and that the formal
             --  for that argument was either out or in-out.
 
+            -----------------------------
+            -- Check_Assignment_Levels --
+            -----------------------------
+
+            procedure Check_Assignment_Levels (Assignee : Entity_Id) is
+               Assignee_Level : constant Entity_Id :=
+                 Ghost_Assertion_Level (Assignee);
+               Id_Level       : constant Entity_Id :=
+                 Ghost_Assertion_Level (Id);
+            begin
+               --  SPARK RM 6.9 (13) A ghost entity E shall only be referenced
+               --  within an assignment statement whose target is a ghost
+               --  variable that is assertion-level-dependent on E.
+
+               if not Is_Assertion_Level_Dependent (Id_Level, Assignee_Level)
+               then
+                  Error_Msg_Sloc := Sloc (Ghost_Ref);
+
+                  Error_Msg_N (Assertion_Level_Error_Msg, Ghost_Ref);
+                  Error_Msg_Name_1 := Chars (Id_Level);
+                  Error_Msg_NE ("\& has assertion level %", Ghost_Ref, Id);
+                  Error_Msg_Name_1 := Chars (Assignee_Level);
+                  Error_Msg_Node_2 := Assignee;
+                  Error_Msg_NE
+                    ("\& is modifying & with %", Ghost_Ref, Id);
+                  Error_Msg_Name_1 := Chars (Assignee_Level);
+                  Error_Msg_NE
+                    ("\assertion level of & should depend on %",
+                     Ghost_Ref,
+                     Id);
+               end if;
+            end Check_Assignment_Levels;
+
             -----------------------------------
             -- Check_Procedure_Call_Policies --
             -----------------------------------
@@ -619,6 +656,8 @@ package body Ghost is
 
             if Nkind (Stmt) = N_Assignment_Statement then
                if Is_Ghost_Assignment (Stmt) then
+                  Check_Assignment_Levels
+                    (Get_Enclosing_Ghost_Entity (Name (Stmt)));
                   return True;
                end if;