From: Viljar Indus <in...@adacore.com>

There are cases where we need to analyze the argument of the pragma
in order to determine the ghostliness of the pragma. However during
that analysis the ghost region of the pragma is not set yet so we
cannot perform the ghost context checks at that moment.

This patch provides the mechanism for disabling ghost context checks
and disables them for pragma arguments that determine the ghostliness
of the pragma.

gcc/ada/ChangeLog:

        * ghost.adb (Check_Ghost_Context): Avoid context checks when they
        are globally disabled.
        * sem.ads (Ghost_Context_Checks_Disabled): New flag to control
        whether ghost context checks are activated or not.
        * sem_prag.adb (Analyze_Pragma): Disable ghost context checks for
        pragmas that determine their ghostliness based on one of its arguments.

Tested on x86_64-pc-linux-gnu, committed on master.

---
 gcc/ada/ghost.adb    |  4 ++++
 gcc/ada/sem.ads      | 12 ++++++++++++
 gcc/ada/sem_prag.adb | 39 +++++++++++++++++++++++++++++++++++++++
 3 files changed, 55 insertions(+)

diff --git a/gcc/ada/ghost.adb b/gcc/ada/ghost.adb
index 4f1a0d9d6a46..ae20ef972c82 100644
--- a/gcc/ada/ghost.adb
+++ b/gcc/ada/ghost.adb
@@ -932,6 +932,10 @@ package body Ghost is
    --  Start of processing for Check_Ghost_Context
 
    begin
+      if Ghost_Context_Checks_Disabled then
+         return;
+      end if;
+
       --  Class-wide pre/postconditions of ignored pragmas are preanalyzed
       --  to report errors on wrong conditions; however, ignored pragmas may
       --  also have references to ghost entities and we must disable checking
diff --git a/gcc/ada/sem.ads b/gcc/ada/sem.ads
index 611309775279..63cf1daad37d 100644
--- a/gcc/ada/sem.ads
+++ b/gcc/ada/sem.ads
@@ -307,6 +307,18 @@ package Sem is
    --  case. We could perhaps do a more accurate job and retain some of the
    --  warnings, but it is quite a tricky job.
 
+   Ghost_Context_Checks_Disabled : Boolean := False;
+   --  This flag controls whether ghost context related checks are enabled or
+   --  disabled. Typically they are enabled however they need to be disabled in
+   --  instances where the ghost region context has not been set.
+   --
+   --  Typically this is done for pragmas where the ghostliness of the pragma
+   --  is determined by an entity specified as one of the arguments. In these
+   --  cases we need to analyze that argument before the pragma itself to
+   --  determine the ghostliness of the pragma. However at that point we have
+   --  not set the ghost region for the pragma in order to determine the ghost
+   --  context of the argument.
+
    -----------------------------------
    -- Handling of Check Suppression --
    -----------------------------------
diff --git a/gcc/ada/sem_prag.adb b/gcc/ada/sem_prag.adb
index 661d4401d7a2..00c9b17ff6ee 100644
--- a/gcc/ada/sem_prag.adb
+++ b/gcc/ada/sem_prag.adb
@@ -6439,7 +6439,14 @@ package body Sem_Prag is
             end if;
          end if;
 
+         --  We are going to check the entity that determines the ghost
+         --  region of that pragma. We need to disable the checks for ghost
+         --  context since the ghost region can only be set after analyzing
+         --  this entity.
+
+         Ghost_Context_Checks_Disabled := True;
          Analyze (Argx);
+         Ghost_Context_Checks_Disabled := False;
 
          if Nkind (Argx) not in N_Direct_Name
            and then (Nkind (Argx) /= N_Attribute_Reference
@@ -9221,8 +9228,15 @@ package body Sem_Prag is
          Check_Optional_Identifier (Arg2, Name_Entity);
          Check_Arg_Is_Local_Name (Arg2);
 
+         --  We are going to check the entity that determines the ghost
+         --  region of that pragma. We need to disable the checks for ghost
+         --  context since the ghost region can only be set after analyzing
+         --  this entity.
+
+         Ghost_Context_Checks_Disabled := True;
          Id := Get_Pragma_Arg (Arg2);
          Analyze (Id);
+         Ghost_Context_Checks_Disabled := False;
 
          if not Is_Entity_Name (Id) then
             Error_Pragma_Arg ("entity name required", Arg2);
@@ -12022,7 +12036,15 @@ package body Sem_Prag is
 
             Check_Optional_Identifier (Arg2, Name_On);
             E_Id := Get_Pragma_Arg (Arg2);
+
+            --  We are going to check the entity that determines the ghost
+            --  region of that pragma. We need to disable the checks for ghost
+            --  context since the ghost region can only be set after analyzing
+            --  this entity.
+
+            Ghost_Context_Checks_Disabled := True;
             Analyze (E_Id);
+            Ghost_Context_Checks_Disabled := False;
 
             if not Is_Entity_Name (E_Id) then
                Error_Pragma_Arg
@@ -15041,6 +15063,7 @@ package body Sem_Prag is
             Check_Ada_83_Warning;
             Check_No_Identifiers;
             Check_Arg_Count (1);
+
             Check_Arg_Is_Local_Name (Arg1);
 
             if Debug_Flag_U then
@@ -15048,8 +15071,16 @@ package body Sem_Prag is
             end if;
 
             C_Ent := Cunit_Entity (Current_Sem_Unit);
+
+            --  We are going to check the entity that determines the ghost
+            --  region of that pragma. We need to disable the checks for ghost
+            --  context since the ghost region can only be set after analyzing
+            --  this entity.
+
+            Ghost_Context_Checks_Disabled := True;
             Analyze (Get_Pragma_Arg (Arg1));
             Nm := Entity (Get_Pragma_Arg (Arg1));
+            Ghost_Context_Checks_Disabled := False;
 
             --  A pragma that applies to a Ghost entity becomes Ghost for the
             --  purposes of legality checks and removal of ignored Ghost code.
@@ -22359,7 +22390,15 @@ package body Sem_Prag is
             while Present (Arg) loop
                Check_Arg_Is_Local_Name (Arg);
                Id := Get_Pragma_Arg (Arg);
+
+               --  We are going to check the entity that determines the ghost
+               --  region of that pragma. We need to disable the checks for
+               --  ghost context since the ghost region can only be set after
+               --  analyzing this entity.
+
+               Ghost_Context_Checks_Disabled := True;
                Analyze (Id);
+               Ghost_Context_Checks_Disabled := False;
 
                if not Is_Entity_Name (Id) then
                   Error_Pragma_Arg ("entity name required", Arg);
-- 
2.43.0

Reply via email to