[Ada] Stabilization of Elaboration order v4.0
authorHristian Kirtchev <kirtchev@adacore.com>
Fri, 5 Jul 2019 07:03:49 +0000 (07:03 +0000)
committerPierre-Marie de Rodat <pmderodat@gcc.gnu.org>
Fri, 5 Jul 2019 07:03:49 +0000 (07:03 +0000)
This patch introduces several changes to the new elaboration order
mechanism:

   * Instantiations processed in the context of invocation graph
     encoding now yield a relation which is later transformed into an
     invocation edge. This ensures that the unit where the instantiation
     resides properly depends on the unit where the body of the generic
     is.

   * The diagnostics of cycles that involve invocation edges now use a
     set to avoid infinite recursion when visiting paths that represent
     recursive code.

   * Various diagnostics that suggest the use of switches have been
     updated to indicate which tool the switches apply to.

   * Bindo can now output the dependencies of various units that specify
     why a predecessor unit must be elaborated prior to a successor
     unit. This functionality implements binder switch -e (output
     complete list of elaboration order dependencies).

   * The output of the elaboration order is now identical to that
     emitted by Binde.

   * The nature of the invocation graph encoding is now recorded in the
     ALI record rather than the Unit record of a unit. This ensures that
     both the spec and body share the same encoding kind.

   * A section on debugging elaboration order issues is now available in
     Bindo.

2019-07-05  Hristian Kirtchev  <kirtchev@adacore.com>

gcc/ada/

* ali.adb (For_Each_Invocation_Construct,
For_Each_Invocation_Relation): New version.
(Scan_ALI): Initialize field Invocation_Graph_Encoding.
(Set_Invocation_Graph_Encoding): Update the setting of the
invocation graph encoding.
* ali.ads: Move field Invocation_Graph_Encoding from Unit_Record
to ALI_Record because the encoding applies to the whole ALI,
rather than one of the units (spec or body) for which the ALI
file was created.
(For_Each_Invocation_Construct, For_Each_Invocation_Relation):
New version.
* bindo.adb: Update the section on switches.  Complete the
section of debugging elaboration order issues.
(Find_Elaboration_Order): Prepare the routine for the switch
from the old to the new elaboration order mechanism.
* bindo-diagnostics.adb (Find_And_Output_Invocation_Paths):
Manage a visited set used by Visit_Vertex.
(Output_All_Cycles_Suggestions,
Output_Dynamic_Model_Suggestions): Clarify the nature of the
suggested switch.
(Output_Elaborate_Body_Transition): Update the diagnostic to
emit a better message.
(Output_Forced_Suggestions, Output_Full_Encoding_Suggestions):
Clarify the nature of the suggested switch.
(Visit_Vertex): Update the parameter profile to add a set of
invokers visited during the transition. This set prevents
infinite exploration of the graph in case the invocations are
recursive.
* bindo-elaborators.adb: Add a use clause for
Bindo.Writers.Dependency_Writers.
(Elaborate_Units_Common): Output the library graph after it has
been augmented with invocation edges. Output just the components
instead of outputting the whole library graph again.
(Elaborate_Units_Dynamic, Elaborate_Units_Static): Output the
dependencies as expressed in the library graph.
* bindo-units.adb (Invocation_Graph_Encoding): Update the
extraction of the invocation graph encoding.
* bindo-writers.adb: Add with and use clauses for Binderr and
Butil.
(palgc, plgc): New debug routine.
(Write_Components): Moved to the spec. Add a header for the
output.
(Write_Dependencies, Write_Dependencies_Of_Vertex,
Write_Dependency_Edge): New routine.
(Write_Elaboration_Order): Update the logic to follow the format
of Binde's order output.
(Write_Library_Graph): Do not output the components every time
the graph is written.
(Write_Unit): Output the invocation graph encoding of the unit.
Output the invocation constructs and relations for the unit
only.
* bindo-writers.ads (Write_Components): Moved from the body.
(Write_Dependencies): New routine.
* bindusg.adb: Prepare the routine for the switch from the old
to the new elaboration order mechanism.
* debug.adb: Binder switch -d_O is now not associated with any
functionality.
* einfo.adb (Is_Elaboration_Target): The attribute applies to
packages, as specified by the comment on the attribute usage.
* opt.ads: Add a global flag which controls the choice between
the new and the legacy elaboration order mechanism.
* sem_elab.adb: Add Package_Target to type Target_Kind.
(Build_Elaborate_Body_Procedure, Build_Elaborate_Procedure,
Build_Elaborate_Spec_Procedure, Check_Elaboration_Scenarios,
Check_SPARK_Model_In_Effect): Use Main_Unit_Entity to obtain the
entity of the main unit.
(Create_Package_Rep): New routine.
(Create_Target_Rep): Add processing for packages.
(Declaration_Placement_Of_Node, Has_Prior_Elaboration): Use
Main_Unit_Entity to obtain the entity of the main
 unit.
(Invocation_Graph_Recording_OK): Prepare the routine for the
switch from the old to the new elaboration order mechanism.
(Main_Unit_Entity): New routine.
(Meet_Elaboration_Requirement,
Process_Conditional_ABE_Variable_Reference): Use
Main_Unit_Entity to obtain the entity of the main unit.
(Process_Invocation_Instantiation): New routine.
(Process_Invocation_Scenario): Add processing for
instantiations.
* switch-b.adb (Scan_Binder_Switches): Prepare the routine for
the switch from the old to the new elaboration order mechanism.

From-SVN: r273128

15 files changed:
gcc/ada/ChangeLog
gcc/ada/ali.adb
gcc/ada/ali.ads
gcc/ada/bindo-diagnostics.adb
gcc/ada/bindo-elaborators.adb
gcc/ada/bindo-units.adb
gcc/ada/bindo-writers.adb
gcc/ada/bindo-writers.ads
gcc/ada/bindo.adb
gcc/ada/bindusg.adb
gcc/ada/debug.adb
gcc/ada/einfo.adb
gcc/ada/opt.ads
gcc/ada/sem_elab.adb
gcc/ada/switch-b.adb

index 882011336c12c00bd6bc05825a35f9ae45871a1e..6f04f775ac65066c2f7d9f56ac88f886cc8aa622 100644 (file)
@@ -1,3 +1,88 @@
+2019-07-05  Hristian Kirtchev  <kirtchev@adacore.com>
+
+       * ali.adb (For_Each_Invocation_Construct,
+       For_Each_Invocation_Relation): New version.
+       (Scan_ALI): Initialize field Invocation_Graph_Encoding.
+       (Set_Invocation_Graph_Encoding): Update the setting of the
+       invocation graph encoding.
+       * ali.ads: Move field Invocation_Graph_Encoding from Unit_Record
+       to ALI_Record because the encoding applies to the whole ALI,
+       rather than one of the units (spec or body) for which the ALI
+       file was created.
+       (For_Each_Invocation_Construct, For_Each_Invocation_Relation):
+       New version.
+       * bindo.adb: Update the section on switches.  Complete the
+       section of debugging elaboration order issues.
+       (Find_Elaboration_Order): Prepare the routine for the switch
+       from the old to the new elaboration order mechanism.
+       * bindo-diagnostics.adb (Find_And_Output_Invocation_Paths):
+       Manage a visited set used by Visit_Vertex.
+       (Output_All_Cycles_Suggestions,
+       Output_Dynamic_Model_Suggestions): Clarify the nature of the
+       suggested switch.
+       (Output_Elaborate_Body_Transition): Update the diagnostic to
+       emit a better message.
+       (Output_Forced_Suggestions, Output_Full_Encoding_Suggestions):
+       Clarify the nature of the suggested switch.
+       (Visit_Vertex): Update the parameter profile to add a set of
+       invokers visited during the transition. This set prevents
+       infinite exploration of the graph in case the invocations are
+       recursive.
+       * bindo-elaborators.adb: Add a use clause for
+       Bindo.Writers.Dependency_Writers.
+       (Elaborate_Units_Common): Output the library graph after it has
+       been augmented with invocation edges. Output just the components
+       instead of outputting the whole library graph again.
+       (Elaborate_Units_Dynamic, Elaborate_Units_Static): Output the
+       dependencies as expressed in the library graph.
+       * bindo-units.adb (Invocation_Graph_Encoding): Update the
+       extraction of the invocation graph encoding.
+       * bindo-writers.adb: Add with and use clauses for Binderr and
+       Butil.
+       (palgc, plgc): New debug routine.
+       (Write_Components): Moved to the spec. Add a header for the
+       output.
+       (Write_Dependencies, Write_Dependencies_Of_Vertex,
+       Write_Dependency_Edge): New routine.
+       (Write_Elaboration_Order): Update the logic to follow the format
+       of Binde's order output.
+       (Write_Library_Graph): Do not output the components every time
+       the graph is written.
+       (Write_Unit): Output the invocation graph encoding of the unit.
+       Output the invocation constructs and relations for the unit
+       only.
+       * bindo-writers.ads (Write_Components): Moved from the body.
+       (Write_Dependencies): New routine.
+       * bindusg.adb: Prepare the routine for the switch from the old
+       to the new elaboration order mechanism.
+       * debug.adb: Binder switch -d_O is now not associated with any
+       functionality.
+       * einfo.adb (Is_Elaboration_Target): The attribute applies to
+       packages, as specified by the comment on the attribute usage.
+       * opt.ads: Add a global flag which controls the choice between
+       the new and the legacy elaboration order mechanism.
+       * sem_elab.adb: Add Package_Target to type Target_Kind.
+       (Build_Elaborate_Body_Procedure, Build_Elaborate_Procedure,
+       Build_Elaborate_Spec_Procedure, Check_Elaboration_Scenarios,
+       Check_SPARK_Model_In_Effect): Use Main_Unit_Entity to obtain the
+       entity of the main unit.
+       (Create_Package_Rep): New routine.
+       (Create_Target_Rep): Add processing for packages.
+       (Declaration_Placement_Of_Node, Has_Prior_Elaboration): Use
+       Main_Unit_Entity to obtain the entity of the main
+        unit.
+       (Invocation_Graph_Recording_OK): Prepare the routine for the
+       switch from the old to the new elaboration order mechanism.
+       (Main_Unit_Entity): New routine.
+       (Meet_Elaboration_Requirement,
+       Process_Conditional_ABE_Variable_Reference): Use
+       Main_Unit_Entity to obtain the entity of the main unit.
+       (Process_Invocation_Instantiation): New routine.
+       (Process_Invocation_Scenario): Add processing for
+       instantiations.
+       * switch-b.adb (Scan_Binder_Switches): Prepare the routine for
+       the switch from the old to the new elaboration order mechanism.
+
 2019-07-05  Joffrey Huguet  <huguet@adacore.com>
 
        * libgnat/a-textio.adb: Add abstract state refinment.
index aa8b2424696d01eacfa283a3f314bae11c6a6f0d..feea73f010f9bf2d580112e8073cd288a0b0f393 100644 (file)
@@ -510,6 +510,27 @@ package body ALI is
       end loop;
    end For_Each_Invocation_Construct;
 
+   -----------------------------------
+   -- For_Each_Invocation_Construct --
+   -----------------------------------
+
+   procedure For_Each_Invocation_Construct
+     (U_Id      : Unit_Id;
+      Processor : Invocation_Construct_Processor_Ptr)
+   is
+      pragma Assert (Present (U_Id));
+      pragma Assert (Processor /= null);
+
+      U_Rec : Unit_Record renames Units.Table (U_Id);
+
+   begin
+      for IC_Id in U_Rec.First_Invocation_Construct ..
+                   U_Rec.Last_Invocation_Construct
+      loop
+         Processor.all (IC_Id);
+      end loop;
+   end For_Each_Invocation_Construct;
+
    ----------------------------------
    -- For_Each_Invocation_Relation --
    ----------------------------------
@@ -527,6 +548,27 @@ package body ALI is
       end loop;
    end For_Each_Invocation_Relation;
 
+   ----------------------------------
+   -- For_Each_Invocation_Relation --
+   ----------------------------------
+
+   procedure For_Each_Invocation_Relation
+     (U_Id      : Unit_Id;
+      Processor : Invocation_Relation_Processor_Ptr)
+   is
+      pragma Assert (Present (U_Id));
+      pragma Assert (Processor /= null);
+
+      U_Rec : Unit_Record renames Units.Table (U_Id);
+
+   begin
+      for IR_Id in U_Rec.First_Invocation_Relation ..
+                   U_Rec.Last_Invocation_Relation
+      loop
+         Processor.all (IR_Id);
+      end loop;
+   end For_Each_Invocation_Relation;
+
    ----------
    -- Hash --
    ----------
@@ -1831,6 +1873,7 @@ package body ALI is
         First_Specific_Dispatching   => Specific_Dispatching.Last + 1,
         First_Unit                   => No_Unit_Id,
         GNATprove_Mode               => False,
+        Invocation_Graph_Encoding    => No_Encoding,
         Last_Interrupt_State         => Interrupt_States.Last,
         Last_Sdep                    => No_Sdep_Id,
         Last_Specific_Dispatching    => Specific_Dispatching.Last,
@@ -3807,9 +3850,10 @@ package body ALI is
       if Update_Units then
          declare
             Curr_Unit : Unit_Record renames Units.Table (Units.Last);
+            Curr_ALI  : ALIs_Record renames ALIs.Table  (Curr_Unit.My_ALI);
 
          begin
-            Curr_Unit.Invocation_Graph_Encoding := Kind;
+            Curr_ALI.Invocation_Graph_Encoding := Kind;
          end;
       end if;
    end Set_Invocation_Graph_Encoding;
index 6db9e49a36fc53eb6981f829627f2a19c008c087..3fa527e3d841eaefda31cad6f010b16fd6e233bf 100644 (file)
@@ -273,6 +273,11 @@ package ALI is
       --  Last_Specific_Dispatching = First_Specific_Dispatching - 1. That
       --  is why the 'Base reference is there, it can be one less than the
       --  lower bound of the subtype. Not set if 'S' appears in Ignore_Lines.
+
+      Invocation_Graph_Encoding : Invocation_Graph_Encoding_Kind;
+      --  The encoding format used to capture information about the invocation
+      --  constructs and relations within the corresponding ALI file of this
+      --  unit.
    end record;
 
    No_Main_Priority : constant Int := -1;
@@ -382,11 +387,6 @@ package ALI is
       Last_Arg : Arg_Id;
       --  Id of last args table entry for this file
 
-      Invocation_Graph_Encoding : Invocation_Graph_Encoding_Kind;
-      --  The encoding format used to capture information about the invocation
-      --  constructs and relations within the corresponding ALI file of this
-      --  unit.
-
       First_Invocation_Construct : Invocation_Construct_Id;
       --  Id of the first invocation construct for this unit
 
@@ -1271,13 +1271,25 @@ package ALI is
    pragma Inline (For_Each_Invocation_Construct);
    --  Invoke Processor on each invocation construct
 
+   procedure For_Each_Invocation_Construct
+     (U_Id      : Unit_Id;
+      Processor : Invocation_Construct_Processor_Ptr);
+   pragma Inline (For_Each_Invocation_Construct);
+   --  Invoke Processor on each invocation construct of unit U_Id
+
    type Invocation_Relation_Processor_Ptr is
      access procedure (IR_Id : Invocation_Relation_Id);
 
    procedure For_Each_Invocation_Relation
      (Processor : Invocation_Relation_Processor_Ptr);
    pragma Inline (For_Each_Invocation_Relation);
-   --  Invoker Processor on each invocation relation
+   --  Invoke Processor on each invocation relation
+
+   procedure For_Each_Invocation_Relation
+     (U_Id      : Unit_Id;
+      Processor : Invocation_Relation_Processor_Ptr);
+   pragma Inline (For_Each_Invocation_Relation);
+   --  Invoke Processor on each invocation relation of unit U_Id
 
    function Invocation_Construct_Kind_To_Code
      (Kind : Invocation_Construct_Kind) return Character;
index a4b031d0006b02b7d6387695445b4fd5b3a9b59e..0c9da46506301b9e2cba9614418b7fbf4b018678 100644 (file)
@@ -247,6 +247,7 @@ package body Bindo.Diagnostics is
       Last_Vertex       : Library_Graph_Vertex_Id;
       Elaborated_Vertex : Library_Graph_Vertex_Id;
       End_Vertex        : Library_Graph_Vertex_Id;
+      Visited_Invokers  : IGV_Sets.Membership_Set;
       Path              : IGE_Lists.Doubly_Linked_List;
       Path_Id           : in out Nat);
    pragma Inline (Visit_Vertex);
@@ -254,8 +255,9 @@ package body Bindo.Diagnostics is
    --  vertex Invoker_Vertex as part of a DFS traversal. Last_Vertex denotes
    --  the previous vertex in the traversal. Elaborated_Vertex is the vertex
    --  whose elaboration started the traversal. End_Vertex is the vertex that
-   --  terminates the traversal. All edges along the path are recorded in Path.
-   --  Path_Id is the id of the path.
+   --  terminates the traversal. Visited_Invoker is the set of all invokers
+   --  visited so far. All edges along the path are recorded in Path. Path_Id
+   --  is the id of the path.
 
    -------------------------
    -- Diagnose_All_Cycles --
@@ -411,6 +413,7 @@ package body Bindo.Diagnostics is
    is
       Path    : IGE_Lists.Doubly_Linked_List;
       Path_Id : Nat;
+      Visited : IGV_Sets.Membership_Set;
 
    begin
       pragma Assert (Present (Inv_Graph));
@@ -429,6 +432,7 @@ package body Bindo.Diagnostics is
 
       Path    := IGE_Lists.Create;
       Path_Id := 1;
+      Visited := IGV_Sets.Create (Number_Of_Vertices (Inv_Graph));
 
       --  Start a DFS traversal over the invocation graph, in an attempt to
       --  reach Destination from Source. The actual start of the path is the
@@ -447,10 +451,12 @@ package body Bindo.Diagnostics is
          Last_Vertex       => Source,
          Elaborated_Vertex => Source,
          End_Vertex        => Destination,
+         Visited_Invokers  => Visited,
          Path              => Path,
          Path_Id           => Path_Id);
 
       IGE_Lists.Destroy (Path);
+      IGV_Sets.Destroy  (Visited);
    end Find_And_Output_Invocation_Paths;
 
    ---------------------------
@@ -511,7 +517,7 @@ package body Bindo.Diagnostics is
 
       if Number_Of_Cycles (G) > 1 and then not Debug_Flag_Underscore_CC then
          Error_Msg_Info
-           ("    diagnose all circularities (-d_C)");
+           ("    diagnose all circularities (binder switch -d_C)");
       end if;
    end Output_All_Cycles_Suggestions;
 
@@ -535,7 +541,7 @@ package body Bindo.Diagnostics is
         and then not Is_Dynamically_Elaborated (G)
       then
          Error_Msg_Info
-           ("    use the dynamic elaboration model (-gnatE)");
+           ("    use the dynamic elaboration model (compiler switch -gnatE)");
       end if;
    end Output_Dynamic_Model_Suggestions;
 
@@ -665,17 +671,21 @@ package body Bindo.Diagnostics is
       pragma Assert (Present (Expected_Destination));
 
       --  The actual and expected destination vertices match, and denote the
-      --  spec of a unit subject to pragma Elaborate_Body. There is no need to
-      --  mention the pragma because it does not affect the path of the cycle.
-      --  Treat the edge as a regular with edge.
+      --  spec or body of a unit subject to pragma Elaborate_Body. There is no
+      --  need to mention the pragma because it does not affect the path of the
+      --  cycle. Treat the edge as a regular with edge.
       --
       --               Actual_Destination
       --    Source --> spec Elaborate_Body -->
       --               Expected_Destination
+      --
+      --               spec Elaborate_Body
+      --
+      --               Actual_Destination
+      --    Source --> body -->
+      --               Expected_Destination
 
       if Actual_Destination = Expected_Destination then
-         pragma Assert (Is_Spec (G, Actual_Destination));
-
          Error_Msg_Unit_1 := Name (G, Source);
          Error_Msg_Unit_2 := Name (G, Actual_Destination);
          Error_Msg_Info
@@ -698,14 +708,18 @@ package body Bindo.Diagnostics is
          pragma Assert
            (Proper_Body (G, Actual_Destination) = Expected_Destination);
 
+         Error_Msg_Unit_1 := Name (G, Source);
+         Error_Msg_Unit_2 := Name (G, Actual_Destination);
+         Error_Msg_Info
+           ("    unit $ has with clause for unit $");
+
          Error_Msg_Unit_1 := Name (G, Actual_Destination);
          Error_Msg_Info
            ("    unit $ is subject to pragma Elaborate_Body");
 
-         Error_Msg_Unit_1 := Name (G, Source);
-         Error_Msg_Unit_2 := Name (G, Expected_Destination);
+         Error_Msg_Unit_1 := Name (G, Expected_Destination);
          Error_Msg_Info
-           ("    unit $ has with clause for unit $");
+           ("    unit $ is in the closure of pragma Elaborate_Body");
       end if;
    end Output_Elaborate_Body_Transition;
 
@@ -832,8 +846,10 @@ package body Bindo.Diagnostics is
       Error_Msg_Unit_1 := Name (G, Succ);
       Error_Msg_Unit_2 := Name (G, Pred);
       Error_Msg_Info
-        ("    remove the dependency of unit $ on unit $ from argument of -f "
-         & "switch");
+        ("    remove the dependency of unit $ on unit $ from the argument of "
+         & "switch -f");
+      Error_Msg_Info
+        ("    remove switch -f");
    end Output_Forced_Suggestions;
 
    ------------------------------
@@ -950,7 +966,8 @@ package body Bindo.Diagnostics is
 
          if Invocation_Graph_Encoding (G, Succ) /= Full_Path_Encoding then
             Error_Msg_Info
-              ("    use detailed invocation information (-gnatd_F)");
+              ("    use detailed invocation information (compiler switch "
+               & "-gnatd_F)");
          end if;
       end if;
    end Output_Full_Encoding_Suggestions;
@@ -1410,6 +1427,7 @@ package body Bindo.Diagnostics is
       Last_Vertex       : Library_Graph_Vertex_Id;
       Elaborated_Vertex : Library_Graph_Vertex_Id;
       End_Vertex        : Library_Graph_Vertex_Id;
+      Visited_Invokers  : IGV_Sets.Membership_Set;
       Path              : IGE_Lists.Doubly_Linked_List;
       Path_Id           : in out Nat)
    is
@@ -1425,6 +1443,7 @@ package body Bindo.Diagnostics is
       pragma Assert (Present (Last_Vertex));
       pragma Assert (Present (Elaborated_Vertex));
       pragma Assert (Present (End_Vertex));
+      pragma Assert (IGV_Sets.Present (Visited_Invokers));
       pragma Assert (IGE_Lists.Present (Path));
 
       --  The current invocation vertex resides within the end library vertex.
@@ -1444,7 +1463,14 @@ package body Bindo.Diagnostics is
       --  Otherwise extend the search for the end library vertex via all edges
       --  to targets.
 
-      else
+      elsif not IGV_Sets.Contains (Visited_Invokers, Invoker) then
+
+         --  Prepare for invoker backtracking
+
+         IGV_Sets.Insert (Visited_Invokers, Invoker);
+
+         --  Extend the search via all edges to targets
+
          Iter := Iterate_Edges_To_Targets (Inv_Graph, Invoker);
          while Has_Next (Iter) loop
             Next (Iter, Edge);
@@ -1466,6 +1492,7 @@ package body Bindo.Diagnostics is
                Last_Vertex       => Invoker_Vertex,
                Elaborated_Vertex => Elaborated_Vertex,
                End_Vertex        => End_Vertex,
+               Visited_Invokers  => Visited_Invokers,
                Path              => Path,
                Path_Id           => Path_Id);
 
@@ -1473,6 +1500,10 @@ package body Bindo.Diagnostics is
 
             IGE_Lists.Delete_Last (Path);
          end loop;
+
+         --  Backtrack the invoker
+
+         IGV_Sets.Delete (Visited_Invokers, Invoker);
       end if;
    end Visit_Vertex;
 
index d26101a4f9b273e52358bde29677131e997f1af1..762198bd69131e9591258f5fe4b7c79a567b3d3b 100644 (file)
@@ -52,6 +52,7 @@ use  Bindo.Validators.Library_Graph_Validators;
 with Bindo.Writers;
 use  Bindo.Writers;
 use  Bindo.Writers.ALI_Writers;
+use  Bindo.Writers.Dependency_Writers;
 use  Bindo.Writers.Elaboration_Order_Writers;
 use  Bindo.Writers.Invocation_Graph_Writers;
 use  Bindo.Writers.Library_Graph_Writers;
@@ -695,12 +696,13 @@ package body Bindo.Elaborators is
          --  to a unit that result in extra edges within the library graph.
 
          Augment_Library_Graph (Inv_Graph, Lib_Graph);
+         Write_Library_Graph (Lib_Graph);
 
          --  Create and output the component graph by collapsing all library
          --  items into library units and traversing the library graph.
 
-         Find_Components     (Lib_Graph);
-         Write_Library_Graph (Lib_Graph);
+         Find_Components  (Lib_Graph);
+         Write_Components (Lib_Graph);
 
          --  Traverse the library graph to determine the elaboration order of
          --  units.
@@ -742,6 +744,11 @@ package body Bindo.Elaborators is
          if Status = Order_OK then
             Order := Mix_Order;
 
+            --  Output the dependencies of vertices when switch -e (output
+            --  complete list of elaboration order dependencies) is active.
+
+            Write_Dependencies (Mix_Lib_Graph);
+
          --  The library graph contains an Elaborate_All circularity. There is
          --  no point in re-elaborating the units without the information from
          --  the invocation graph because the circularity will persist.
@@ -774,6 +781,11 @@ package body Bindo.Elaborators is
             if Status = Order_OK then
                Order := Dyn_Order;
 
+               --  Output the dependencies of vertices when switch -e (output
+               --  complete list of elaboration order dependencies) is active.
+
+               Write_Dependencies (Dyn_Lib_Graph);
+
             --  Otherwise the library graph contains a circularity without the
             --  extra information provided by the invocation graph. Diagnose
             --  the circularity.
@@ -820,9 +832,16 @@ package body Bindo.Elaborators is
             Order         => Order,
             Status        => Status);
 
-         --  The augmented library graph contains a circularity
+         --  The elaboration order is satisfactory. Output the dependencies of
+         --  vertices when switch -e (output complete list of elaboration order
+         --  dependencies) is active.
 
-         if Status /= Order_OK then
+         if Status = Order_OK then
+            Write_Dependencies (Lib_Graph);
+
+         --  Otherwise the augmented library graph contains a circularity
+
+         else
             Diagnose_Circularities
               (Inv_Graph => Inv_Graph,
                Lib_Graph => Lib_Graph);
index f234f40a3834e1cf437708487ded60efeb703995..05b52507f66ba7155d35394f83639e591b596be7 100644 (file)
@@ -243,9 +243,10 @@ package body Bindo.Units is
       pragma Assert (Present (U_Id));
 
       U_Rec : Unit_Record renames ALI.Units.Table (U_Id);
+      U_ALI : ALIs_Record renames ALI.ALIs.Table  (U_Rec.My_ALI);
 
    begin
-      return U_Rec.Invocation_Graph_Encoding;
+      return U_ALI.Invocation_Graph_Encoding;
    end Invocation_Graph_Encoding;
 
    -------------------------------
index 067ba1ffad516e28a81809a6b668851b24e5babd..a3b45fce76627140b9e70ed156d743368da0732e 100644 (file)
 --                                                                          --
 ------------------------------------------------------------------------------
 
-with Debug;  use Debug;
-with Fname;  use Fname;
-with Opt;    use Opt;
-with Output; use Output;
+with Binderr; use Binderr;
+with Butil;   use Butil;
+with Debug;   use Debug;
+with Fname;   use Fname;
+with Opt;     use Opt;
+with Output;  use Output;
 
 with Bindo.Units;
 use  Bindo.Units;
@@ -271,10 +273,19 @@ package body Bindo.Writers is
          Write_Int (Int (U_Rec.Last_Invocation_Relation));
          Write_Str (")");
          Write_Eol;
+
+         Write_Str ("  Invocation_Graph_Encoding = ");
+         Write_Str (Invocation_Graph_Encoding (U_Id)'Img);
+         Write_Eol;
          Write_Eol;
 
-         For_Each_Invocation_Construct (Write_Invocation_Construct'Access);
-         For_Each_Invocation_Relation  (Write_Invocation_Relation'Access);
+         For_Each_Invocation_Construct
+           (U_Id      => U_Id,
+            Processor => Write_Invocation_Construct'Access);
+
+         For_Each_Invocation_Relation
+           (U_Id      => U_Id,
+            Processor => Write_Invocation_Relation'Access);
       end Write_Unit;
 
       -----------------------
@@ -323,6 +334,18 @@ package body Bindo.Writers is
       pragma Inline (Write_Cyclic_Edge);
       --  Write cyclic edge Edge of library graph G to standard
 
+      -----------
+      -- Debug --
+      -----------
+
+      procedure palgc (G : Library_Graph) renames Write_Cycles;
+      pragma Unreferenced (palgc);
+
+      procedure plgc
+        (G     : Library_Graph;
+         Cycle : Library_Graph_Cycle_Id) renames Write_Cycle;
+      pragma Unreferenced (plgc);
+
       -----------------
       -- Write_Cycle --
       -----------------
@@ -425,6 +448,178 @@ package body Bindo.Writers is
       end Write_Cyclic_Edge;
    end Cycle_Writers;
 
+   ------------------------
+   -- Dependency_Writers --
+   ------------------------
+
+   package body Dependency_Writers is
+
+      -----------------------
+      -- Local subprograms --
+      -----------------------
+
+      procedure Write_Dependencies_Of_Vertex
+        (G      : Library_Graph;
+         Vertex : Library_Graph_Vertex_Id);
+      pragma Inline (Write_Dependencies_Of_Vertex);
+      --  Write the dependencies of vertex Vertex of library graph G to
+      --  standard output.
+
+      procedure Write_Dependency_Edge
+        (G    : Library_Graph;
+         Edge : Library_Graph_Edge_Id);
+      pragma Inline (Write_Dependency_Edge);
+      --  Write the dependency described by edge Edge of library graph G to
+      --  standard output.
+
+      ------------------------
+      -- Write_Dependencies --
+      ------------------------
+
+      procedure Write_Dependencies (G : Library_Graph) is
+         Use_Formatting : constant Boolean := not Zero_Formatting;
+
+         Iter   : Library_Graphs.All_Vertex_Iterator;
+         Vertex : Library_Graph_Vertex_Id;
+
+      begin
+         pragma Assert (Present (G));
+
+         --  Nothing to do when switch -e (output complete list of elaboration
+         --  order dependencies) is not in effect.
+
+         if not Elab_Dependency_Output then
+            return;
+         end if;
+
+         if Use_Formatting then
+            Write_Eol;
+            Write_Line ("ELABORATION ORDER DEPENDENCIES");
+            Write_Eol;
+         end if;
+
+         Info_Prefix_Suppress := True;
+
+         Iter := Iterate_All_Vertices (G);
+         while Has_Next (Iter) loop
+            Next (Iter, Vertex);
+
+            Write_Dependencies_Of_Vertex (G, Vertex);
+         end loop;
+
+         Info_Prefix_Suppress := False;
+
+         if Use_Formatting then
+            Write_Eol;
+         end if;
+      end Write_Dependencies;
+
+      ----------------------------------
+      -- Write_Dependencies_Of_Vertex --
+      ----------------------------------
+
+      procedure Write_Dependencies_Of_Vertex
+        (G      : Library_Graph;
+         Vertex : Library_Graph_Vertex_Id)
+      is
+         Edge : Library_Graph_Edge_Id;
+         Iter : Edges_To_Successors_Iterator;
+
+      begin
+         pragma Assert (Present (G));
+         pragma Assert (Present (Vertex));
+
+         --  Nothing to do for internal and predefined units
+
+         if Is_Internal_Unit (G, Vertex)
+           or else Is_Predefined_Unit (G, Vertex)
+         then
+            return;
+         end if;
+
+         Iter := Iterate_Edges_To_Successors (G, Vertex);
+         while Has_Next (Iter) loop
+            Next (Iter, Edge);
+
+            Write_Dependency_Edge (G, Edge);
+         end loop;
+      end Write_Dependencies_Of_Vertex;
+
+      ---------------------------
+      -- Write_Dependency_Edge --
+      ---------------------------
+
+      procedure Write_Dependency_Edge
+        (G    : Library_Graph;
+         Edge : Library_Graph_Edge_Id)
+      is
+         pragma Assert (Present (G));
+         pragma Assert (Present (Edge));
+
+         Pred : constant Library_Graph_Vertex_Id := Predecessor (G, Edge);
+         Succ : constant Library_Graph_Vertex_Id := Successor   (G, Edge);
+
+      begin
+         --  Nothing to do for internal and predefined units
+
+         if Is_Internal_Unit (G, Succ)
+           or else Is_Predefined_Unit (G, Succ)
+         then
+            return;
+         end if;
+
+         Error_Msg_Unit_1 := Name (G, Pred);
+         Error_Msg_Unit_2 := Name (G, Succ);
+         Error_Msg_Output
+           (Msg  => "   unit $ must be elaborated before unit $",
+            Info => True);
+
+         Error_Msg_Unit_1 := Name (G, Succ);
+         Error_Msg_Unit_2 := Name (G, Pred);
+
+         if Is_Elaborate_All_Edge (G, Edge) then
+            Error_Msg_Output
+              (Msg  =>
+                 "     reason: unit $ has with clause and pragma "
+                 & "Elaborate_All for unit $",
+               Info => True);
+
+         elsif Is_Elaborate_Body_Edge (G, Edge) then
+            Error_Msg_Output
+              (Msg  => "     reason: unit $ has with clause for unit $",
+               Info => True);
+
+         elsif Is_Elaborate_Edge (G, Edge) then
+            Error_Msg_Output
+              (Msg  =>
+                 "     reason: unit $ has with clause and pragma Elaborate "
+                 & "for unit $",
+               Info => True);
+
+         elsif Is_Forced_Edge (G, Edge) then
+            Error_Msg_Output
+              (Msg  =>
+                 "     reason: unit $ has a dependency on unit $ forced by -f "
+                 & "switch",
+               Info => True);
+
+         elsif Is_Invocation_Edge (G, Edge) then
+            Error_Msg_Output
+              (Msg  =>
+                 "     reason: unit $ invokes a construct of unit $ at "
+                 & "elaboration time",
+               Info => True);
+
+         else
+            pragma Assert (Is_With_Edge (G, Edge));
+
+            Error_Msg_Output
+              (Msg  => "     reason: unit $ has with clause for unit $",
+               Info => True);
+         end if;
+      end Write_Dependency_Edge;
+   end Dependency_Writers;
+
    -------------------------------
    -- Elaboration_Order_Writers --
    -------------------------------
@@ -448,25 +643,27 @@ package body Bindo.Writers is
       -----------------------------
 
       procedure Write_Elaboration_Order (Order : Unit_Id_Table) is
+         Use_Formatting : constant Boolean := not Zero_Formatting;
+
       begin
-         --  Nothing to do when switch -d_O (output elaboration order) is not
-         --  in effect.
+         --  Nothing to do when switch -l (output chosen elaboration order) is
+         --  not in effect.
 
-         if not Debug_Flag_Underscore_OO then
+         if not Elab_Order_Output then
             return;
          end if;
 
-         Write_Str ("Elaboration Order");
-         Write_Eol;
-         Write_Eol;
+         if Use_Formatting then
+            Write_Eol;
+            Write_Str ("ELABORATION ORDER");
+            Write_Eol;
+         end if;
 
          Write_Units (Order);
 
-         Write_Eol;
-         Write_Str ("Elaboration Order end");
-         Write_Eol;
-
-         Write_Eol;
+         if Use_Formatting then
+            Write_Eol;
+         end if;
       end Write_Elaboration_Order;
 
       ----------------
@@ -474,13 +671,16 @@ package body Bindo.Writers is
       ----------------
 
       procedure Write_Unit (U_Id : Unit_Id) is
+         Use_Formatting : constant Boolean := not Zero_Formatting;
+
       begin
          pragma Assert (Present (U_Id));
 
-         Write_Str  ("unit (U_Id_");
-         Write_Int  (Int (U_Id));
-         Write_Str  (") name = ");
-         Write_Name (Name (U_Id));
+         if Use_Formatting then
+            Write_Str ("   ");
+         end if;
+
+         Write_Unit_Name (Name (U_Id));
          Write_Eol;
       end Write_Unit;
 
@@ -825,10 +1025,6 @@ package body Bindo.Writers is
       --  Write all vertices of component Comp of library graph G to standard
       --  output.
 
-      procedure Write_Components (G : Library_Graph);
-      pragma Inline (Write_Components);
-      --  Write all components of library graph G to standard output
-
       procedure Write_Edges_To_Successors
         (G      : Library_Graph;
          Vertex : Library_Graph_Vertex_Id);
@@ -942,7 +1138,22 @@ package body Bindo.Writers is
          Iter : Component_Iterator;
 
       begin
+         --  Nothing to do when switch -d_L (output library item graph) is not
+         --  in effect.
+
+         if not Debug_Flag_Underscore_LL then
+            return;
+         end if;
+
+         Write_Str ("Library Graph components");
+         Write_Eol;
+         Write_Eol;
+
          if Num_Of_Comps > 0 then
+            Write_Str ("Components: ");
+            Write_Num (Int (Num_Of_Comps));
+            Write_Eol;
+
             Iter := Iterate_Components (G);
             while Has_Next (Iter) loop
                Next (Iter, Comp);
@@ -952,6 +1163,11 @@ package body Bindo.Writers is
          else
             Write_Eol;
          end if;
+
+         Write_Str ("Library Graph components end");
+         Write_Eol;
+
+         Write_Eol;
       end Write_Components;
 
       -------------------------------
@@ -1009,7 +1225,6 @@ package body Bindo.Writers is
 
          Write_Statistics (G);
          Write_Library_Graph_Vertices (G);
-         Write_Components (G);
 
          Write_Str ("Library Graph end");
          Write_Eol;
@@ -1231,10 +1446,12 @@ package body Bindo.Writers is
       ---------------------
 
       procedure Write_File_Name (Nam : File_Name_Type) is
+         Use_Formatting : constant Boolean := not Zero_Formatting;
+
       begin
          pragma Assert (Present (Nam));
 
-         if not Zero_Formatting then
+         if Use_Formatting then
             Write_Str ("   ");
          end if;
 
@@ -1296,6 +1513,8 @@ package body Bindo.Writers is
       ------------------------
 
       procedure Write_Unit_Closure (Order : Unit_Id_Table) is
+         Use_Formatting : constant Boolean := not Zero_Formatting;
+
          Set : Membership_Set;
 
       begin
@@ -1306,7 +1525,7 @@ package body Bindo.Writers is
             return;
          end if;
 
-         if not Zero_Formatting then
+         if Use_Formatting then
             Write_Eol;
             Write_Line ("REFERENCED SOURCES");
          end if;
@@ -1320,7 +1539,7 @@ package body Bindo.Writers is
 
          Destroy (Set);
 
-         if not Zero_Formatting then
+         if Use_Formatting then
             Write_Eol;
          end if;
       end Write_Unit_Closure;
index b7916387c514ab2594f5a3e5b3150d34c7f1afe3..ff6b9b3b6602a0702b7f45a7b05b3dfd338fe411 100644 (file)
@@ -91,6 +91,17 @@ package Bindo.Writers is
 
    end Cycle_Writers;
 
+   ------------------------
+   -- Dependency_Writers --
+   ------------------------
+
+   package Dependency_Writers is
+      procedure Write_Dependencies (G : Library_Graph);
+      --  Write all elaboration dependencies of the units represented by
+      --  vertices of library graph G.
+
+   end Dependency_Writers;
+
    -------------------------------
    -- Elaboration_Order_Writers --
    -------------------------------
@@ -116,6 +127,9 @@ package Bindo.Writers is
    ---------------------------
 
    package Library_Graph_Writers is
+      procedure Write_Components (G : Library_Graph);
+      --  Write all components of library graph G to standard output
+
       procedure Write_Library_Graph (G : Library_Graph);
       --  Write library graph G to standard output
 
index 039fd0d3ccd1d5bb0d4a3729aff9f3c06bf406b3..b3106adfb25373656c527e60bfd852bb29ea1870 100644 (file)
@@ -32,10 +32,10 @@ use  Bindo.Elaborators;
 package body Bindo is
 
    ---------------------------------
-   -- Elaboration order mechanism --
+   -- Elaboration-order mechanism --
    ---------------------------------
 
-   --  The elaboration order (EO) mechanism implemented in this unit and its
+   --  The elaboration-order (EO) mechanism implemented in this unit and its
    --  children has the following objectives:
    --
    --    * Find an ordering of all library items (historically referred to as
@@ -272,7 +272,7 @@ package body Bindo is
    --          whose elaboration cannot be guaranteed.
    --
    --        - A detailed traceback of the cycle, showcasing the transition
-   --          between units, along with any other elaboration order-related
+   --          between units, along with any other elaboration-order-related
    --          information.
    --
    --        - A set of suggestions on how to break the cycle considering the
@@ -308,18 +308,13 @@ package body Bindo is
    --
    --        GNATbind utilizes the new bindo elaboration order
    --
-   --  -d_O  Output elaboration order
-   --
-   --        GNATbind outputs the elaboration order in text format to standard
-   --        output.
-   --
    --  -d_P  Output cycle paths
    --
    --        GNATbind output the cycle paths in text format to standard output
    --
-   --  -d_T  Output elaboration order trace information
+   --  -d_T  Output elaboration-order trace information
    --
-   --        GNATbind outputs trace information on elaboration order and cycle
+   --        GNATbind outputs trace information on elaboration-order and cycle-
    --        detection activities to standard output.
    --
    --  -d_V  Validate bindo cycles, graphs, and order
@@ -327,12 +322,126 @@ package body Bindo is
    --        GNATbind validates the invocation graph, library graph along with
    --        its cycles, and elaboration order by detecting inconsistencies and
    --        producing error reports.
+   --
+   --  -e    Output complete list of elaboration-order dependencies
+   --
+   --        GNATbind outputs the dependencies between units to standard
+   --        output.
+   --
+   --  -f    Force elaboration order from given file
+   --
+   --        GNATbind applies an additional set of edges to the library graph.
+   --        The edges are read from a file specified by the argument of the
+   --        flag.
+   --
+   --  -H    Legacy elaboration-order model enabled
+   --
+   --        GNATbind uses the library-graph and heuristics-based elaboration-
+   --        order model.
+   --
+   --  -l    Output chosen elaboration order
+   --
+   --        GNATbind outputs the elaboration order in text format to standard
+   --        output.
+   --
+   --  -p    Pessimistic (worst-case) elaboration order
+   --
+   --        This switch is not used in Bindo and its children.
 
    ----------------------------------------
-   -- Debugging elaboration order issues --
+   -- Debugging elaboration-order issues --
    ----------------------------------------
 
-   --  ??? more on this later
+   --  Prior to debugging elaboration-order-related issues, enable all relevant
+   --  debug flags to collect as much information as possible. Depending on the
+   --  number of files in the bind, Bindo may emit anywhere between several MBs
+   --  to several hundred MBs of data to standard output. The switches are:
+   --
+   --    -d_A -d_C -d_I -d_L -d_P -d_T -d_V
+   --
+   --  Bindo offers several debugging routines that can be invoked from gdb.
+   --  Those are defined in the body of Bindo.Writers, in sections denoted by
+   --  header Debug. For quick reference, the routines are:
+   --
+   --    palgc  --  print all library-graph cycles
+   --    pau    --  print all units
+   --    pc     --  print component
+   --    pige   --  print invocation-graph edge
+   --    pigv   --  print invocation-graph vertex
+   --    plgc   --  print library-graph cycle
+   --    plge   --  print library-graph edge
+   --    plgv   --  print library-graph vertex
+   --    pu     --  print units
+   --
+   --  * Invalid elaboration order
+   --
+   --    The elaboration order is invalid when:
+   --
+   --      - A unit that requires elaboration is missing from the order
+   --      - A unit that does not require elaboration is present in the order
+   --
+   --    Examine the output of the elaboration algorithm available via switch
+   --    -d_T to determine how the related units were included in or excluded
+   --    from the order. Determine whether the library graph contains all the
+   --    relevant edges for those units.
+   --
+   --    Units and routines of interest:
+   --      Bindo.Elaborators
+   --      Elaborate_Library_Graph
+   --      Elaborate_Units_Common
+   --      Elaborate_Units_Dynamic
+   --      Elaborate_Units_Static
+   --
+   --  * Invalid invocation graph
+   --
+   --    The invocation graph is invalid when:
+   --
+   --      - An edge lacks an attribute
+   --      - A vertex lacks an attribute
+   --
+   --    Find the malformed edge or vertex and determine which attribute is
+   --    missing. Examine the contents of the invocation-related ALI tables
+   --    available via switch -d_A. If the invocation construct or relation
+   --    is missing, verify the ALI file. If the ALI lacks all the relevant
+   --    information, then Sem_Elab most likely failed to discover a valid
+   --    elaboration path.
+   --
+   --    Units and routines of interest:
+   --      Bindo.Builders
+   --      Bindo.Graphs
+   --      Add_Edge
+   --      Add_Vertex
+   --      Build_Invocation_Graph
+   --
+   --  * Invalid library graph
+   --
+   --    The library graph is invalid when:
+   --
+   --      - An edge lacks an attribute
+   --      - A vertex lacks an attribute
+   --
+   --    Find the malformed edge or vertex and determine which attribute is
+   --    missing.
+   --
+   --    Units and routines of interest:
+   --      Bindo.Builders
+   --      Bindo.Graphs
+   --      Add_Edge
+   --      Add_Vertex
+   --      Build_Library_Graph
+   --
+   --  * Invalid library-graph cycle
+   --
+   --    A library-graph cycle is invalid when:
+   --
+   --      - It lacks enough edges to form a circuit
+   --      - At least one edge in the circuit is repeated
+   --
+   --    Find the malformed cycle and determine which attribute is missing.
+   --
+   --    Units and routines of interest:
+   --      Bindo.Graphs
+   --      Find_Cycles
 
    ----------------------------
    -- Find_Elaboration_Order --
@@ -343,7 +452,28 @@ package body Bindo is
       Main_Lib_File : File_Name_Type)
    is
    begin
-      --  Use the invocation and library graph-based elaboration order when
+      --  ??? Enable the following code when switching from the old to the new
+      --  elaboration-order mechanism.
+
+      --  Use the library graph and heuristic-based elaboration order when
+      --  switch -H (legacy elaboration-order mode enabled).
+
+      --  if Legacy_Elaboration_Order then
+      --     Binde.Find_Elab_Order (Order, Main_Lib_File);
+
+      --  Otherwise use the invocation and library-graph-based elaboration
+      --  order.
+
+      --  else
+      --     Invocation_And_Library_Graph_Elaborators.Elaborate_Units
+      --       (Order         => Order,
+      --        Main_Lib_File => Main_Lib_File);
+      --  end if;
+
+      --  ??? Remove the following code when switching from the old to the new
+      --  elaboration-order mechanism.
+
+      --  Use the invocation and library-graph-based elaboration order when
       --  switch -d_N (new bindo order) is in effect.
 
       if Debug_Flag_Underscore_NN then
@@ -351,7 +481,7 @@ package body Bindo is
            (Order         => Order,
             Main_Lib_File => Main_Lib_File);
 
-      --  Otherwise use the library graph and heuristic-based elaboration
+      --  Otherwise use the library-graph and heuristic-based elaboration
       --  order.
 
       else
index 8c51d116feed162cf486610391a2bc1b79c9daee..a4a97395672b31bf216ebad3b40b60a0b1d0dfad 100644 (file)
@@ -143,6 +143,14 @@ package body Bindusg is
       Write_Line
         ("  -h        Output this usage (help) information");
 
+      --  ??? Enable the following code when switching from the old to the new
+      --  elaboration-order mechanism.
+
+      --  Line for -H switch
+
+      --  Write_Line
+      --    ("  -H        Legacy elaboration-order model enabled");
+
       --  Lines for -I switch
 
       Write_Line
index 2635654a89a688685f4b258175afdf145497ef0e..da4bea1fec404e635dde3f0cdeb59db7f9815015 100644 (file)
@@ -389,7 +389,7 @@ package body Debug is
    --  d_L  Output library graph
    --  d_M
    --  d_N  New bindo order
-   --  d_O  Output elaboration order
+   --  d_O
    --  d_P  Output cycle paths
    --  d_Q
    --  d_R
@@ -1155,8 +1155,6 @@ package body Debug is
 
    --  d_N  GNATBIND utilizes the elaboration order provided by bindo
 
-   --  d_O  GNATBIND outputs the elaboration order of units to standard output
-
    --  d_P  GNATBIND outputs the cycle paths to standard output
 
    --  d_T  GNATBIND outputs trace information of elaboration order and cycle
index b9a9a8d53a7261ed25b82ddb869a2b63e641ff79..5fba0fa772b9275ef1ccac1c551eb3796c47fb22 100644 (file)
@@ -8127,7 +8127,7 @@ package body Einfo is
    function Is_Elaboration_Target (Id : Entity_Id) return Boolean is
    begin
       return
-        Ekind_In (Id, E_Constant, E_Variable)
+        Ekind_In (Id, E_Constant, E_Package, E_Variable)
           or else Is_Entry        (Id)
           or else Is_Generic_Unit (Id)
           or else Is_Subprogram   (Id)
index 16b5cbae00a64e2fe88a8dd16d97b36c332aa465..0b62af8b6969e1b9929977d4395d4431451cd29e 100644 (file)
@@ -947,6 +947,11 @@ package Opt is
    --  Set to True when the pre-18.x access-before-elaboration model is to be
    --  used. Modified by use of -gnatH.
 
+   Legacy_Elaboration_Order : Boolean := False;
+   --  GNATBIND
+   --  Set to True when the pre-20.x elaboration-order model is to be used.
+   --  Modified by use of -H.
+
    Link_Only : Boolean := False;
    --  GNATMAKE, GPRBUILD
    --  Set to True to skip compile and bind steps (except when Bind_Only is
index 2bd38c83780ce2a5d478585a59af9ae5cf508d47..8612428635c4af7ebab783c71ad605176ec2644d 100644 (file)
@@ -788,6 +788,9 @@ package body Sem_Elab is
      (Generic_Target,
       --  A generic unit being instantiated
 
+      Package_Target,
+      --  The package form of an instantiation
+
       Subprogram_Target,
       --  An entry, operator, or subprogram being invoked, or aliased through
       --  'Access or 'Unrestricted_Access.
@@ -2046,6 +2049,10 @@ package body Sem_Elab is
    pragma Inline (Is_Same_Unit);
    --  Determine whether entities Unit_1 and Unit_2 denote the same unit
 
+   function Main_Unit_Entity return Entity_Id;
+   pragma Inline (Main_Unit_Entity);
+   --  Return the entity of the main unit
+
    function Non_Private_View (Typ : Entity_Id) return Entity_Id;
    pragma Inline (Non_Private_View);
    --  Return the full view of private type Typ if available, otherwise return
@@ -3955,7 +3962,7 @@ package body Sem_Elab is
       --  Elaboration_Checks which appears on the initial declaration of the
       --  main unit.
 
-      Install_Elaboration_Model (Unit_Entity (Cunit_Entity (Main_Unit)));
+      Install_Elaboration_Model (Unit_Entity (Main_Unit_Entity));
 
       --  Examine the context of the main unit and record all units with prior
       --  elaboration with respect to it.
@@ -6344,7 +6351,7 @@ package body Sem_Elab is
          --  because diagnostics on reads are relevant only for external
          --  variables.
 
-         if Is_Same_Unit (Unit_Id, Cunit_Entity (Main_Unit)) then
+         if Is_Same_Unit (Unit_Id, Main_Unit_Entity) then
             null;
 
          --  Nothing to do when the variable is already initialized. Note that
@@ -8163,7 +8170,7 @@ package body Sem_Elab is
          --       body of A elaborated  <--  problem
          --
          --    The generation of an implicit pragma Elaborate_All (B) ensures
-         --    that the elaboration order mechanism will not pick the above
+         --    that the elaboration-order mechanism will not pick the above
          --    order.
          --
          --    An implicit Elaborate is NOT generated when the unit is subject
@@ -8502,10 +8509,9 @@ package body Sem_Elab is
          Elab_Body_OK : Boolean := False;
          Same_Unit_OK : Boolean := False) return Boolean
       is
-         EA_Id : constant Elaboration_Attributes_Id :=
-                   Elaboration_Attributes_Of (Unit_Id);
-
-         Main_Id   : constant Entity_Id := Cunit_Entity (Main_Unit);
+         EA_Id     : constant Elaboration_Attributes_Id :=
+                       Elaboration_Attributes_Of (Unit_Id);
+         Main_Id   : constant Entity_Id := Main_Unit_Entity;
          Unit_Prag : constant Node_Id   := Elab_Pragma (EA_Id);
          Unit_With : constant Node_Id   := With_Clause (EA_Id);
 
@@ -8575,7 +8581,7 @@ package body Sem_Elab is
       is
          pragma Assert (Nam_In (Req_Nam, Name_Elaborate, Name_Elaborate_All));
 
-         Main_Id : constant Entity_Id := Cunit_Entity (Main_Unit);
+         Main_Id : constant Entity_Id := Main_Unit_Entity;
          Unit_Id : constant Entity_Id := Find_Top_Unit (Targ_Id);
 
          procedure Elaboration_Requirement_Error;
@@ -10356,6 +10362,11 @@ package body Sem_Elab is
       pragma Inline (Create_Instantiation_Rep);
       --  Create the representation of instantiation Inst
 
+      function Create_Package_Rep
+        (Pack_Id : Entity_Id) return Target_Rep_Record;
+      pragma Inline (Create_Package_Rep);
+      --  Create the representation of package Pack_Id
+
       function Create_Protected_Entry_Rep
         (PE_Id : Entity_Id) return Target_Rep_Record;
       pragma Inline (Create_Protected_Entry_Rep);
@@ -10624,6 +10635,26 @@ package body Sem_Elab is
          return Rec;
       end Create_Instantiation_Rep;
 
+      ------------------------
+      -- Create_Package_Rep --
+      ------------------------
+
+      function Create_Package_Rep
+        (Pack_Id : Entity_Id) return Target_Rep_Record
+      is
+         Rec : Target_Rep_Record;
+
+      begin
+         Rec.Kind := Package_Target;
+
+         Spec_And_Body_From_Entity
+           (Id        => Pack_Id,
+            Body_Decl => Rec.Body_Decl,
+            Spec_Decl => Rec.Spec_Decl);
+
+         return Rec;
+      end Create_Package_Rep;
+
       --------------------------------
       -- Create_Protected_Entry_Rep --
       --------------------------------
@@ -10846,6 +10877,9 @@ package body Sem_Elab is
          then
             Rec := Create_Subprogram_Rep (Id);
 
+         elsif Ekind (Id) = E_Package then
+            Rec := Create_Package_Rep (Id);
+
          else
             pragma Assert (False);
             return Rec;
@@ -11622,6 +11656,14 @@ package body Sem_Elab is
       --  Process invocation call scenario Call with representation Call_Rep.
       --  In_State is the current state of the Processing phase.
 
+      procedure Process_Invocation_Instantiation
+        (Inst     : Node_Id;
+         Inst_Rep : Scenario_Rep_Id;
+         In_State : Processing_In_State);
+      pragma Inline (Process_Invocation_Instantiation);
+      --  Process invocation instantiation scenario Inst with representation
+      --  Inst_Rep. In_State is the current state of the Processing phase.
+
       procedure Process_Invocation_Scenario
         (N        : Node_Id;
          In_State : Processing_In_State);
@@ -11767,7 +11809,7 @@ package body Sem_Elab is
          end if;
 
          Spec_And_Body_From_Entity
-           (Id        => Cunit_Entity (Main_Unit),
+           (Id        => Main_Unit_Entity,
             Body_Decl => Body_Decl,
             Spec_Decl => Spec_Decl);
 
@@ -11799,7 +11841,7 @@ package body Sem_Elab is
 
          Set_Ekind (Proc_Id, E_Procedure);
          Set_Etype (Proc_Id, Standard_Void_Type);
-         Set_Scope (Proc_Id, Unique_Entity (Cunit_Entity (Main_Unit)));
+         Set_Scope (Proc_Id, Unique_Entity (Main_Unit_Entity));
 
          --  Create a dummy declaration for the elaboration procedure. The
          --  declaration does not need to be syntactically legal, but must
@@ -11830,7 +11872,7 @@ package body Sem_Elab is
          end if;
 
          Spec_And_Body_From_Entity
-           (Id        => Cunit_Entity (Main_Unit),
+           (Id        => Main_Unit_Entity,
             Body_Decl => Body_Decl,
             Spec_Decl => Spec_Decl);
 
@@ -11995,7 +12037,7 @@ package body Sem_Elab is
          function Declaration_Placement_Of_Node
            (N : Node_Id) return Declaration_Placement_Kind
          is
-            Main_Unit_Id : constant Entity_Id := Cunit_Entity (Main_Unit);
+            Main_Unit_Id : constant Entity_Id := Main_Unit_Entity;
             N_Unit_Id    : constant Entity_Id := Find_Top_Unit (N);
 
          begin
@@ -12150,6 +12192,9 @@ package body Sem_Elab is
          Main_Cunit : constant Node_Id := Cunit (Main_Unit);
 
       begin
+         --  ??? Remove the following use of the debug flag when switching from
+         --  the old to the new elaboration-order mechanism.
+
          --  Nothing to do when switch -gnatd_G (encode invocation graph in ALI
          --  files) is not in effect.
 
@@ -12458,6 +12503,43 @@ package body Sem_Elab is
          end if;
       end Process_Invocation_Call;
 
+      --------------------------------------
+      -- Process_Invocation_Instantiation --
+      --------------------------------------
+
+      procedure Process_Invocation_Instantiation
+        (Inst     : Node_Id;
+         Inst_Rep : Scenario_Rep_Id;
+         In_State : Processing_In_State)
+      is
+         pragma Unreferenced (Inst);
+
+         Gen_Id : constant Entity_Id := Target (Inst_Rep);
+
+      begin
+         --  Nothing to do when the generic appears within an internal unit
+
+         if In_Internal_Unit (Gen_Id) then
+            return;
+         end if;
+
+         --  The generic being instantiated resides within an external unit
+         --
+         --      Main unit         External unit
+         --    +-----------+      +-------------+
+         --    |           |      |             |
+         --    |  Start ------------> Generic   |
+         --    |           |      |             |
+         --    +-----------+      +-------------+
+         --
+         --  Record the invocation path which originates from Start and reaches
+         --  the generic.
+
+         if not In_Extended_Main_Code_Unit (Gen_Id) then
+            Record_Invocation_Path (In_State);
+         end if;
+      end Process_Invocation_Instantiation;
+
       ---------------------------------
       -- Process_Invocation_Scenario --
       ---------------------------------
@@ -12503,6 +12585,14 @@ package body Sem_Elab is
                      In_State  => In_State);
                end if;
             end if;
+
+         --  Instantiation
+
+         elsif Is_Suitable_Instantiation (Scen) then
+            Process_Invocation_Instantiation
+              (Inst     => Scen,
+               Inst_Rep => Scenario_Representation_Of (Scen, In_State),
+               In_State => In_State);
          end if;
 
          --  Remove the current scenario from the stack of active scenarios
@@ -13589,6 +13679,18 @@ package body Sem_Elab is
       end if;
    end Kill_Elaboration_Scenario;
 
+   ----------------------
+   -- Main_Unit_Entity --
+   ----------------------
+
+   function Main_Unit_Entity return Entity_Id is
+   begin
+      --  Note that Cunit_Entity (Main_Unit) is not reliable in the presence of
+      --  generic bodies and may return an outdated entity.
+
+      return Defining_Entity (Unit (Cunit (Main_Unit)));
+   end Main_Unit_Entity;
+
    ----------------------
    -- Non_Private_View --
    ----------------------
@@ -15026,8 +15128,7 @@ package body Sem_Elab is
       --  emitted multiple times.
 
       procedure Check_SPARK_Model_In_Effect is
-         Spec_Id : constant Entity_Id :=
-                     Unique_Entity (Cunit_Entity (Main_Unit));
+         Spec_Id : constant Entity_Id := Unique_Entity (Main_Unit_Entity);
 
       begin
          --  Do not emit the warning multiple times as this creates useless
index dc62ec2051002823de07d018de38d636f24f8ca3..eefd225f5398324b22bef10e5f691c32b5a0f7fd 100644 (file)
@@ -353,6 +353,15 @@ package body Switch.B is
             Ptr := Ptr + 1;
             Usage_Requested := True;
 
+         --  ??? Enable the following code when switching from the old to the
+         --  new elaboration-order mechanism.
+
+         --  Processing for H switch
+
+         --  when 'H' =>
+         --     Ptr := Ptr + 1;
+         --     Legacy_Elaboration_Order := True;
+
          --  Processing for i switch
 
          when 'i' =>