This patch updates the new ABE mechanism to fully remove a recorded top level
elaboration scenario from its data structures when the scenario appears in dead
code. Previously the mechanism suppressed the generation of checks for such a
scenario, but still produced warnings.

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

gcc/ada/

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

        * sem_elab.adb: Update the documentation on adding a new elaboration
        schenario. Add new hash table Recorded_Top_Level_Scenarios.
        (Is_Check_Emitting_Scenario): Removed.
        (Is_Recorded_Top_Level_Scenario): New routine.
        (Kill_Elaboration_Scenario): Reimplemented.
        (Record_Elaboration_Scenario): Mark the scenario as recorded.
        (Set_Is_Recorded_Top_Level_Scenario): New routine.
        (Update_Elaboration_Scenario): Reimplemented.
        * sinfo.adb (Is_Recorded_Scenario): Removed.
        (Set_Is_Recorded_Scenario): Removed.
        * sinfo.ads: Remove attribute Is_Recorded_Scenario along with
        occurrences in nodes.
        (Is_Recorded_Scenario): Removed along with pragma Inline.
        (Set_Is_Recorded_Scenario): Removed along with pragma Inline.

gcc/testsuite/

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

        * gnat.dg/elab3.adb, gnat.dg/elab3.ads, gnat.dg/elab3_pkg.adb,
        gnat.dg/elab3_pkg.ads: New testcase.
Index: sinfo.adb
===================================================================
--- sinfo.adb   (revision 254563)
+++ sinfo.adb   (working copy)
@@ -2098,17 +2098,6 @@
       return Flag1 (N);
    end Is_Read;
 
-   function Is_Recorded_Scenario
-      (N : Node_Id) return Boolean is
-   begin
-      pragma Assert (False
-        or else NT (N).Nkind = N_Call_Marker
-        or else NT (N).Nkind = N_Function_Instantiation
-        or else NT (N).Nkind = N_Package_Instantiation
-        or else NT (N).Nkind = N_Procedure_Instantiation);
-      return Flag6 (N);
-   end Is_Recorded_Scenario;
-
    function Is_Source_Call
       (N : Node_Id) return Boolean is
    begin
@@ -5537,17 +5526,6 @@
       Set_Flag1 (N, Val);
    end Set_Is_Read;
 
-   procedure Set_Is_Recorded_Scenario
-      (N : Node_Id; Val : Boolean := True) is
-   begin
-      pragma Assert (False
-        or else NT (N).Nkind = N_Call_Marker
-        or else NT (N).Nkind = N_Function_Instantiation
-        or else NT (N).Nkind = N_Package_Instantiation
-        or else NT (N).Nkind = N_Procedure_Instantiation);
-      Set_Flag6 (N, Val);
-   end Set_Is_Recorded_Scenario;
-
    procedure Set_Is_Source_Call
       (N : Node_Id; Val : Boolean := True) is
    begin
Index: sinfo.ads
===================================================================
--- sinfo.ads   (revision 254563)
+++ sinfo.ads   (working copy)
@@ -1867,12 +1867,6 @@
    --    Present in variable reference markers. Set when the original variable
    --    reference constitues a read of the variable.
 
-   --  Is_Recorded_Scenario (Flag6-Sem)
-   --    Present in call marker and instantiation nodes. Set when the scenario
-   --    was saved by the ABE Recording phase. This flag aids the ABE machinery
-   --    to keep its internal data up-to-date in case the node is transformed
-   --    by Atree.Rewrite.
-
    --  Is_Source_Call (Flag4-Sem)
    --    Present in call marker nodes. Set when the related call came from
    --    source.
@@ -7045,7 +7039,6 @@
       --  Is_Elaboration_Checks_OK_Node (Flag1-Sem)
       --  Is_SPARK_Mode_On_Node (Flag2-Sem)
       --  Is_Declaration_Level_Node (Flag5-Sem)
-      --  Is_Recorded_Scenario (Flag6-Sem)
       --  Is_Known_Guaranteed_ABE (Flag18-Sem)
 
       --  N_Procedure_Instantiation
@@ -7059,7 +7052,6 @@
       --  Is_Elaboration_Checks_OK_Node (Flag1-Sem)
       --  Is_SPARK_Mode_On_Node (Flag2-Sem)
       --  Is_Declaration_Level_Node (Flag5-Sem)
-      --  Is_Recorded_Scenario (Flag6-Sem)
       --  Must_Override (Flag14) set if overriding indicator present
       --  Must_Not_Override (Flag15) set if not_overriding indicator present
       --  Is_Known_Guaranteed_ABE (Flag18-Sem)
@@ -7075,7 +7067,6 @@
       --  Is_Elaboration_Checks_OK_Node (Flag1-Sem)
       --  Is_SPARK_Mode_On_Node (Flag2-Sem)
       --  Is_Declaration_Level_Node (Flag5-Sem)
-      --  Is_Recorded_Scenario (Flag6-Sem)
       --  Must_Override (Flag14) set if overriding indicator present
       --  Must_Not_Override (Flag15) set if not_overriding indicator present
       --  Is_Known_Guaranteed_ABE (Flag18-Sem)
@@ -7833,7 +7824,6 @@
       --  Is_Dispatching_Call (Flag3-Sem)
       --  Is_Source_Call (Flag4-Sem)
       --  Is_Declaration_Level_Node (Flag5-Sem)
-      --  Is_Recorded_Scenario (Flag6-Sem)
       --  Is_Known_Guaranteed_ABE (Flag18-Sem)
 
       ------------------------
@@ -9777,9 +9767,6 @@
    function Is_Read
      (N : Node_Id) return Boolean;    -- Flag1
 
-   function Is_Recorded_Scenario
-     (N : Node_Id) return Boolean;    -- Flag6
-
    function Is_Source_Call
      (N : Node_Id) return Boolean;    -- Flag4
 
@@ -10872,9 +10859,6 @@
    procedure Set_Is_Read
      (N : Node_Id; Val : Boolean := True);    -- Flag1
 
-   procedure Set_Is_Recorded_Scenario
-     (N : Node_Id; Val : Boolean := True);    -- Flag6
-
    procedure Set_Is_Source_Call
      (N : Node_Id; Val : Boolean := True);    -- Flag4
 
@@ -13337,7 +13321,6 @@
    pragma Inline (Is_Protected_Subprogram_Body);
    pragma Inline (Is_Qualified_Universal_Literal);
    pragma Inline (Is_Read);
-   pragma Inline (Is_Recorded_Scenario);
    pragma Inline (Is_Source_Call);
    pragma Inline (Is_SPARK_Mode_On_Node);
    pragma Inline (Is_Static_Coextension);
@@ -13697,7 +13680,6 @@
    pragma Inline (Set_Is_Protected_Subprogram_Body);
    pragma Inline (Set_Is_Qualified_Universal_Literal);
    pragma Inline (Set_Is_Read);
-   pragma Inline (Set_Is_Recorded_Scenario);
    pragma Inline (Set_Is_Source_Call);
    pragma Inline (Set_Is_SPARK_Mode_On_Node);
    pragma Inline (Set_Is_Static_Coextension);
Index: sem_elab.adb
===================================================================
--- sem_elab.adb        (revision 254566)
+++ sem_elab.adb        (working copy)
@@ -68,7 +68,7 @@
    --    * Diagnose at compile-time or install run-time checks to prevent ABE
    --      access to data and behaviour.
    --
-   --      The high level idea is to accurately diagnose ABE issues within a
+   --      The high-level idea is to accurately diagnose ABE issues within a
    --      single unit because the ABE mechanism can inspect the whole unit.
    --      As soon as the elaboration graph extends to an external unit, the
    --      diagnostics stop because the body of the unit may not be available.
@@ -146,8 +146,8 @@
    --    the library level if it appears in a package library unit, ignoring
    --    enclosng packages.
    --
-   --  * Non-library level encapsulator - A construct that cannot be elaborated
-   --    on its own and requires elaboration by a top level scenario.
+   --  * Non-library-level encapsulator - A construct that cannot be elaborated
+   --    on its own and requires elaboration by a top-level scenario.
    --
    --  * Scenario - A construct or context which may be elaborated or executed
    --    by elaboration code. The scenarios recognized by the ABE mechanism are
@@ -181,7 +181,7 @@
    --
    --      - For task activation, the target is the task body
    --
-   --  * Top level scenario - A scenario which appears in a non-generic main
+   --  * Top-level scenario - A scenario which appears in a non-generic main
    --    unit. Depending on the elaboration model is in effect, the following
    --    addotional restrictions apply:
    --
@@ -198,7 +198,7 @@
    --  The Recording phase coincides with the analysis/resolution phase of the
    --  compiler. It has the following objectives:
    --
-   --    * Record all top level scenarios for examination by the Processing
+   --    * Record all top-level scenarios for examination by the Processing
    --      phase.
    --
    --      Saving only a certain number of nodes improves the performance of
@@ -231,9 +231,9 @@
    --  and/or inlining of bodies, but before the removal of Ghost code. It has
    --  the following objectives:
    --
-   --    * Examine all top level scenarios saved during the Recording phase
+   --    * Examine all top-level scenarios saved during the Recording phase
    --
-   --      The top level scenarios act as roots for depth-first traversal of
+   --      The top-level scenarios act as roots for depth-first traversal of
    --      the call/instantiation/task activation graph. The traversal stops
    --      when an outgoing edge leaves the main unit.
    --
@@ -420,8 +420,7 @@
    --  The following steps describe how to add a new elaboration scenario and
    --  preserve the existing architecture.
    --
-   --    1) If necessary, update predicates Is_Check_Emitting_Scenario and
-   --       Is_Scenario.
+   --    1) If necessary, update predicate Is_Scenario
    --
    --    2) Add predicate Is_Suitable_xxx. Include a call to it in predicate
    --       Is_Suitable_Scenario.
@@ -712,8 +711,28 @@
       Hash       => Elaboration_Context_Hash,
       Equal      => "=");
 
+   --  The following table stores a status flag for each top-level scenario
+   --  recorded in table Top_Level_Scenarios.
+
+   Recorded_Top_Level_Scenarios_Max : constant := 503;
+
+   type Recorded_Top_Level_Scenarios_Index is
+     range 0 .. Recorded_Top_Level_Scenarios_Max - 1;
+
+   function Recorded_Top_Level_Scenarios_Hash
+     (Key : Node_Id) return Recorded_Top_Level_Scenarios_Index;
+   --  Obtain the hash value of entity Key
+
+   package Recorded_Top_Level_Scenarios is new Simple_HTable
+     (Header_Num => Recorded_Top_Level_Scenarios_Index,
+      Element    => Boolean,
+      No_Element => False,
+      Key        => Node_Id,
+      Hash       => Recorded_Top_Level_Scenarios_Hash,
+      Equal      => "=");
+
    --  The following table stores all active scenarios in a recursive traversal
-   --  starting from a top level scenario. This table must be maintained in a
+   --  starting from a top-level scenario. This table must be maintained in a
    --  FIFO fashion.
 
    package Scenario_Stack is new Table.Table
@@ -724,7 +743,7 @@
       Table_Increment      => 100,
       Table_Name           => "Scenario_Stack");
 
-   --  The following table stores all top level scenario saved during the
+   --  The following table stores all top-level scenario saved during the
    --  Recording phase. The contents of this table act as traversal roots
    --  later in the Processing phase. This table must be maintained in a
    --  LIFO fashion.
@@ -738,7 +757,7 @@
       Table_Name           => "Top_Level_Scenarios");
 
    --  The following table stores the bodies of all eligible scenarios visited
-   --  during a traversal starting from a top level scenario. The contents of
+   --  during a traversal starting from a top-level scenario. The contents of
    --  this table must be reset upon each new traversal.
 
    Visited_Bodies_Max : constant := 511;
@@ -867,7 +886,7 @@
    --  Return the code unit which contains arbitrary node or entity N. This
    --  is the unit of the file which physically contains the related construct
    --  denoted by N except when N is within an instantiation. In that case the
-   --  unit is that of the top level instantiation.
+   --  unit is that of the top-level instantiation.
 
    procedure Find_Elaborated_Units;
    --  Populate table Elaboration_Context with all units which have prior
@@ -1019,11 +1038,6 @@
    pragma Inline (Is_Bodiless_Subprogram);
    --  Determine whether subprogram Subp_Id will never have a body
 
-   function Is_Check_Emitting_Scenario (N : Node_Id) return Boolean;
-   pragma Inline (Is_Check_Emitting_Scenario);
-   --  Determine whether arbitrary node N denotes a scenario which may emit a
-   --  conditional ABE check.
-
    function Is_Controlled_Proc
      (Subp_Id  : Entity_Id;
       Subp_Nam : Name_Id) return Boolean;
@@ -1101,6 +1115,11 @@
    --  Determine whether entity Id denotes the protected or unprotected version
    --  of a protected subprogram.
 
+   function Is_Recorded_Top_Level_Scenario (N : Node_Id) return Boolean;
+   pragma Inline (Is_Recorded_Top_Level_Scenario);
+   --  Determine whether arbitrary node is a recorded top-level scenario which
+   --  appears in table Top_Level_Scenarios.
+
    function Is_Safe_Activation
      (Call      : Node_Id;
       Task_Decl : Node_Id) return Boolean;
@@ -1329,14 +1348,14 @@
    --  routine.
 
    procedure Process_Guaranteed_ABE (N : Node_Id);
-   --  Top level dispatcher for processing of scenarios which result in a
+   --  Top-level dispatcher for processing of scenarios which result in a
    --  guaranteed ABE.
 
    procedure Process_Instantiation
      (Exp_Inst       : Node_Id;
       In_Partial_Fin : Boolean;
       In_Task_Body   : Boolean);
-   --  Top level dispatcher for processing of instantiations. Perform ABE
+   --  Top-level dispatcher for processing of instantiations. Perform ABE
    --  checks and diagnostics for expanded instantiation Exp_Inst. Flag
    --  In_Partial_Fin shoud be set when the processing is initiated by a
    --  partial finalization routine. Flag In_Task_Body should be set when
@@ -1393,14 +1412,14 @@
      (N              : Node_Id;
       In_Partial_Fin : Boolean := False;
       In_Task_Body   : Boolean := False);
-   --  Top level dispatcher for processing of various elaboration scenarios.
+   --  Top-level dispatcher for processing of various elaboration scenarios.
    --  Perform ABE checks and diagnostics for scenario N. Flag In_Partial_Fin
    --  shoud be set when the processing is initiated by a partial finalization
    --  routine. Flag In_Task_Body should be set when the processing is started
    --  from a task body.
 
    procedure Process_Variable_Assignment (Asmt : Node_Id);
-   --  Top level dispatcher for processing of variable assignments. Perform ABE
+   --  Top-level dispatcher for processing of variable assignments. Perform ABE
    --  checks and diagnostics for assignment statement Asmt.
 
    procedure Process_Variable_Assignment_Ada
@@ -1416,7 +1435,7 @@
    --  updates the value of variable Var_Id using the SPARK rules.
 
    procedure Process_Variable_Reference (Ref : Node_Id);
-   --  Top level dispatcher for processing of variable references. Perform ABE
+   --  Top-level dispatcher for processing of variable references. Perform ABE
    --  checks and diagnostics for variable reference Ref.
 
    procedure Process_Variable_Reference_Read
@@ -1432,10 +1451,16 @@
 
    function Root_Scenario return Node_Id;
    pragma Inline (Root_Scenario);
-   --  Return the top level scenario which started a recursive search for other
-   --  scenarios. It is assumed that there is a valid top level scenario on the
+   --  Return the top-level scenario which started a recursive search for other
+   --  scenarios. It is assumed that there is a valid top-level scenario on the
    --  active scenario stack.
 
+   procedure Set_Is_Recorded_Top_Level_Scenario
+     (N   : Node_Id;
+      Val : Boolean := True);
+   pragma Inline (Set_Is_Recorded_Top_Level_Scenario);
+   --  Mark scenario N as being recorded in table Top_Level_Scenarios
+
    function Static_Elaboration_Checks return Boolean;
    pragma Inline (Static_Elaboration_Checks);
    --  Determine whether the static model is in effect
@@ -1970,12 +1995,12 @@
 
       Find_Elaborated_Units;
 
-      --  Examine each top level scenario saved during the Recording phase and
+      --  Examine each top-level scenario saved during the Recording phase and
       --  perform various actions depending on the elaboration model in effect.
 
       for Index in Top_Level_Scenarios.First .. Top_Level_Scenarios.Last loop
 
-         --  Clear the table of visited scenario bodies for each new top level
+         --  Clear the table of visited scenario bodies for each new top-level
          --  scenario.
 
          Visited_Bodies.Reset;
@@ -2046,7 +2071,7 @@
 
       Level := Find_Enclosing_Level (Call);
 
-      --  Library level calls are always considered because they are part of
+      --  Library-level calls are always considered because they are part of
       --  the associated unit's elaboration actions.
 
       if Level in Library_Level then
@@ -3589,7 +3614,7 @@
                return Declaration_Level;
             end if;
 
-         --  The current construct is a declaration level encapsulator
+         --  The current construct is a declaration-level encapsulator
 
          elsif Nkind_In (Curr, N_Entry_Body,
                                N_Subprogram_Body,
@@ -3612,9 +3637,9 @@
                return Declaration_Level;
             end if;
 
-         --  The current construct is a non-library level encapsulator which
+         --  The current construct is a non-library-level encapsulator which
          --  indicates that the node cannot possibly appear at any level.
-         --  Note that this check must come after the declaration level check
+         --  Note that this check must come after the declaration-level check
          --  because both predicates share certain nodes.
 
          elsif Is_Non_Library_Level_Encapsulator (Curr) then
@@ -4103,7 +4128,7 @@
       Nested_OK : Boolean := False) return Boolean
    is
       function Find_Enclosing_Context (N : Node_Id) return Node_Id;
-      --  Return the nearest enclosing non-library level or compilation unit
+      --  Return the nearest enclosing non-library-level or compilation unit
       --  node which which encapsulates arbitrary node N. Return Empty is no
       --  such context is available.
 
@@ -4149,7 +4174,7 @@
                   return Par;
                end if;
 
-            --  Reaching a compilation unit node without hitting a non-library
+            --  Reaching a compilation unit node without hitting a non-library-
             --  level encapsulator indicates that N is at the library level in
             --  which case the compilation unit is the context.
 
@@ -4231,7 +4256,7 @@
 
    procedure Initialize is
    begin
-      --  Set the soft link which enables Atree.Rewrite to update a top level
+      --  Set the soft link which enables Atree.Rewrite to update a top-level
       --  scenario each time it is transformed into another node.
 
       Set_Rewriting_Proc (Update_Elaboration_Scenario'Access);
@@ -4837,19 +4862,6 @@
       return False;
    end Is_Bodiless_Subprogram;
 
-   --------------------------------
-   -- Is_Check_Emitting_Scenario --
-   --------------------------------
-
-   function Is_Check_Emitting_Scenario (N : Node_Id) return Boolean is
-   begin
-      return
-        Nkind_In (N, N_Call_Marker,
-                     N_Function_Instantiation,
-                     N_Package_Instantiation,
-                     N_Procedure_Instantiation);
-   end Is_Check_Emitting_Scenario;
-
    ------------------------
    -- Is_Controlled_Proc --
    ------------------------
@@ -5105,6 +5117,15 @@
           and then Present (Protected_Subprogram (Id));
    end Is_Protected_Body_Subp;
 
+   ------------------------------------
+   -- Is_Recorded_Top_Level_Scenario --
+   ------------------------------------
+
+   function Is_Recorded_Top_Level_Scenario (N : Node_Id) return Boolean is
+   begin
+      return Recorded_Top_Level_Scenarios.Get (N);
+   end Is_Recorded_Top_Level_Scenario;
+
    ------------------------
    -- Is_Safe_Activation --
    ------------------------
@@ -5568,7 +5589,7 @@
    begin
       --  The root appears within the declaratons of a block statement, entry
       --  body, subprogram body, or task body ignoring enclosing packages. The
-      --  root is always within the main unit. An up level target is a notion
+      --  root is always within the main unit. An up-level target is a notion
       --  applicable only to the static model because scenarios are reached by
       --  means of graph traversal started from a fixed declarative or library
       --  level.
@@ -5578,7 +5599,7 @@
       if Static_Elaboration_Checks
         and then Find_Enclosing_Level (Root) = Declaration_Level
       then
-         --  The target is within the main unit. It acts as an up level target
+         --  The target is within the main unit. It acts as an up-level target
          --  when it appears within a context which encloses the root.
 
          --    package body Main_Unit is
@@ -5594,7 +5615,7 @@
             return not In_Same_Context (Root, Target_Decl, Nested_OK => True);
 
          --  Otherwise the target is external to the main unit which makes it
-         --  an up level target.
+         --  an up-level target.
 
          else
             return True;
@@ -5609,14 +5630,32 @@
    -------------------------------
 
    procedure Kill_Elaboration_Scenario (N : Node_Id) is
+      package Scenarios renames Top_Level_Scenarios;
+
    begin
-      --  Eliminate the scenario by suppressing the generation of conditional
-      --  ABE checks or guaranteed ABE failures. Note that other diagnostics
-      --  must be carried out ignoring the fact that the scenario is within
-      --  dead code.
+      --  Eliminate a recorded top-level scenario when it appears within dead
+      --  code because it will not be executed at elaboration time.
 
-      if Is_Scenario (N) then
-         Set_Is_Elaboration_Checks_OK_Node (N, False);
+      if Is_Scenario (N)
+        and then Is_Recorded_Top_Level_Scenario (N)
+      then
+         --  Performance node: list traversal
+
+         for Index in Scenarios.First .. Scenarios.Last loop
+            if Scenarios.Table (Index) = N then
+               Scenarios.Table (Index) := Empty;
+
+               --  The top-level scenario is no longer recorded
+
+               Set_Is_Recorded_Top_Level_Scenario (N, False);
+               return;
+            end if;
+         end loop;
+
+         --  A recorded top-level scenario must be in the table of recorded
+         --  top-level scenarios.
+
+         pragma Assert (False);
       end if;
    end Kill_Elaboration_Scenario;
 
@@ -8352,7 +8391,7 @@
          return;
       end if;
 
-      --  Ensure that a library level call does not appear in a preelaborated
+      --  Ensure that a library-level call does not appear in a preelaborated
       --  unit. The check must come before ignoring scenarios within external
       --  units or inside generics because calls in those context must also be
       --  verified.
@@ -8426,23 +8465,23 @@
 
          Level := Find_Enclosing_Level (N);
 
-         --  Declaration level scenario
+         --  Declaration-level scenario
 
          if Declaration_Level_OK and then Level = Declaration_Level then
             null;
 
-         --  Library level scenario
+         --  Library-level scenario
 
          elsif Level in Library_Level then
             null;
 
-         --  Instantiation library level scenario
+         --  Instantiation library-level scenario
 
          elsif Level = Instantiation then
             null;
 
          --  Otherwise the scenario does not appear at the proper level and
-         --  cannot possibly act as a top level scenario.
+         --  cannot possibly act as a top-level scenario.
 
          else
             return;
@@ -8459,16 +8498,21 @@
       --  later processing by the ABE phase.
 
       Top_Level_Scenarios.Append (N);
+      Set_Is_Recorded_Top_Level_Scenario (N);
+   end Record_Elaboration_Scenario;
 
-      --  Mark a scenario which may produce run-time conditional ABE checks or
-      --  guaranteed ABE failures as recorded. The flag ensures that scenario
-      --  rewriting performed by Atree.Rewrite will be properly reflected in
-      --  all relevant internal data structures.
+   ---------------------------------------
+   -- Recorded_Top_Level_Scenarios_Hash --
+   ---------------------------------------
 
-      if Is_Check_Emitting_Scenario (N) then
-         Set_Is_Recorded_Scenario (N);
-      end if;
-   end Record_Elaboration_Scenario;
+   function Recorded_Top_Level_Scenarios_Hash
+     (Key : Node_Id) return Recorded_Top_Level_Scenarios_Index
+   is
+   begin
+      return
+        Recorded_Top_Level_Scenarios_Index
+          (Key mod Recorded_Top_Level_Scenarios_Max);
+   end Recorded_Top_Level_Scenarios_Hash;
 
    -------------------
    -- Root_Scenario --
@@ -8485,6 +8529,18 @@
       return Stack.Table (Stack.First);
    end Root_Scenario;
 
+   ----------------------------------------
+   -- Set_Is_Recorded_Top_Level_Scenario --
+   ----------------------------------------
+
+   procedure Set_Is_Recorded_Top_Level_Scenario
+     (N   : Node_Id;
+      Val : Boolean := True)
+   is
+   begin
+      Recorded_Top_Level_Scenarios.Set (N, Val);
+   end Set_Is_Recorded_Top_Level_Scenario;
+
    -------------------------------
    -- Static_Elaboration_Checks --
    -------------------------------
@@ -8590,7 +8646,7 @@
 
             --  Save a suitable scenario in the Nested_Scenarios list of the
             --  subprogram body. As a result any subsequent traversals of the
-            --  subprogram body started from a different top level scenario no
+            --  subprogram body started from a different top-level scenario no
             --  longer need to reexamine the tree.
 
             elsif Is_Suitable_Scenario (Nod) then
@@ -8683,7 +8739,7 @@
       end if;
 
       --  Nothing to do if the body was already traversed during the processing
-      --  of the same top level scenario.
+      --  of the same top-level scenario.
 
       if Visited_Bodies.Get (N) then
          return;
@@ -8697,7 +8753,7 @@
       Nested := Nested_Scenarios (Defining_Entity (N));
 
       --  The subprogram body was already examined as part of the elaboration
-      --  graph starting from a different top level scenario. There is no need
+      --  graph starting from a different top-level scenario. There is no need
       --  to traverse the declarations and statements again because this will
       --  yield the exact same scenarios. Use the nested scenarios collected
       --  during the first inspection of the body.
@@ -8721,14 +8777,18 @@
       package Scenarios renames Top_Level_Scenarios;
 
    begin
+      --  Nothing to do when the old and new scenarios are one and the same
+
+      if Old_N = New_N then
+         return;
+
       --  A scenario is being transformed by Atree.Rewrite. Update all relevant
       --  internal data structures to reflect this change. This ensures that a
       --  potential run-time conditional ABE check or a guaranteed ABE failure
       --  is inserted at the proper place in the tree.
 
-      if Is_Check_Emitting_Scenario (Old_N)
-        and then Is_Recorded_Scenario (Old_N)
-        and then Old_N /= New_N
+      elsif Is_Scenario (Old_N)
+        and then Is_Recorded_Top_Level_Scenario (Old_N)
       then
          --  Performance note: list traversal
 
@@ -8736,13 +8796,17 @@
             if Scenarios.Table (Index) = Old_N then
                Scenarios.Table (Index) := New_N;
 
-               Set_Is_Recorded_Scenario (Old_N, False);
-               Set_Is_Recorded_Scenario (New_N);
+               --  The old top-level scenario is no longer recorded, but the
+               --  new one is.
+
+               Set_Is_Recorded_Top_Level_Scenario (Old_N, False);
+               Set_Is_Recorded_Top_Level_Scenario (New_N);
                return;
             end if;
          end loop;
 
-         --  A recorded scenario must be in the table of recorded scenarios
+         --  A recorded top-level scenario must be in the table of recorded
+         --  top-level scenarios.
 
          pragma Assert (False);
       end if;
Index: ../testsuite/gnat.dg/elab3.adb
===================================================================
--- ../testsuite/gnat.dg/elab3.adb      (revision 0)
+++ ../testsuite/gnat.dg/elab3.adb      (revision 0)
@@ -0,0 +1,9 @@
+--  { dg-do compile }
+
+with Elab3_Pkg;
+
+package body Elab3 is
+   package Inst is new Elab3_Pkg (False, ABE);
+
+   procedure ABE is begin null; end ABE;
+end Elab3;
Index: ../testsuite/gnat.dg/elab3.ads
===================================================================
--- ../testsuite/gnat.dg/elab3.ads      (revision 0)
+++ ../testsuite/gnat.dg/elab3.ads      (revision 0)
@@ -0,0 +1,3 @@
+package Elab3 is
+   procedure ABE;
+end Elab3;
Index: ../testsuite/gnat.dg/elab3_pkg.adb
===================================================================
--- ../testsuite/gnat.dg/elab3_pkg.adb  (revision 0)
+++ ../testsuite/gnat.dg/elab3_pkg.adb  (revision 0)
@@ -0,0 +1,11 @@
+package body Elab3_Pkg is
+   procedure Elaborator is
+   begin
+      Proc;
+   end Elaborator;
+
+begin
+   if Elaborate then
+      Elaborator;
+   end if;
+end Elab3_Pkg;
Index: ../testsuite/gnat.dg/elab3_pkg.ads
===================================================================
--- ../testsuite/gnat.dg/elab3_pkg.ads  (revision 0)
+++ ../testsuite/gnat.dg/elab3_pkg.ads  (revision 0)
@@ -0,0 +1,7 @@
+generic
+   Elaborate : Boolean := True;
+   with procedure Proc;
+
+package Elab3_Pkg is
+   procedure Elaborator;
+end Elab3_Pkg;

Reply via email to