Commit 16cc65b6 by Hristian Kirtchev Committed by Pierre-Marie de Rodat

[Ada] Elaboration order v4.0 activation

This patch enables the elaboration order v4.0 as the default elaboration
order in GNATbind. The previous v3.0 elaboration order is now referred
to as the "legacy elaboration order mechanism" and is available using
binder switch -H.

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

gcc/ada/

	* bindo.adb: Remove with and use clauses for Debug.  Add with
	and use clauses for Opt.
	(Find_Elaboration_Order): Enable the v4.0 elaboration order. The
	v3.0 mechanism is now available under binder switch -H.
	* bindusg.adb (Display): Enable switch -H.
	* debug.adb: Free compiler switch -gnatd_G.  Free binder switch
	-d_N.
	* sem_elab.adb: Update the section on switches to remove
	-gnatd_G.
	(Invocation_Graph_Recording_OK): The invocation graph is now
	unconditionally recorded in ALI files.
	* switch-b.adb (Scan_Binder_Switches): Scan switch -H.
	* doc/gnat_ugn/building_executable_programs_with_gnat.rst:
	Update the documentation on compiler switches related to
	elaboration.  Update the documentation on binder switches to
	include switch -H.
	* doc/gnat_ugn/elaboration_order_handling_in_gnat.rst: Update
	the documentation on elaboration order handling in GNAT.
	* gnat_ugn.texi: Regenerate.

From-SVN: r273280
parent fb95bfcc
2019-07-09 Hristian Kirtchev <kirtchev@adacore.com>
* bindo.adb: Remove with and use clauses for Debug. Add with
and use clauses for Opt.
(Find_Elaboration_Order): Enable the v4.0 elaboration order. The
v3.0 mechanism is now available under binder switch -H.
* bindusg.adb (Display): Enable switch -H.
* debug.adb: Free compiler switch -gnatd_G. Free binder switch
-d_N.
* sem_elab.adb: Update the section on switches to remove
-gnatd_G.
(Invocation_Graph_Recording_OK): The invocation graph is now
unconditionally recorded in ALI files.
* switch-b.adb (Scan_Binder_Switches): Scan switch -H.
* doc/gnat_ugn/building_executable_programs_with_gnat.rst:
Update the documentation on compiler switches related to
elaboration. Update the documentation on binder switches to
include switch -H.
* doc/gnat_ugn/elaboration_order_handling_in_gnat.rst: Update
the documentation on elaboration order handling in GNAT.
* gnat_ugn.texi: Regenerate.
2019-07-09 Eric Botcazou <ebotcazou@adacore.com> 2019-07-09 Eric Botcazou <ebotcazou@adacore.com>
* repinfo.adb (List_Entities): Disregard formals altogether. * repinfo.adb (List_Entities): Disregard formals altogether.
......
...@@ -24,7 +24,7 @@ ...@@ -24,7 +24,7 @@
------------------------------------------------------------------------------ ------------------------------------------------------------------------------
with Binde; with Binde;
with Debug; use Debug; with Opt; use Opt;
with Bindo.Elaborators; with Bindo.Elaborators;
use Bindo.Elaborators; use Bindo.Elaborators;
...@@ -426,9 +426,7 @@ package body Bindo is ...@@ -426,9 +426,7 @@ package body Bindo is
-- Units and routines of interest: -- Units and routines of interest:
-- Bindo.Elaborators -- Bindo.Elaborators
-- Elaborate_Library_Graph -- Elaborate_Library_Graph
-- Elaborate_Units_Common -- Elaborate_Units
-- Elaborate_Units_Dynamic
-- Elaborate_Units_Static
-- --
-- * Invalid invocation graph -- * Invalid invocation graph
-- --
...@@ -490,40 +488,19 @@ package body Bindo is ...@@ -490,40 +488,19 @@ package body Bindo is
Main_Lib_File : File_Name_Type) Main_Lib_File : File_Name_Type)
is is
begin begin
-- ??? 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 -- Use the library graph and heuristic-based elaboration order when
-- switch -H (legacy elaboration-order mode enabled). -- switch -H (legacy elaboration-order mode enabled).
-- if Legacy_Elaboration_Order then if Legacy_Elaboration_Order then
-- Binde.Find_Elab_Order (Order, Main_Lib_File); Binde.Find_Elab_Order (Order, Main_Lib_File);
-- Otherwise use the invocation and library-graph-based elaboration -- Otherwise use the invocation and library-graph-based elaboration
-- order. -- order.
-- else 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
Invocation_And_Library_Graph_Elaborators.Elaborate_Units Invocation_And_Library_Graph_Elaborators.Elaborate_Units
(Order => Order, (Order => Order,
Main_Lib_File => Main_Lib_File); Main_Lib_File => Main_Lib_File);
-- Otherwise use the library-graph and heuristic-based elaboration
-- order.
else
Binde.Find_Elab_Order (Order, Main_Lib_File);
end if; end if;
end Find_Elaboration_Order; end Find_Elaboration_Order;
......
...@@ -143,13 +143,10 @@ package body Bindusg is ...@@ -143,13 +143,10 @@ package body Bindusg is
Write_Line Write_Line
(" -h Output this usage (help) information"); (" -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 -- Line for -H switch
-- Write_Line Write_Line
-- (" -H Legacy elaboration-order model enabled"); (" -H Legacy elaboration order model enabled");
-- Lines for -I switch -- Lines for -I switch
......
...@@ -178,7 +178,7 @@ package body Debug is ...@@ -178,7 +178,7 @@ package body Debug is
-- d_D -- d_D
-- d_E -- d_E
-- d_F Encode full invocation paths in ALI files -- d_F Encode full invocation paths in ALI files
-- d_G Encode invocation graph in ALI files -- d_G
-- d_H -- d_H
-- d_I -- d_I
-- d_J -- d_J
...@@ -388,7 +388,7 @@ package body Debug is ...@@ -388,7 +388,7 @@ package body Debug is
-- d_K -- d_K
-- d_L Output library graph -- d_L Output library graph
-- d_M -- d_M
-- d_N New bindo order -- d_N
-- d_O -- d_O
-- d_P Output cycle paths -- d_P Output cycle paths
-- d_Q -- d_Q
...@@ -1001,9 +1001,6 @@ package body Debug is ...@@ -1001,9 +1001,6 @@ package body Debug is
-- an external target, offering additional information to GNATBIND for -- an external target, offering additional information to GNATBIND for
-- purposes of error diagnostics. -- purposes of error diagnostics.
-- d_G The compiler encodes the invocation graph of a unit in its ALI
-- file.
-- d_L Output trace information on elaboration checking. This debug switch -- d_L Output trace information on elaboration checking. This debug switch
-- causes output to be generated showing each call or instantiation as -- causes output to be generated showing each call or instantiation as
-- it is checked, and the progress of the recursive trace through -- it is checked, and the progress of the recursive trace through
...@@ -1164,8 +1161,6 @@ package body Debug is ...@@ -1164,8 +1161,6 @@ package body Debug is
-- d_L GNATBIND outputs the contents of the library graph in textual -- d_L GNATBIND outputs the contents of the library graph in textual
-- format to standard output. -- format to standard output.
-- d_N GNATBIND utilizes the elaboration order provided by bindo
-- d_P GNATBIND outputs the cycle paths to standard output -- d_P GNATBIND outputs the cycle paths to standard output
-- d_T GNATBIND outputs trace information of elaboration order and cycle -- d_T GNATBIND outputs trace information of elaboration order and cycle
......
...@@ -1836,7 +1836,8 @@ Alphabetical List of All Switches ...@@ -1836,7 +1836,8 @@ Alphabetical List of All Switches
.. index:: -gnatE (gcc) .. index:: -gnatE (gcc)
:switch:`-gnatE` :switch:`-gnatE`
Full dynamic elaboration checks. Dynamic elaboration checking mode enabled. For further details see
:ref:`Elaboration_Order_Handling_in_GNAT`.
.. index:: -gnatf (gcc) .. index:: -gnatf (gcc)
...@@ -1878,8 +1879,9 @@ Alphabetical List of All Switches ...@@ -1878,8 +1879,9 @@ Alphabetical List of All Switches
.. index:: -gnatH (gcc) .. index:: -gnatH (gcc)
:switch:`-gnatH` :switch:`-gnatH`
Legacy elaboration-checking mode enabled. When this switch is in effect, the Legacy elaboration-checking mode enabled. When this switch is in effect,
pre-18.x access-before-elaboration model becomes the de facto model. the pre-18.x access-before-elaboration model becomes the de facto model.
For further details see :ref:`Elaboration_Order_Handling_in_GNAT`.
.. index:: -gnati (gcc) .. index:: -gnati (gcc)
...@@ -1935,7 +1937,8 @@ Alphabetical List of All Switches ...@@ -1935,7 +1937,8 @@ Alphabetical List of All Switches
- Select statements - Select statements
- Synchronous task suspension - Synchronous task suspension
and does not emit compile-time diagnostics or run-time checks. and does not emit compile-time diagnostics or run-time checks. For further
details see :ref:`Elaboration_Order_Handling_in_GNAT`.
.. index:: -gnatk (gcc) .. index:: -gnatk (gcc)
...@@ -6368,7 +6371,9 @@ be presented in subsequent sections. ...@@ -6368,7 +6371,9 @@ be presented in subsequent sections.
.. index:: -f (gnatbind) .. index:: -f (gnatbind)
:switch:`-f{elab-order}` :switch:`-f{elab-order}`
Force elaboration order. Force elaboration order. For further details see :ref:`Elaboration_Control`
and :ref:`Elaboration_Order_Handling_in_GNAT`.
.. index:: -F (gnatbind) .. index:: -F (gnatbind)
...@@ -6388,15 +6393,22 @@ be presented in subsequent sections. ...@@ -6388,15 +6393,22 @@ be presented in subsequent sections.
Output usage (help) information. Output usage (help) information.
.. index:: -H32 (gnatbind) .. index:: -H (gnatbind)
:switch:`-H`
Legacy elaboration order model enabled. For further details see
:ref:`Elaboration_Order_Handling_in_GNAT`.
.. index:: -H32 (gnatbind)
:switch:`-H32` :switch:`-H32`
Use 32-bit allocations for ``__gnat_malloc`` (and thus for access types). Use 32-bit allocations for ``__gnat_malloc`` (and thus for access types).
For further details see :ref:`Dynamic_Allocation_Control`. For further details see :ref:`Dynamic_Allocation_Control`.
.. index:: -H64 (gnatbind) .. index:: -H64 (gnatbind)
.. index:: __gnat_malloc .. index:: __gnat_malloc
:switch:`-H64` :switch:`-H64`
Use 64-bit allocations for ``__gnat_malloc`` (and thus for access types). Use 64-bit allocations for ``__gnat_malloc`` (and thus for access types).
...@@ -6816,7 +6828,7 @@ Elaboration Control ...@@ -6816,7 +6828,7 @@ Elaboration Control
^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^
The following switches provide additional control over the elaboration The following switches provide additional control over the elaboration
order. For full details see :ref:`Elaboration_Order_Handling_in_GNAT`. order. For further details see :ref:`Elaboration_Order_Handling_in_GNAT`.
.. index:: -f (gnatbind) .. index:: -f (gnatbind)
...@@ -6860,28 +6872,32 @@ order. For full details see :ref:`Elaboration_Order_Handling_in_GNAT`. ...@@ -6860,28 +6872,32 @@ order. For full details see :ref:`Elaboration_Order_Handling_in_GNAT`.
ignored. ignored.
.. index:: -p (gnatbind) .. index:: -p (gnatbind)
:switch:`-p` :switch:`-p`
Normally the binder attempts to choose an elaboration order that is Pessimistic elaboration order
likely to minimize the likelihood of an elaboration order error resulting
in raising a ``Program_Error`` exception. This switch reverses the This switch is only applicable to the pre-20.x legacy elaboration models.
action of the binder, and requests that it deliberately choose an order The post-20.x elaboration model uses a more informed approach of ordering
that is likely to maximize the likelihood of an elaboration error. the units.
This is useful in ensuring portability and avoiding dependence on
accidental fortuitous elaboration ordering. Normally the binder attempts to choose an elaboration order that is likely to
minimize the likelihood of an elaboration order error resulting in raising a
Normally it only makes sense to use the :switch:`-p` ``Program_Error`` exception. This switch reverses the action of the binder,
switch if dynamic and requests that it deliberately choose an order that is likely to maximize
the likelihood of an elaboration error. This is useful in ensuring
portability and avoiding dependence on accidental fortuitous elaboration
ordering.
Normally it only makes sense to use the :switch:`-p` switch if dynamic
elaboration checking is used (:switch:`-gnatE` switch used for compilation). elaboration checking is used (:switch:`-gnatE` switch used for compilation).
This is because in the default static elaboration mode, all necessary This is because in the default static elaboration mode, all necessary
``Elaborate`` and ``Elaborate_All`` pragmas are implicitly inserted. ``Elaborate`` and ``Elaborate_All`` pragmas are implicitly inserted.
These implicit pragmas are still respected by the binder in These implicit pragmas are still respected by the binder in :switch:`-p`
:switch:`-p` mode, so a mode, so a safe elaboration order is assured.
safe elaboration order is assured.
Note that :switch:`-p` is not intended for Note that :switch:`-p` is not intended for production use; it is more for
production use; it is more for debugging/experimental use. debugging/experimental use.
.. _Output_Control: .. _Output_Control:
......
...@@ -50,9 +50,14 @@ Elaboration code is executed as follows: ...@@ -50,9 +50,14 @@ Elaboration code is executed as follows:
In addition to the Ada terminology, this appendix defines the following terms: In addition to the Ada terminology, this appendix defines the following terms:
* *Invocation*
The act of calling a subprogram, instantiating a generic, or activating a
task.
* *Scenario* * *Scenario*
A construct that is elaborated or executed by elaboration code is referred to A construct that is elaborated or invoked by elaboration code is referred to
as an *elaboration scenario* or simply a **scenario**. GNAT recognizes the as an *elaboration scenario* or simply a **scenario**. GNAT recognizes the
following scenarios: following scenarios:
...@@ -102,7 +107,7 @@ Elaboration code may appear in two distinct contexts: ...@@ -102,7 +107,7 @@ Elaboration code may appear in two distinct contexts:
In the example above, the call to ``Server.Func`` is an elaboration scenario In the example above, the call to ``Server.Func`` is an elaboration scenario
because it appears at the library level of package ``Client``. Note that the because it appears at the library level of package ``Client``. Note that the
declaration of package ``Nested`` is ignored according to the definition declaration of package ``Nested`` is ignored according to the definition
given above. As a result, the call to ``Server.Func`` will be executed when given above. As a result, the call to ``Server.Func`` will be invoked when
the spec of unit ``Client`` is elaborated. the spec of unit ``Client`` is elaborated.
* *Package body statements* * *Package body statements*
...@@ -124,7 +129,7 @@ Elaboration code may appear in two distinct contexts: ...@@ -124,7 +129,7 @@ Elaboration code may appear in two distinct contexts:
In the example above, the call to ``Proc`` is an elaboration scenario because In the example above, the call to ``Proc`` is an elaboration scenario because
it appears within the statement sequence of package body ``Client``. As a it appears within the statement sequence of package body ``Client``. As a
result, the call to ``Proc`` will be executed when the body of ``Client`` is result, the call to ``Proc`` will be invoked when the body of ``Client`` is
elaborated. elaborated.
.. _Elaboration_Order: .. _Elaboration_Order:
...@@ -137,19 +142,19 @@ executed is referred to as **elaboration order**. ...@@ -137,19 +142,19 @@ executed is referred to as **elaboration order**.
Within a single unit, elaboration code is executed in sequential order. Within a single unit, elaboration code is executed in sequential order.
:: ::
package body Client is package body Client is
Result : ... := Server.Func; Result : ... := Server.Func;
procedure Proc is procedure Proc is
package Inst is new Server.Gen; package Inst is new Server.Gen;
begin begin
Inst.Eval (Result); Inst.Eval (Result);
end Proc; end Proc;
begin begin
Proc; Proc;
end Client; end Client;
In the example above, the elaboration order within package body ``Client`` is In the example above, the elaboration order within package body ``Client`` is
as follows: as follows:
...@@ -173,52 +178,56 @@ factors: ...@@ -173,52 +178,56 @@ factors:
* |withed| units * |withed| units
* parent units
* purity of units * purity of units
* preelaborability of units * preelaborability of units
* presence of elaboration control pragmas * presence of elaboration control pragmas
* invocations performed in elaboration code
A program may have several elaboration orders depending on its structure. A program may have several elaboration orders depending on its structure.
:: ::
package Server is package Server is
function Func (Index : Integer) return Integer; function Func (Index : Integer) return Integer;
end Server; end Server;
:: ::
package body Server is package body Server is
Results : array (1 .. 5) of Integer := (1, 2, 3, 4, 5); Results : array (1 .. 5) of Integer := (1, 2, 3, 4, 5);
function Func (Index : Integer) return Integer is function Func (Index : Integer) return Integer is
begin begin
return Results (Index); return Results (Index);
end Func; end Func;
end Server; end Server;
:: ::
with Server; with Server;
package Client is package Client is
Val : constant Integer := Server.Func (3); Val : constant Integer := Server.Func (3);
end Client; end Client;
:: ::
with Client; with Client;
procedure Main is begin null; end Main; procedure Main is begin null; end Main;
The following elaboration order exhibits a fundamental problem referred to as The following elaboration order exhibits a fundamental problem referred to as
*access-before-elaboration* or simply **ABE**. *access-before-elaboration* or simply **ABE**.
:: ::
spec of Server spec of Server
spec of Client spec of Client
body of Server body of Server
body of Main body of Main
The elaboration of ``Server``'s spec materializes function ``Func``, making it The elaboration of ``Server``'s spec materializes function ``Func``, making it
callable. The elaboration of ``Client``'s spec elaborates the declaration of callable. The elaboration of ``Client``'s spec elaborates the declaration of
...@@ -236,19 +245,20 @@ vein as index or null exclusion checks. A failed ABE check raises exception ...@@ -236,19 +245,20 @@ vein as index or null exclusion checks. A failed ABE check raises exception
The following elaboration order avoids the ABE problem and the program can be The following elaboration order avoids the ABE problem and the program can be
successfully elaborated. successfully elaborated.
:: ::
spec of Server spec of Server
body of Server body of Server
spec of Client spec of Client
body of Main body of Main
Ada states that a total elaboration order must exist, but it does not define Ada states that a total elaboration order must exist, but it does not define
what this order is. A compiler is thus tasked with choosing a suitable what this order is. A compiler is thus tasked with choosing a suitable
elaboration order which satisfies the dependencies imposed by |with| clauses, elaboration order which satisfies the dependencies imposed by |with| clauses,
unit categorization, and elaboration control pragmas. Ideally an order which unit categorization, elaboration control pragmas, and invocations performed in
avoids ABE problems should be chosen, however a compiler may not always find elaboration code. Ideally an order that avoids ABE problems should be chosen,
such an order due to complications with respect to control and data flow. however a compiler may not always find such an order due to complications with
respect to control and data flow.
.. _Checking_the_Elaboration_Order: .. _Checking_the_Elaboration_Order:
...@@ -268,7 +278,7 @@ provides three lines of defense: ...@@ -268,7 +278,7 @@ provides three lines of defense:
* *Dynamic semantics* * *Dynamic semantics*
Dynamic checks are performed at run time, to ensure that a target is Dynamic checks are performed at run time, to ensure that a target is
elaborated prior to a scenario that executes it, thus avoiding ABE problems. elaborated prior to a scenario that invokes it, thus avoiding ABE problems.
A failed run-time check raises exception ``Program_Error``. The following A failed run-time check raises exception ``Program_Error``. The following
restrictions apply: restrictions apply:
...@@ -290,8 +300,7 @@ provides three lines of defense: ...@@ -290,8 +300,7 @@ provides three lines of defense:
The restrictions above can be summarized by the following rule: The restrictions above can be summarized by the following rule:
*If a target has a body, then this body must be elaborated prior to the *If a target has a body, then this body must be elaborated prior to the
execution of the scenario that invokes, instantiates, or activates the scenario that invokes the target.*
target.*
* *Elaboration control* * *Elaboration control*
...@@ -346,7 +355,7 @@ the desired elaboration order and avoiding ABE problems altogether. ...@@ -346,7 +355,7 @@ the desired elaboration order and avoiding ABE problems altogether.
Pragma ``Elaborate_Body`` requires that the body of a unit is elaborated Pragma ``Elaborate_Body`` requires that the body of a unit is elaborated
immediately after its spec. This restriction guarantees that no client immediately after its spec. This restriction guarantees that no client
scenario can execute a server target before the target body has been scenario can invoke a server target before the target body has been
elaborated because the spec and body are effectively "glued" together. elaborated because the spec and body are effectively "glued" together.
:: ::
...@@ -601,24 +610,53 @@ elaboration order and to diagnose elaboration problems. ...@@ -601,24 +610,53 @@ elaboration order and to diagnose elaboration problems.
* *Dynamic elaboration model* * *Dynamic elaboration model*
This is the most permissive of the three elaboration models. When the This is the most permissive of the three elaboration models and emulates the
dynamic model is in effect, GNAT assumes that all code within all units in behavior specified by the Ada Reference Manual. When the dynamic model is in
a partition is elaboration code. GNAT performs very few diagnostics and effect, GNAT makes the following assumptions:
generates run-time checks to verify the elaboration order of a program. This
behavior is identical to that specified by the Ada Reference Manual. The - All code within all units in a partition is considered to be elaboration
dynamic model is enabled with compiler switch :switch:`-gnatE`. code.
- Some of the invocations in elaboration code may not take place at runtime
due to conditional execution.
GNAT performs extensive diagnostics on a unit-by-unit basis for all scenarios
that invoke internal targets. In addition, GNAT generates run-time checks for
all external targets and for all scenarios that may exhibit ABE problems.
The elaboration order is obtained by honoring all |with| clauses, purity and
preelaborability of units, and elaboration control pragmas. The dynamic model
attempts to take all invocations in elaboration code into account. If an
invocation leads to a circularity, GNAT ignores the invocation based on the
assumptions stated above. An order obtained using the dynamic model may fail
an ABE check at runtime when GNAT ignored an invocation.
The dynamic model is enabled with compiler switch :switch:`-gnatE`.
.. index:: Static elaboration model .. index:: Static elaboration model
* *Static elaboration model* * *Static elaboration model*
This is the middle ground of the three models. When the static model is in This is the middle ground of the three models. When the static model is in
effect, GNAT performs extensive diagnostics on a unit-by-unit basis for all effect, GNAT makes the following assumptions:
scenarios that elaborate or execute internal targets. GNAT also generates
run-time checks for all external targets and for all scenarios that may - Only code at the library level and in package body statements within all
exhibit ABE problems. Finally, GNAT installs implicit ``Elaborate`` and units in a partition is considered to be elaboration code.
``Elaborate_All`` pragmas for server units based on the dependencies of
client units. The static model is the default model in GNAT. - All invocations in elaboration will take place at runtime, regardless of
conditional execution.
GNAT performs extensive diagnostics on a unit-by-unit basis for all scenarios
that invoke internal targets. In addition, GNAT generates run-time checks for
all external targets and for all scenarios that may exhibit ABE problems.
The elaboration order is obtained by honoring all |with| clauses, purity and
preelaborability of units, presence of elaboration control pragmas, and all
invocations in elaboration code. An order obtained using the static model is
guaranteed to be ABE problem-free, excluding dispatching calls and
access-to-subprogram types.
The static model is the default model in GNAT.
.. index:: SPARK elaboration model .. index:: SPARK elaboration model
...@@ -627,17 +665,23 @@ elaboration order and to diagnose elaboration problems. ...@@ -627,17 +665,23 @@ elaboration order and to diagnose elaboration problems.
This is the most conservative of the three models and enforces the SPARK This is the most conservative of the three models and enforces the SPARK
rules of elaboration as defined in the SPARK Reference Manual, section 7.7. rules of elaboration as defined in the SPARK Reference Manual, section 7.7.
The SPARK model is in effect only when a scenario and a target reside in a The SPARK model is in effect only when a scenario and a target reside in a
region subject to SPARK_Mode On, otherwise the dynamic or static model is in region subject to ``SPARK_Mode On``, otherwise the dynamic or static model
effect. is in effect.
.. index:: Legacy elaboration model The SPARK model is enabled with compiler switch :switch:`-gnatd.v`.
* *Legacy elaboration model* .. index:: Legacy elaboration models
* *Legacy elaboration models*
In addition to the three elaboration models outlined above, GNAT provides the In addition to the three elaboration models outlined above, GNAT provides the
elaboration model of pre-18.x versions referred to as `legacy elaboration following legacy models:
model`. The legacy elaboration model is enabled with compiler switch
:switch:`-gnatH`. - `Legacy elaboration-checking model` available in pre-18.x versions of GNAT.
This model is enabled with compiler switch :switch:`-gnatH`.
- `Legacy elaboration-order model` available in pre-20.x versions of GNAT.
This model is enabled with binder switch :switch:`-H`.
.. index:: Relaxed elaboration mode .. index:: Relaxed elaboration mode
...@@ -645,812 +689,430 @@ The dynamic, legacy, and static models can be relaxed using compiler switch ...@@ -645,812 +689,430 @@ The dynamic, legacy, and static models can be relaxed using compiler switch
:switch:`-gnatJ`, making them more permissive. Note that in this mode, GNAT :switch:`-gnatJ`, making them more permissive. Note that in this mode, GNAT
may not diagnose certain elaboration issues or install run-time checks. may not diagnose certain elaboration issues or install run-time checks.
.. _Common_Elaboration_Model_Traits": .. _Mixing_Elaboration_Models:
Common Elaboration-model Traits Mixing Elaboration Models
=============================== =========================
All three GNAT models are able to detect elaboration problems related to It is possible to mix units compiled with a different elaboration model,
dispatching calls and a particular kind of ABE referred to as *guaranteed ABE*. however the following rules must be observed:
* *Dispatching calls* * A client unit compiled with the dynamic model can only |with| a server unit
that meets at least one of the following criteria:
GNAT installs run-time checks for each primitive subprogram of each tagged - The server unit is compiled with the dynamic model.
type defined in a partition on the assumption that a dispatching call
invoked at elaboration time will execute one of these primitives. As a
result, a dispatching call that executes a primitive whose body has not
been elaborated yet will raise exception ``Program_Error`` at run time. The
checks can be suppressed using pragma ``Suppress (Elaboration_Check)``.
* *Guaranteed ABE* - The server unit is a GNAT implementation unit from the ``Ada``, ``GNAT``,
``Interfaces``, or ``System`` hierarchies.
A guaranteed ABE arises when the body of a target is not elaborated early - The server unit has pragma ``Pure`` or ``Preelaborate``.
enough, and causes all scenarios that directly execute the target to fail.
:: - The client unit has an explicit ``Elaborate_All`` pragma for the server
unit.
package body Guaranteed_ABE is These rules ensure that elaboration checks are not omitted. If the rules are
function ABE return Integer; violated, the binder emits a warning:
Val : constant Integer := ABE; ::
function ABE return Integer is warning: "x.ads" has dynamic elaboration checks and with's
begin warning: "y.ads" which has static elaboration checks
...
end ABE;
end Guaranteed_ABE;
In the example above, the elaboration of ``Guaranteed_ABE``'s body elaborates The warnings can be suppressed by binder switch :switch:`-ws`.
the declaration of ``Val``. This invokes function ``ABE``, however the body
of ``ABE`` has not been elaborated yet. GNAT emits similar diagnostics in all
three models:
:: .. _ABE_Diagnostics:
1. package body Guaranteed_ABE is ABE Diagnostics
2. function ABE return Integer; ===============
3.
4. Val : constant Integer := ABE;
|
>>> warning: cannot call "ABE" before body seen
>>> warning: Program_Error will be raised at run time
5. GNAT performs extensive diagnostics on a unit-by-unit basis for all scenarios
6. function ABE return Integer is that invoke internal targets, regardless of whether the dynamic, SPARK, or
7. begin static model is in effect.
8. ...
9. end ABE;
10. end Guaranteed_ABE;
Note that GNAT emits warnings rather than hard errors whenever it encounters an Note that GNAT emits warnings rather than hard errors whenever it encounters an
elaboration problem. This is because the elaboration model in effect may be too elaboration problem. This is because the elaboration model in effect may be too
conservative, or a particular scenario may not be elaborated or executed due to conservative, or a particular scenario may not be invoked due conditional
data and control flow. The warnings can be suppressed selectively with ``pragma execution. The warnings can be suppressed selectively with ``pragma Warnings
Warnigns (Off)`` or globally with compiler switch :switch:`-gnatwL`. (Off)`` or globally with compiler switch :switch:`-gnatwL`.
.. _Dynamic_Elaboration_Model_in_GNAT:
Dynamic Elaboration Model in GNAT
=================================
The dynamic model assumes that all code within all units in a partition is
elaboration code. As a result, run-time checks are installed for each scenario
regardless of whether the target is internal or external. The checks can be
suppressed using pragma ``Suppress (Elaboration_Check)``. This behavior is
identical to that specified by the Ada Reference Manual. The following example
showcases run-time checks installed by GNAT to verify the elaboration state of
package ``Dynamic_Model``.
::
with Server;
package body Dynamic_Model is
procedure API is
begin
...
end API;
<check that the body of Server.Gen is elaborated>
package Inst is new Server.Gen;
T : Server.Task_Type; A *guaranteed ABE* arises when the body of a target is not elaborated early
enough, and causes *all* scenarios that directly invoke the target to fail.
begin ::
<check that the body of Server.Task_Type is elaborated>
<check that the body of Server.Proc is elaborated>
Server.Proc;
end Dynamic_Model;
The checks verify that the body of a target has been successfully elaborated
before a scenario activates, calls, or instantiates a target.
Note that no scenario within package ``Dynamic_Model`` calls procedure ``API``.
In fact, procedure ``API`` may not be invoked by elaboration code within the
partition, however the dynamic model assumes that this can happen.
The dynamic model emits very few diagnostics, but can make suggestions on package body Guaranteed_ABE is
missing ``Elaborate`` and ``Elaborate_All`` pragmas for library-level function ABE return Integer;
scenarios. This information is available when compiler switch :switch:`-gnatel`
is in effect.
:: Val : constant Integer := ABE;
1. with Server; function ABE return Integer is
2. package body Dynamic_Model is begin
3. Val : constant Integer := Server.Func; ...
| end ABE;
>>> info: call to "Func" during elaboration end Guaranteed_ABE;
>>> info: missing pragma "Elaborate_All" for unit "Server"
4. end Dynamic_Model; In the example above, the elaboration of ``Guaranteed_ABE``'s body elaborates
the declaration of ``Val``. This invokes function ``ABE``, however the body of
``ABE`` has not been elaborated yet. GNAT emits the following diagnostic:
.. _Static_Elaboration_Model_in_GNAT: ::
Static Elaboration Model in GNAT 4. Val : constant Integer := ABE;
================================ |
>>> warning: cannot call "ABE" before body seen
>>> warning: Program_Error will be raised at run time
In contrast to the dynamic model, the static model is more precise in its A *conditional ABE* arises when the body of a target is not elaborated early
analysis of elaboration code. The model makes a clear distinction between enough, and causes *some* scenarios that directly invoke the target to fail.
internal and external targets, and resorts to different diagnostics and
run-time checks based on the nature of the target.
* *Internal targets* ::
The static model performs extensive diagnostics on scenarios which elaborate 1. package body Conditional_ABE is
or execute internal targets. The warnings resulting from these diagnostics 2. procedure Force_Body is null;
are enabled by default, but can be suppressed selectively with ``pragma 3.
Warnings (Off)`` or globally with compiler switch :switch:`-gnatwL`. 4. generic
5. with function Func return Integer;
6. package Gen is
7. Val : constant Integer := Func;
8. end Gen;
9.
10. function ABE return Integer;
11.
12. function Cause_ABE return Boolean is
13. package Inst is new Gen (ABE);
14. begin
15. ...
16. end Cause_ABE;
17.
18. Val : constant Boolean := Cause_ABE;
19.
20. function ABE return Integer is
21. begin
22. ...
23. end ABE;
24.
25. Safe : constant Boolean := Cause_ABE;
26. end Conditional_ABE;
In the example above, the elaboration of package body ``Conditional_ABE``
elaborates the declaration of ``Val``. This invokes function ``Cause_ABE``,
which instantiates generic unit ``Gen`` as ``Inst``. The elaboration of
``Inst`` invokes function ``ABE``, however the body of ``ABE`` has not been
elaborated yet. GNAT emits the following diagnostic:
:: ::
1. package body Static_Model is 13. package Inst is new Gen (ABE);
2. generic
3. with function Func return Integer;
4. package Gen is
5. Val : constant Integer := Func;
6. end Gen;
7.
8. function ABE return Integer;
9.
10. function Cause_ABE return Boolean is
11. package Inst is new Gen (ABE);
| |
>>> warning: in instantiation at line 5 >>> warning: in instantiation at line 7
>>> warning: cannot call "ABE" before body seen >>> warning: cannot call "ABE" before body seen
>>> warning: Program_Error may be raised at run time >>> warning: Program_Error may be raised at run time
>>> warning: body of unit "Static_Model" elaborated >>> warning: body of unit "Conditional_ABE" elaborated
>>> warning: function "Cause_ABE" called at line 16 >>> warning: function "Cause_ABE" called at line 18
>>> warning: function "ABE" called at line 5, instance at line 11 >>> warning: function "ABE" called at line 7, instance at line 13
12. begin
13. ...
14. end Cause_ABE;
15.
16. Val : constant Boolean := Cause_ABE;
17.
18. function ABE return Integer is
19. begin
20. ...
21. end ABE;
22. end Static_Model;
The example above illustrates an ABE problem within package ``Static_Model``,
which is hidden by several layers of indirection. The elaboration of package
body ``Static_Model`` elaborates the declaration of ``Val``. This invokes
function ``Cause_ABE``, which instantiates generic unit ``Gen`` as ``Inst``.
The elaboration of ``Inst`` invokes function ``ABE``, however the body of
``ABE`` has not been elaborated yet.
* *External targets*
The static model installs run-time checks to verify the elaboration status
of server targets only when the scenario that elaborates or executes that
target is part of the elaboration code of the client unit. The checks can be
suppressed using pragma ``Suppress (Elaboration_Check)``.
:: Note that the same ABE problem does not occur with the elaboration of
declaration ``Safe`` because the body of function ``ABE`` has already been
elaborated at that point.
with Server; .. _SPARK_Diagnostics:
package body Static_Model is
generic
with function Func return Integer;
package Gen is
Val : constant Integer := Func;
end Gen;
function Call_Func return Boolean is
<check that the body of Server.Func is elaborated>
package Inst is new Gen (Server.Func);
begin
...
end Call_Func;
Val : constant Boolean := Call_Func;
end Static_Model;
In the example above, the elaboration of package body ``Static_Model`` SPARK Diagnostics
elaborates the declaration of ``Val``. This invokes function ``Call_Func``, =================
which instantiates generic unit ``Gen`` as ``Inst``. The elaboration of
``Inst`` invokes function ``Server.Func``. Since ``Server.Func`` is an
external target, GNAT installs a run-time check to verify that its body has
been elaborated.
In addition to checks, the static model installs implicit ``Elaborate`` and GNAT enforces the SPARK rules of elaboration as defined in the SPARK Reference
``Elaborate_All`` pragmas to guarantee safe elaboration use of server units. Manual section 7.7 when compiler switch :switch:`-gnatd.v` is in effect. Note
This information is available when compiler switch :switch:`-gnatel` is in that GNAT emits hard errors whenever it encounters a violation of the SPARK
effect. rules.
:: ::
1. with Server; 1. with Server;
2. package body Static_Model is 2. package body SPARK_Diagnostics with SPARK_Mode is
3. generic 3. Val : constant Integer := Server.Func;
4. with function Func return Integer; |
5. package Gen is >>> call to "Func" during elaboration in SPARK
6. Val : constant Integer := Func; >>> unit "SPARK_Diagnostics" requires pragma "Elaborate_All" for "Server"
7. end Gen; >>> body of unit "SPARK_Model" elaborated
8. >>> function "Func" called at line 3
9. function Call_Func return Boolean is
10. package Inst is new Gen (Server.Func);
|
>>> info: instantiation of "Gen" during elaboration
>>> info: in instantiation at line 6
>>> info: call to "Func" during elaboration
>>> info: in instantiation at line 6
>>> info: implicit pragma "Elaborate_All" generated for unit "Server"
>>> info: body of unit "Static_Model" elaborated
>>> info: function "Call_Func" called at line 15
>>> info: function "Func" called at line 6, instance at line 10
11. begin
12. ...
13. end Call_Func;
14.
15. Val : constant Boolean := Call_Func;
|
>>> info: call to "Call_Func" during elaboration
16. end Static_Model;
In the example above, the elaboration of package body ``Static_Model``
elaborates the declaration of ``Val``. This invokes function ``Call_Func``,
which instantiates generic unit ``Gen`` as ``Inst``. The elaboration of
``Inst`` invokes function ``Server.Func``. Since ``Server.Func`` is an
external target, GNAT installs an implicit ``Elaborate_All`` pragma for unit
``Server``. The pragma guarantees that both the spec and body of ``Server``,
along with any additional dependencies that ``Server`` may require, are
elaborated prior to the body of ``Static_Model``.
.. _SPARK_Elaboration_Model_in_GNAT:
SPARK Elaboration Model in GNAT
===============================
The SPARK model is identical to the static model in its handling of internal
targets. The SPARK model, however, requires explicit ``Elaborate`` or
``Elaborate_All`` pragmas to be present in the program when a target is
external, and compiler switch :switch:`-gnatd.v` is in effect.
::
1. with Server;
2. package body SPARK_Model with SPARK_Mode is
3. Val : constant Integer := Server.Func;
|
>>> call to "Func" during elaboration in SPARK
>>> unit "SPARK_Model" requires pragma "Elaborate_All" for "Server"
>>> body of unit "SPARK_Model" elaborated
>>> function "Func" called at line 3
4. end SPARK_Model;
Legacy Elaboration Model in GNAT
================================
The legacy elaboration model is provided for compatibility with code bases
developed with pre-18.x versions of GNAT. It is similar in functionality to
the dynamic and static models of post-18.x version of GNAT, but may differ
in terms of diagnostics and run-time checks. The legacy elaboration model is
enabled with compiler switch :switch:`-gnatH`.
.. _Mixing_Elaboration_Models: 4. end SPARK_Diagnostics;
Mixing Elaboration Models .. _Elaboration_Circularities:
=========================
It is possible to mix units compiled with a different elaboration model, Elaboration Circularities
however the following rules must be observed: =========================
* A client unit compiled with the dynamic model can only |with| a server unit An **elaboration circularity** occurs whenever the elaboration of a set of
that meets at least one of the following criteria: units enters a deadlocked state, where each unit is waiting for another unit
to be elaborated. This situation may be the result of improper use of |with|
clauses, elaboration control pragmas, or invocations in elaboration code.
- The server unit is compiled with the dynamic model. The following example showcases an elaboration circularity.
- The server unit is a GNAT implementation unit from the Ada, GNAT, ::
Interfaces, or System hierarchies.
- The server unit has pragma ``Pure`` or ``Preelaborate``. with B; pragma Elaborate (B);
package A is
end A;
- The client unit has an explicit ``Elaborate_All`` pragma for the server ::
unit.
These rules ensure that elaboration checks are not omitted. If the rules are package B is
violated, the binder emits a warning: procedure Force_Body;
end B;
:: ::
warning: "x.ads" has dynamic elaboration checks and with's with C;
warning: "y.ads" which has static elaboration checks package body B is
procedure Force_Body is null;
The warnings can be suppressed by binder switch :switch:`-ws`. Elab : constant Integer := C.Func;
end B;
.. _Elaboration_Circularities: ::
Elaboration Circularities package C is
========================= function Func return Integer;
end C;
If the binder cannot find an acceptable elaboration order, it outputs detailed ::
diagnostics describing an **elaboration circularity**.
:: with A;
package body C is
function Func return Integer is
begin
...
end Func;
end C;
package Server is The binder emits the following diagnostic:
function Func return Integer;
end Server;
:: ::
with Client; error: Elaboration circularity detected
package body Server is info:
function Func return Integer is info: Reason:
begin info:
... info: unit "a (spec)" depends on its own elaboration
end Func; info:
end Server; info: Circularity:
info:
info: unit "a (spec)" has with clause and pragma Elaborate for unit "b (spec)"
info: unit "b (body)" is in the closure of pragma Elaborate
info: unit "b (body)" invokes a construct of unit "c (body)" at elaboration time
info: unit "c (body)" has with clause for unit "a (spec)"
info:
info: Suggestions:
info:
info: remove pragma Elaborate for unit "b (body)" in unit "a (spec)"
info: use the dynamic elaboration model (compiler switch -gnatE)
:: The diagnostic consist of the following sections:
with Server; * Reason
package Client is
Val : constant Integer := Server.Func;
end Client;
:: This section provides a short explanation describing why the set of units
could not be ordered.
with Client; * Circularity
procedure Main is begin null; end Main;
:: This section enumerates the units comprising the deadlocked set, along with
their interdependencies.
error: elaboration circularity detected * Suggestions
info: "server (body)" must be elaborated before "client (spec)"
info: reason: implicit Elaborate_All in unit "client (spec)"
info: recompile "client (spec)" with -gnatel for full details
info: "server (body)"
info: must be elaborated along with its spec:
info: "server (spec)"
info: which is withed by:
info: "client (spec)"
info: "client (spec)" must be elaborated before "server (body)"
info: reason: with clause
In the example above, ``Client`` must be elaborated prior to ``Main`` by virtue This section enumerates various tactics for eliminating the circularity.
of a |with| clause. The elaboration of ``Client`` invokes ``Server.Func``, and
static model generates an implicit ``Elaborate_All`` pragma for ``Server``. The
pragma implies that both the spec and body of ``Server``, along with any units
they |with|, must be elaborated prior to ``Client``. However, ``Server``'s body
|withs| ``Client``, implying that ``Client`` must be elaborated prior to
``Server``. The end result is that ``Client`` must be elaborated prior to
``Client``, and this leads to a circularity.
.. _Resolving_Elaboration_Circularities: .. _Resolving_Elaboration_Circularities:
Resolving Elaboration Circularities Resolving Elaboration Circularities
=================================== ===================================
When faced with an elaboration circularity, a programmer has several options The most desirable option from the point of view of long-term maintenance is to
available. rearrange the program so that the elaboration problems are avoided. One useful
technique is to place the elaboration code into separate child packages.
* *Fix the program* Another is to move some of the initialization code to explicitly invoked
subprograms, where the program controls the order of initialization explicitly.
The most desirable option from the point of view of long-term maintenance Although this is the most desirable option, it may be impractical and involve
is to rearrange the program so that the elaboration problems are avoided. too much modification, especially in the case of complex legacy code.
One useful technique is to place the elaboration code into separate child
packages. Another is to move some of the initialization code to explicitly
invoked subprograms, where the program controls the order of initialization
explicitly. Although this is the most desirable option, it may be impractical
and involve too much modification, especially in the case of complex legacy
code.
* *Switch to more permissive elaboration model*
If the compilation was performed using the static model, enable the dynamic
model with compiler switch :switch:`-gnatE`. GNAT will no longer generate
implicit ``Elaborate`` and ``Elaborate_All`` pragmas, resulting in a behavior
identical to that specified by the Ada Reference Manual. The binder will
generate an executable program that may or may not raise ``Program_Error``,
and it is the programmer's responsibility to ensure that it does not raise
``Program_Error``.
If the compilation was performed using a post-18.x version of GNAT, consider When faced with an elaboration circularity, the programmer should also consider
using the legacy elaboration model, in the following order: the tactics given in the suggestions section of the circularity diagnostic.
Depending on the units involved in the circularity, their |with| clauses,
purity, preelaborability, presence of elaboration control pragmas and
invocations at elaboration time, the binder may suggest one or more of the
following tactics to eliminate the circularity:
- Use the relaxed static elaboration model, with compiler switch * Pragma Elaborate elimination
:switch:`-gnatJ`.
- Use the relaxed dynamic elaboration model, with compiler switches ::
:switch:`-gnatE` :switch:`-gnatJ`.
- Use the legacy static elaboration model, with compiler switch
:switch:`-gnatH`.
- Use the legacy dynamic elaboration model, with compiler switches remove pragma Elaborate for unit "..." in unit "..."
:switch:`-gnatE` :switch:`-gnatH`.
* *Suppress all elaboration checks* This tactic is suggested when the binder has determine that pragma
``Elaborate``
The drawback of run-time checks is that they generate overhead at run time, - Prevents a set of units from being elaborated.
both in space and time. If the programmer is absolutely sure that a program
will not raise an elaboration-related ``Program_Error``, then using the
pragma ``Suppress (Elaboration_Check)`` globally (as a configuration pragma)
will eliminate all run-time checks.
* *Suppress elaboration checks selectively* - The removal of the pragma will not eliminate the semantic effects of the
pragma. In other words, the argument of the pragma will still be elaborated
prior to the unit containing the pragma.
If a scenario cannot possibly lead to an elaboration ``Program_Error``, - The removal of the pragma will enable the successful ordering of the units.
and the binder nevertheless complains about implicit ``Elaborate`` and
``Elaborate_All`` pragmas that lead to elaboration circularities, it
is possible to suppress the generation of implicit ``Elaborate`` and
``Elaborate_All`` pragmas, as well as run-time checks. Clearly this can
be unsafe, and it is the responsibility of the programmer to make sure
that the resulting program has no elaboration anomalies. Pragma
``Suppress (Elaboration_Check)`` can be used with different levels of
granularity to achieve these effects.
- *Target suppression* The programmer should remove the pragma as advised, and rebuild the program.
When the pragma is placed in a declarative part, without a second argument * Pragma Elaborate_All elimination
naming an entity, it will suppress implicit ``Elaborate`` and
``Elaborate_All`` pragma generation, as well as run-time checks, on all
targets within the region.
:: ::
package Range_Suppress is remove pragma Elaborate_All for unit "..." in unit "..."
pragma Suppress (Elaboration_Check);
function Func return Integer; This tactic is suggested when the binder has determined that pragma
``Elaborate_All``
generic - Prevents a set of units from being elaborated.
procedure Gen;
pragma Unsuppress (Elaboration_Check); - The removal of the pragma will not eliminate the semantic effects of the
pragma. In other words, the argument of the pragma along with its |with|
closure will still be elaborated prior to the unit containing the pragma.
task type Tsk; - The removal of the pragma will enable the successful ordering of the units.
end Range_Suppress;
In the example above, a pair of Suppress/Unsuppress pragmas define a region The programmer should remove the pragma as advised, and rebuild the program.
of suppression within package ``Range_Suppress``. As a result, no implicit
``Elaborate`` and ``Elaborate_All`` pragmas, nor any run-time checks, will
be generated by callers of ``Func`` and instantiators of ``Gen``. Note that
task type ``Tsk`` is not within this region.
An alternative to the region-based suppression is to use multiple * Pragma Elaborate_All downgrade
``Suppress`` pragmas with arguments naming specific entities for which
elaboration checks should be suppressed:
:: ::
package Range_Suppress is
function Func return Integer;
pragma Suppress (Elaboration_Check, Func);
generic change pragma Elaborate_All for unit "..." to Elaborate in unit "..."
procedure Gen;
pragma Suppress (Elaboration_Check, Gen);
task type Tsk; This tactic is always suggested with the pragma ``Elaborate_All`` elimination
end Range_Suppress; tactic. It offers a different alernative of guaranteeing that the argument of
the pragma will still be elaborated prior to the unit containing the pragma.
- *Scenario suppression* The programmer should update the pragma as advised, and rebuild the program.
When the pragma ``Suppress`` is placed in a declarative or statement * Pragma Elaborate_Body elimination
part, without an entity argument, it will suppress implicit ``Elaborate``
and ``Elaborate_All`` pragma generation, as well as run-time checks, on
all scenarios within the region.
:: ::
with Server; remove pragma Elaborate_Body in unit "..."
package body Range_Suppress is
pragma Suppress (Elaboration_Check);
function Func return Integer is This tactic is suggested when the binder has determined that pragma
begin ``Elaborate_Body``
return Server.Func;
end Func;
procedure Gen is - Prevents a set of units from being elaborated.
begin
Server.Proc;
end Gen;
pragma Unsuppress (Elaboration_Check); - The removal of the pragma will enable the successful ordering of the units.
task body Tsk is Note that the binder cannot determine whether the pragma is required for
begin other purposes, such as guaranteeing the initialization of a variable
Server.Proc; declared in the spec by elaboration code in the body.
end Tsk;
end Range_Suppress;
In the example above, a pair of Suppress/Unsuppress pragmas define a region
of suppression within package body ``Range_Suppress``. As a result, the
calls to ``Server.Func`` in ``Func`` and ``Server.Proc`` in ``Gen`` will
not generate any implicit ``Elaborate`` and ``Elaborate_All`` pragmas or
run-time checks.
.. _Resolving_Task_Issues:
Resolving Task Issues
=====================
The model of execution in Ada dictates that elaboration must first take place,
and only then can the main program be started. Tasks which are activated during
elaboration violate this model and may lead to serious concurrent problems at
elaboration time.
A task can be activated in two different ways:
* The task is created by an allocator in which case it is activated immediately
after the allocator is evaluated.
* The task is declared at the library level or within some nested master in
which case it is activated before starting execution of the statement
sequence of the master defining the task.
Since the elaboration of a partition is performed by the environment task
servicing that partition, any tasks activated during elaboration may be in
a race with the environment task, and lead to unpredictable state and behavior.
The static model seeks to avoid such interactions by assuming that all code in
the task body is executed at elaboration time, if the task was activated by
elaboration code.
::
package Decls is
task Lib_Task is
entry Start;
end Lib_Task;
type My_Int is new Integer;
function Ident (M : My_Int) return My_Int;
end Decls;
::
with Utils;
package body Decls is
task body Lib_Task is
begin
accept Start;
Utils.Put_Val (2);
end Lib_Task;
function Ident (M : My_Int) return My_Int is
begin
return M;
end Ident;
end Decls;
::
with Decls;
package Utils is
procedure Put_Val (Arg : Decls.My_Int);
end Utils;
::
with Ada.Text_IO; use Ada.Text_IO;
package body Utils is
procedure Put_Val (Arg : Decls.My_Int) is
begin
Put_Line (Arg'Img);
end Put_Val;
end Utils;
::
with Decls;
procedure Main is
begin
Decls.Lib_Task.Start;
end Main;
When the above example is compiled with the static model, an elaboration
circularity arises:
::
error: elaboration circularity detected
info: "decls (body)" must be elaborated before "decls (body)"
info: reason: implicit Elaborate_All in unit "decls (body)"
info: recompile "decls (body)" with -gnatel for full details
info: "decls (body)"
info: must be elaborated along with its spec:
info: "decls (spec)"
info: which is withed by:
info: "utils (spec)"
info: which is withed by:
info: "decls (body)"
In the above example, ``Decls`` must be elaborated prior to ``Main`` by virtue
of a with clause. The elaboration of ``Decls`` activates task ``Lib_Task``. The
static model conservatibely assumes that all code within the body of
``Lib_Task`` is executed, and generates an implicit ``Elaborate_All`` pragma
for ``Units`` due to the call to ``Utils.Put_Val``. The pragma implies that
both the spec and body of ``Utils``, along with any units they |with|,
must be elaborated prior to ``Decls``. However, ``Utils``'s spec |withs|
``Decls``, implying that ``Decls`` must be elaborated before ``Utils``. The end
result is that ``Utils`` must be elaborated prior to ``Utils``, and this
leads to a circularity.
In reality, the example above will not exhibit an ABE problem at run time.
When the body of task ``Lib_Task`` is activated, execution will wait for entry
``Start`` to be accepted, and the call to ``Utils.Put_Val`` will not take place
at elaboration time. Task ``Lib_Task`` will resume its execution after the main
program is executed because ``Main`` performs a rendezvous with
``Lib_Task.Start``, and at that point all units have already been elaborated.
As a result, the static model may seem overly conservative, partly because it
does not take control and data flow into account.
When faced with a task elaboration circularity, a programmer has several
options available:
* *Use the dynamic model*
The dynamic model does not generate implicit ``Elaborate`` and
``Elaborate_All`` pragmas. Instead, it will install checks prior to every
call in the example above, thus verifying the successful elaboration of
``Utils.Put_Val`` in case the call to it takes place at elaboration time.
The dynamic model is enabled with compiler switch :switch:`-gnatE`.
* *Isolate the tasks* The programmer should remove the pragma as advised, and rebuild the program.
Relocating tasks in their own separate package could decouple them from * Use of dynamic elaboration model
dependencies that would otherwise cause an elaboration circularity. The
example above can be rewritten as follows:
:: ::
package Decls1 is -- new use the dynamic elaboration model (compiler switch -gnatE)
task Lib_Task is
entry Start;
end Lib_Task;
end Decls1;
:: This tactic is suggested when the binder has determined that an invocation at
elaboration time
with Utils; - Prevents a set of units from being elaborated.
package body Decls1 is -- new
task body Lib_Task is
begin
accept Start;
Utils.Put_Val (2);
end Lib_Task;
end Decls1;
:: - The use of the dynamic model will enable the successful ordering of the
units.
package Decls2 is -- new The programmer has two options:
type My_Int is new Integer;
function Ident (M : My_Int) return My_Int;
end Decls2;
:: - Determine the units involved in the invocation using the detailed
invocation information, and add compiler switch :switch:`-gnatE` to the
compilation arguments of selected files only. This approach will yield
safer elaboration orders compared to the other option because it will
minimize the opportunities presented to the dynamic model for ignoring
invocations.
with Utils; - Add compiler switch :switch:`-gnatE` to the general compilation arguments.
package body Decls2 is -- new
function Ident (M : My_Int) return My_Int is
begin
return M;
end Ident;
end Decls2;
:: * Use of detailed invocation information
with Decls2;
package Utils is
procedure Put_Val (Arg : Decls2.My_Int);
end Utils;
:: ::
with Ada.Text_IO; use Ada.Text_IO; use detailed invocation information (compiler switch -gnatd_F)
package body Utils is
procedure Put_Val (Arg : Decls2.My_Int) is
begin
Put_Line (Arg'Img);
end Put_Val;
end Utils;
:: This tactic is always suggested with the use of the dynamic model tactic. It
causes the circularity section of the circularity diagnostic to describe the
flow of elaboration code from a unit to a unit, enumerating all such paths in
the process.
with Decls1; The programmer should analyze this information to determine which units
procedure Main is should be compiled with the dynamic model.
begin
Decls1.Lib_Task.Start;
end Main;
* *Declare the tasks*
The original example uses a single task declaration for ``Lib_Task``. An * Forced dependency elimination
explicit task type declaration and a properly placed task object could avoid
the dependencies that would otherwise cause an elaboration circularity. The
example can be rewritten as follows:
:: ::
package Decls is remove the dependency of unit "..." on unit "..." from the argument of switch -f
task type Lib_Task is -- new
entry Start;
end Lib_Task;
type My_Int is new Integer; This tactic is suggested when the binder has determined that a dependency
present in the forced delboration order file indicated by binder switch
:switch:`-f`
function Ident (M : My_Int) return My_Int; - Prevents a set of units from being elaborated.
end Decls;
:: - The removal of the dependency will enable the successful ordering of the
units.
with Utils; The programmer should edit the forced elaboration order file, remove the
package body Decls is dependency, and rebind the program.
task body Lib_Task is
begin
accept Start;
Utils.Put_Val (2);
end Lib_Task;
function Ident (M : My_Int) return My_Int is * All forced dependency elimination
begin
return M;
end Ident;
end Decls;
:: ::
with Decls; remove switch -f
package Utils is
procedure Put_Val (Arg : Decls.My_Int);
end Utils;
:: This tactic is suggested in case editing the forced elaboration order file is
not an option.
with Ada.Text_IO; use Ada.Text_IO; The programmer should remove binder switch :switch:`-f` from the binder
package body Utils is arguments, and rebind.
procedure Put_Val (Arg : Decls.My_Int) is
begin
Put_Line (Arg'Img);
end Put_Val;
end Utils;
::
with Decls; * Multiple circularities diagnostic
package Obj_Decls is -- new
Task_Obj : Decls.Lib_Task;
end Obj_Decls;
:: ::
with Obj_Decls; diagnose all circularities (binder switch -d_C)
procedure Main is
begin
Obj_Decls.Task_Obj.Start; -- new
end Main;
* *Use restriction No_Entry_Calls_In_Elaboration_Code* By default, the binder will diagnose only the highest precedence circularity.
If the program contains multiple circularities, the binder will suggest the
use of binder switch :switch:`-d_C` in order to obtain the diagnostics of all
circularities.
The issue exhibited in the original example under this section revolves The programmer should add binder switch :switch:`-d_C` to the binder
around the body of ``Lib_Task`` blocking on an accept statement. There is arguments, and rebind.
no rule to prevent elaboration code from performing entry calls, however in
practice this is highly unusual. In addition, the pattern of starting tasks
at elaboration time and then immediately blocking on accept or select
statements is quite common.
If a programmer knows that elaboration code will not perform any entry If none of the tactics suggested by the binder eliminate the elaboration
calls, then the programmer can indicate that the static model should not circularity, the programmer should consider using one of the legacy elaboration
process the remainder of a task body once an accept or select statement has models, in the following order:
been encountered. This behavior can be specified by a configuration pragma:
:: * Use the pre-20.x legacy elaboration order model, with binder switch
:switch:`-H`.
* Use both pre-18.x and pre-20.x legacy elaboration models, with compiler
switch :switch:`-gnatH` and binder switch :switch:`-H`.
pragma Restrictions (No_Entry_Calls_In_Elaboration_Code); * Use the relaxed static elaboration model, with compiler switches
:switch:`-gnatH` :switch:`-gnatJ` and binder switch :switch:`-H`.
In addition to the change in behavior with respect to task bodies, the * Use the relaxed dynamic elaboration model, with compiler switches
static model will verify that no entry calls take place at elaboration time. :switch:`-gnatH` :switch:`-gnatJ` :switch:`-gnatE` and binder switch
:switch:`-H`.
.. _Elaboration_Related_Compiler_Switches: .. _Elaboration_Related_Compiler_Switches:
...@@ -1465,13 +1127,17 @@ the elaboration order chosen by the binder. ...@@ -1465,13 +1127,17 @@ the elaboration order chosen by the binder.
:switch:`-gnatE` :switch:`-gnatE`
Dynamic elaboration checking mode enabled Dynamic elaboration checking mode enabled
When this switch is in effect, GNAT activates the dynamic elaboration model. When this switch is in effect, GNAT activates the dynamic model.
.. index:: -gnatel (gnat) .. index:: -gnatel (gnat)
:switch:`-gnatel` :switch:`-gnatel`
Turn on info messages on generated Elaborate[_All] pragmas Turn on info messages on generated Elaborate[_All] pragmas
This switch is only applicable to the pre-20.x legacy elaboration models.
The post-20.x elaboration model no longer relies on implicitly generated
``Elaborate`` and ``Elaborate_All`` pragmas to order units.
When this switch is in effect, GNAT will emit the following supplementary When this switch is in effect, GNAT will emit the following supplementary
information depending on the elaboration model in effect. information depending on the elaboration model in effect.
...@@ -1482,7 +1148,7 @@ the elaboration order chosen by the binder. ...@@ -1482,7 +1148,7 @@ the elaboration order chosen by the binder.
- *Static model* - *Static model*
GNAT will indicate all scenarios executed during elaboration. In addition, GNAT will indicate all scenarios invoked during elaboration. In addition,
it will provide detailed traceback when an implicit ``Elaborate`` or it will provide detailed traceback when an implicit ``Elaborate`` or
``Elaborate_All`` pragma is generated. ``Elaborate_All`` pragma is generated.
...@@ -1615,29 +1281,24 @@ options: ...@@ -1615,29 +1281,24 @@ options:
as their origins. Elaboration warnings are enabled with compiler switch as their origins. Elaboration warnings are enabled with compiler switch
:switch:`-gnatwl`. :switch:`-gnatwl`.
* Use switch :switch:`-gnatel` to obtain messages on generated implicit * Cosider the tactics given in the suggestions section of the circularity
``Elaborate`` and ``Elaborate_All`` pragmas. The trace information could diagnostic.
indicate why a server unit must be elaborated prior to a client unit.
* If the warnings produced by the static model indicate that a task is
involved, consider the options in section `Resolving Task Issues`_.
* If none of the steps outlined above resolve the circularity, use a more * If none of the steps outlined above resolve the circularity, use a more
permissive elaboration model, in the following order: permissive elaboration model, in the following order:
- Use the dynamic elaboration model, with compiler switch :switch:`-gnatE`. - Use the pre-20.x legacy elaboration order model, with binder switch
:switch:`-H`.
- Use the legacy static elaboration model, with compiler switch
:switch:`-gnatH`.
- Use the legacy dynamic elaboration model, with compiler switches - Use both pre-18.x and pre-20.x legacy elaboration models, with compiler
:switch:`-gnatH` :switch:`-gnatE`. switch :switch:`-gnatH` and binder switch :switch:`-H`.
- Use the relaxed legacy static elaboration model, with compiler switches - Use the relaxed static elaboration model, with compiler switches
:switch:`-gnatH` :switch:`-gnatJ`. :switch:`-gnatH` :switch:`-gnatJ` and binder switch :switch:`-H`.
- Use the relaxed legacy dynamic elaboration model, with compiler switches - Use the relaxed dynamic elaboration model, with compiler switches
:switch:`-gnatH` :switch:`-gnatJ` :switch:`-gnatE`. :switch:`-gnatH` :switch:`-gnatJ` :switch:`-gnatE` and binder switch
:switch:`-H`.
.. _Inspecting_the_Chosen_Elaboration_Order: .. _Inspecting_the_Chosen_Elaboration_Order:
...@@ -1650,128 +1311,128 @@ elaboration order appears as a sequence of calls to ``Elab_Body`` and ...@@ -1650,128 +1311,128 @@ elaboration order appears as a sequence of calls to ``Elab_Body`` and
``Elab_Spec``, interspersed with assignments to `Exxx` which indicates that a ``Elab_Spec``, interspersed with assignments to `Exxx` which indicates that a
particular unit is elaborated. For example: particular unit is elaborated. For example:
:: ::
System.Soft_Links'Elab_Body; System.Soft_Links'Elab_Body;
E14 := True; E14 := True;
System.Secondary_Stack'Elab_Body; System.Secondary_Stack'Elab_Body;
E18 := True; E18 := True;
System.Exception_Table'Elab_Body; System.Exception_Table'Elab_Body;
E24 := True; E24 := True;
Ada.Io_Exceptions'Elab_Spec; Ada.Io_Exceptions'Elab_Spec;
E67 := True; E67 := True;
Ada.Tags'Elab_Spec; Ada.Tags'Elab_Spec;
Ada.Streams'Elab_Spec; Ada.Streams'Elab_Spec;
E43 := True; E43 := True;
Interfaces.C'Elab_Spec; Interfaces.C'Elab_Spec;
E69 := True; E69 := True;
System.Finalization_Root'Elab_Spec; System.Finalization_Root'Elab_Spec;
E60 := True; E60 := True;
System.Os_Lib'Elab_Body; System.Os_Lib'Elab_Body;
E71 := True; E71 := True;
System.Finalization_Implementation'Elab_Spec; System.Finalization_Implementation'Elab_Spec;
System.Finalization_Implementation'Elab_Body; System.Finalization_Implementation'Elab_Body;
E62 := True; E62 := True;
Ada.Finalization'Elab_Spec; Ada.Finalization'Elab_Spec;
E58 := True; E58 := True;
Ada.Finalization.List_Controller'Elab_Spec; Ada.Finalization.List_Controller'Elab_Spec;
E76 := True; E76 := True;
System.File_Control_Block'Elab_Spec; System.File_Control_Block'Elab_Spec;
E74 := True; E74 := True;
System.File_Io'Elab_Body; System.File_Io'Elab_Body;
E56 := True; E56 := True;
Ada.Tags'Elab_Body; Ada.Tags'Elab_Body;
E45 := True; E45 := True;
Ada.Text_Io'Elab_Spec; Ada.Text_Io'Elab_Spec;
Ada.Text_Io'Elab_Body; Ada.Text_Io'Elab_Body;
E07 := True; E07 := True;
Note also binder switch :switch:`-l`, which outputs the chosen elaboration Note also binder switch :switch:`-l`, which outputs the chosen elaboration
order and provides a more readable form of the above: order and provides a more readable form of the above:
:: ::
ada (spec) ada (spec)
interfaces (spec) interfaces (spec)
system (spec) system (spec)
system.case_util (spec) system.case_util (spec)
system.case_util (body) system.case_util (body)
system.concat_2 (spec) system.concat_2 (spec)
system.concat_2 (body) system.concat_2 (body)
system.concat_3 (spec) system.concat_3 (spec)
system.concat_3 (body) system.concat_3 (body)
system.htable (spec) system.htable (spec)
system.parameters (spec) system.parameters (spec)
system.parameters (body) system.parameters (body)
system.crtl (spec) system.crtl (spec)
interfaces.c_streams (spec) interfaces.c_streams (spec)
interfaces.c_streams (body) interfaces.c_streams (body)
system.restrictions (spec) system.restrictions (spec)
system.restrictions (body) system.restrictions (body)
system.standard_library (spec) system.standard_library (spec)
system.exceptions (spec) system.exceptions (spec)
system.exceptions (body) system.exceptions (body)
system.storage_elements (spec) system.storage_elements (spec)
system.storage_elements (body) system.storage_elements (body)
system.secondary_stack (spec) system.secondary_stack (spec)
system.stack_checking (spec) system.stack_checking (spec)
system.stack_checking (body) system.stack_checking (body)
system.string_hash (spec) system.string_hash (spec)
system.string_hash (body) system.string_hash (body)
system.htable (body) system.htable (body)
system.strings (spec) system.strings (spec)
system.strings (body) system.strings (body)
system.traceback (spec) system.traceback (spec)
system.traceback (body) system.traceback (body)
system.traceback_entries (spec) system.traceback_entries (spec)
system.traceback_entries (body) system.traceback_entries (body)
ada.exceptions (spec) ada.exceptions (spec)
ada.exceptions.last_chance_handler (spec) ada.exceptions.last_chance_handler (spec)
system.soft_links (spec) system.soft_links (spec)
system.soft_links (body) system.soft_links (body)
ada.exceptions.last_chance_handler (body) ada.exceptions.last_chance_handler (body)
system.secondary_stack (body) system.secondary_stack (body)
system.exception_table (spec) system.exception_table (spec)
system.exception_table (body) system.exception_table (body)
ada.io_exceptions (spec) ada.io_exceptions (spec)
ada.tags (spec) ada.tags (spec)
ada.streams (spec) ada.streams (spec)
interfaces.c (spec) interfaces.c (spec)
interfaces.c (body) interfaces.c (body)
system.finalization_root (spec) system.finalization_root (spec)
system.finalization_root (body) system.finalization_root (body)
system.memory (spec) system.memory (spec)
system.memory (body) system.memory (body)
system.standard_library (body) system.standard_library (body)
system.os_lib (spec) system.os_lib (spec)
system.os_lib (body) system.os_lib (body)
system.unsigned_types (spec) system.unsigned_types (spec)
system.stream_attributes (spec) system.stream_attributes (spec)
system.stream_attributes (body) system.stream_attributes (body)
system.finalization_implementation (spec) system.finalization_implementation (spec)
system.finalization_implementation (body) system.finalization_implementation (body)
ada.finalization (spec) ada.finalization (spec)
ada.finalization (body) ada.finalization (body)
ada.finalization.list_controller (spec) ada.finalization.list_controller (spec)
ada.finalization.list_controller (body) ada.finalization.list_controller (body)
system.file_control_block (spec) system.file_control_block (spec)
system.file_io (spec) system.file_io (spec)
system.file_io (body) system.file_io (body)
system.val_uns (spec) system.val_uns (spec)
system.val_util (spec) system.val_util (spec)
system.val_util (body) system.val_util (body)
system.val_uns (body) system.val_uns (body)
system.wch_con (spec) system.wch_con (spec)
system.wch_con (body) system.wch_con (body)
system.wch_cnv (spec) system.wch_cnv (spec)
system.wch_jis (spec) system.wch_jis (spec)
system.wch_jis (body) system.wch_jis (body)
system.wch_cnv (body) system.wch_cnv (body)
system.wch_stw (spec) system.wch_stw (spec)
system.wch_stw (body) system.wch_stw (body)
ada.tags (body) ada.tags (body)
ada.exceptions (body) ada.exceptions (body)
ada.text_io (spec) ada.text_io (spec)
ada.text_io (body) ada.text_io (body)
text_io (spec) text_io (spec)
gdbstr (body) gdbstr (body)
...@@ -533,15 +533,11 @@ Elaboration Order Handling in GNAT ...@@ -533,15 +533,11 @@ Elaboration Order Handling in GNAT
* Checking the Elaboration Order:: * Checking the Elaboration Order::
* Controlling the Elaboration Order in Ada:: * Controlling the Elaboration Order in Ada::
* Controlling the Elaboration Order in GNAT:: * Controlling the Elaboration Order in GNAT::
* Common Elaboration-model Traits::
* Dynamic Elaboration Model in GNAT::
* Static Elaboration Model in GNAT::
* SPARK Elaboration Model in GNAT::
* Legacy Elaboration Model in GNAT::
* Mixing Elaboration Models:: * Mixing Elaboration Models::
* ABE Diagnostics::
* SPARK Diagnostics::
* Elaboration Circularities:: * Elaboration Circularities::
* Resolving Elaboration Circularities:: * Resolving Elaboration Circularities::
* Resolving Task Issues::
* Elaboration-related Compiler Switches:: * Elaboration-related Compiler Switches::
* Summary of Procedures for Elaboration Control:: * Summary of Procedures for Elaboration Control::
* Inspecting the Chosen Elaboration Order:: * Inspecting the Chosen Elaboration Order::
...@@ -9585,7 +9581,8 @@ checking options to be controlled from the command line. ...@@ -9585,7 +9581,8 @@ checking options to be controlled from the command line.
@item @code{-gnatE} @item @code{-gnatE}
Full dynamic elaboration checks. Dynamic elaboration checking mode enabled. For further details see
@ref{f,,Elaboration Order Handling in GNAT}.
@end table @end table
@geindex -gnatf (gcc) @geindex -gnatf (gcc)
...@@ -9651,8 +9648,9 @@ Output usage information. The output is written to @code{stdout}. ...@@ -9651,8 +9648,9 @@ Output usage information. The output is written to @code{stdout}.
@item @code{-gnatH} @item @code{-gnatH}
Legacy elaboration-checking mode enabled. When this switch is in effect, the Legacy elaboration-checking mode enabled. When this switch is in effect,
pre-18.x access-before-elaboration model becomes the de facto model. the pre-18.x access-before-elaboration model becomes the de facto model.
For further details see @ref{f,,Elaboration Order Handling in GNAT}.
@end table @end table
@geindex -gnati (gcc) @geindex -gnati (gcc)
...@@ -9749,7 +9747,8 @@ Select statements ...@@ -9749,7 +9747,8 @@ Select statements
Synchronous task suspension Synchronous task suspension
@end itemize @end itemize
and does not emit compile-time diagnostics or run-time checks. and does not emit compile-time diagnostics or run-time checks. For further
details see @ref{f,,Elaboration Order Handling in GNAT}.
@end table @end table
@geindex -gnatk (gcc) @geindex -gnatk (gcc)
...@@ -15747,7 +15746,8 @@ Currently the same as @code{-Ea}. ...@@ -15747,7 +15746,8 @@ Currently the same as @code{-Ea}.
@item @code{-f@emph{elab-order}} @item @code{-f@emph{elab-order}}
Force elaboration order. Force elaboration order. For further details see @ref{120,,Elaboration Control}
and @ref{f,,Elaboration Order Handling in GNAT}.
@end table @end table
@geindex -F (gnatbind) @geindex -F (gnatbind)
...@@ -15774,22 +15774,41 @@ flag checks are generated. ...@@ -15774,22 +15774,41 @@ flag checks are generated.
@item @code{-h} @item @code{-h}
Output usage (help) information. Output usage (help) information.
@end table
@geindex -H (gnatbind)
@table @asis
@item @code{-H}
Legacy elaboration order model enabled. For further details see
@ref{f,,Elaboration Order Handling in GNAT}.
@end table
@geindex -H32 (gnatbind) @geindex -H32 (gnatbind)
@table @asis
@item @code{-H32} @item @code{-H32}
Use 32-bit allocations for @code{__gnat_malloc} (and thus for access types). Use 32-bit allocations for @code{__gnat_malloc} (and thus for access types).
For further details see @ref{120,,Dynamic Allocation Control}. For further details see @ref{121,,Dynamic Allocation Control}.
@end table
@geindex -H64 (gnatbind) @geindex -H64 (gnatbind)
@geindex __gnat_malloc @geindex __gnat_malloc
@table @asis
@item @code{-H64} @item @code{-H64}
Use 64-bit allocations for @code{__gnat_malloc} (and thus for access types). Use 64-bit allocations for @code{__gnat_malloc} (and thus for access types).
For further details see @ref{120,,Dynamic Allocation Control}. For further details see @ref{121,,Dynamic Allocation Control}.
@geindex -I (gnatbind) @geindex -I (gnatbind)
...@@ -16019,7 +16038,7 @@ Enable dynamic stack usage, with @code{n} results stored and displayed ...@@ -16019,7 +16038,7 @@ Enable dynamic stack usage, with @code{n} results stored and displayed
at program termination. A result is generated when a task at program termination. A result is generated when a task
terminates. Results that can't be stored are displayed on the fly, at terminates. Results that can't be stored are displayed on the fly, at
task termination. This option is currently not supported on Itanium task termination. This option is currently not supported on Itanium
platforms. (See @ref{121,,Dynamic Stack Usage Analysis} for details.) platforms. (See @ref{122,,Dynamic Stack Usage Analysis} for details.)
@geindex -v (gnatbind) @geindex -v (gnatbind)
...@@ -16088,7 +16107,7 @@ no arguments. ...@@ -16088,7 +16107,7 @@ no arguments.
@end menu @end menu
@node Consistency-Checking Modes,Binder Error Message Control,,Switches for gnatbind @node Consistency-Checking Modes,Binder Error Message Control,,Switches for gnatbind
@anchor{gnat_ugn/building_executable_programs_with_gnat consistency-checking-modes}@anchor{122}@anchor{gnat_ugn/building_executable_programs_with_gnat id35}@anchor{123} @anchor{gnat_ugn/building_executable_programs_with_gnat consistency-checking-modes}@anchor{123}@anchor{gnat_ugn/building_executable_programs_with_gnat id35}@anchor{124}
@subsubsection Consistency-Checking Modes @subsubsection Consistency-Checking Modes
...@@ -16142,7 +16161,7 @@ case the checking against sources has already been performed by ...@@ -16142,7 +16161,7 @@ case the checking against sources has already been performed by
@end table @end table
@node Binder Error Message Control,Elaboration Control,Consistency-Checking Modes,Switches for gnatbind @node Binder Error Message Control,Elaboration Control,Consistency-Checking Modes,Switches for gnatbind
@anchor{gnat_ugn/building_executable_programs_with_gnat id36}@anchor{124}@anchor{gnat_ugn/building_executable_programs_with_gnat binder-error-message-control}@anchor{125} @anchor{gnat_ugn/building_executable_programs_with_gnat id36}@anchor{125}@anchor{gnat_ugn/building_executable_programs_with_gnat binder-error-message-control}@anchor{126}
@subsubsection Binder Error Message Control @subsubsection Binder Error Message Control
...@@ -16252,12 +16271,12 @@ with extreme care. ...@@ -16252,12 +16271,12 @@ with extreme care.
@end table @end table
@node Elaboration Control,Output Control,Binder Error Message Control,Switches for gnatbind @node Elaboration Control,Output Control,Binder Error Message Control,Switches for gnatbind
@anchor{gnat_ugn/building_executable_programs_with_gnat id37}@anchor{126}@anchor{gnat_ugn/building_executable_programs_with_gnat elaboration-control}@anchor{127} @anchor{gnat_ugn/building_executable_programs_with_gnat id37}@anchor{127}@anchor{gnat_ugn/building_executable_programs_with_gnat elaboration-control}@anchor{120}
@subsubsection Elaboration Control @subsubsection Elaboration Control
The following switches provide additional control over the elaboration The following switches provide additional control over the elaboration
order. For full details see @ref{f,,Elaboration Order Handling in GNAT}. order. For further details see @ref{f,,Elaboration Order Handling in GNAT}.
@geindex -f (gnatbind) @geindex -f (gnatbind)
...@@ -16302,30 +16321,38 @@ above forced elaboration order file. ...@@ -16302,30 +16321,38 @@ above forced elaboration order file.
Blank lines and Ada-style comments are ignored. Unit names that do not exist Blank lines and Ada-style comments are ignored. Unit names that do not exist
in the program are ignored. Units in the GNAT predefined library are also in the program are ignored. Units in the GNAT predefined library are also
ignored. ignored.
@end table
@geindex -p (gnatbind) @geindex -p (gnatbind)
@table @asis
@item @code{-p} @item @code{-p}
Normally the binder attempts to choose an elaboration order that is Pessimistic elaboration order
likely to minimize the likelihood of an elaboration order error resulting
in raising a @code{Program_Error} exception. This switch reverses the
action of the binder, and requests that it deliberately choose an order
that is likely to maximize the likelihood of an elaboration error.
This is useful in ensuring portability and avoiding dependence on
accidental fortuitous elaboration ordering.
Normally it only makes sense to use the @code{-p} This switch is only applicable to the pre-20.x legacy elaboration models.
switch if dynamic The post-20.x elaboration model uses a more informed approach of ordering
the units.
Normally the binder attempts to choose an elaboration order that is likely to
minimize the likelihood of an elaboration order error resulting in raising a
@code{Program_Error} exception. This switch reverses the action of the binder,
and requests that it deliberately choose an order that is likely to maximize
the likelihood of an elaboration error. This is useful in ensuring
portability and avoiding dependence on accidental fortuitous elaboration
ordering.
Normally it only makes sense to use the @code{-p} switch if dynamic
elaboration checking is used (@code{-gnatE} switch used for compilation). elaboration checking is used (@code{-gnatE} switch used for compilation).
This is because in the default static elaboration mode, all necessary This is because in the default static elaboration mode, all necessary
@code{Elaborate} and @code{Elaborate_All} pragmas are implicitly inserted. @code{Elaborate} and @code{Elaborate_All} pragmas are implicitly inserted.
These implicit pragmas are still respected by the binder in These implicit pragmas are still respected by the binder in @code{-p}
@code{-p} mode, so a mode, so a safe elaboration order is assured.
safe elaboration order is assured.
Note that @code{-p} is not intended for Note that @code{-p} is not intended for production use; it is more for
production use; it is more for debugging/experimental use. debugging/experimental use.
@end table @end table
@node Output Control,Dynamic Allocation Control,Elaboration Control,Switches for gnatbind @node Output Control,Dynamic Allocation Control,Elaboration Control,Switches for gnatbind
...@@ -16410,7 +16437,7 @@ be used to improve code generation in some cases. ...@@ -16410,7 +16437,7 @@ be used to improve code generation in some cases.
@end table @end table
@node Dynamic Allocation Control,Binding with Non-Ada Main Programs,Output Control,Switches for gnatbind @node Dynamic Allocation Control,Binding with Non-Ada Main Programs,Output Control,Switches for gnatbind
@anchor{gnat_ugn/building_executable_programs_with_gnat dynamic-allocation-control}@anchor{120}@anchor{gnat_ugn/building_executable_programs_with_gnat id39}@anchor{12a} @anchor{gnat_ugn/building_executable_programs_with_gnat dynamic-allocation-control}@anchor{121}@anchor{gnat_ugn/building_executable_programs_with_gnat id39}@anchor{12a}
@subsubsection Dynamic Allocation Control @subsubsection Dynamic Allocation Control
...@@ -23169,7 +23196,7 @@ subprogram whose stack usage might be larger than the specified amount of ...@@ -23169,7 +23196,7 @@ subprogram whose stack usage might be larger than the specified amount of
bytes. The wording is in keeping with the qualifier documented above. bytes. The wording is in keeping with the qualifier documented above.
@node Dynamic Stack Usage Analysis,,Static Stack Usage Analysis,Stack Related Facilities @node Dynamic Stack Usage Analysis,,Static Stack Usage Analysis,Stack Related Facilities
@anchor{gnat_ugn/gnat_and_program_execution dynamic-stack-usage-analysis}@anchor{121}@anchor{gnat_ugn/gnat_and_program_execution id60}@anchor{1c6} @anchor{gnat_ugn/gnat_and_program_execution dynamic-stack-usage-analysis}@anchor{122}@anchor{gnat_ugn/gnat_and_program_execution id60}@anchor{1c6}
@subsection Dynamic Stack Usage Analysis @subsection Dynamic Stack Usage Analysis
...@@ -27187,15 +27214,11 @@ GNAT, either automatically or with explicit programming features. ...@@ -27187,15 +27214,11 @@ GNAT, either automatically or with explicit programming features.
* Checking the Elaboration Order:: * Checking the Elaboration Order::
* Controlling the Elaboration Order in Ada:: * Controlling the Elaboration Order in Ada::
* Controlling the Elaboration Order in GNAT:: * Controlling the Elaboration Order in GNAT::
* Common Elaboration-model Traits::
* Dynamic Elaboration Model in GNAT::
* Static Elaboration Model in GNAT::
* SPARK Elaboration Model in GNAT::
* Legacy Elaboration Model in GNAT::
* Mixing Elaboration Models:: * Mixing Elaboration Models::
* ABE Diagnostics::
* SPARK Diagnostics::
* Elaboration Circularities:: * Elaboration Circularities::
* Resolving Elaboration Circularities:: * Resolving Elaboration Circularities::
* Resolving Task Issues::
* Elaboration-related Compiler Switches:: * Elaboration-related Compiler Switches::
* Summary of Procedures for Elaboration Control:: * Summary of Procedures for Elaboration Control::
* Inspecting the Chosen Elaboration Order:: * Inspecting the Chosen Elaboration Order::
...@@ -27243,9 +27266,15 @@ In addition to the Ada terminology, this appendix defines the following terms: ...@@ -27243,9 +27266,15 @@ In addition to the Ada terminology, this appendix defines the following terms:
@itemize * @itemize *
@item @item
@emph{Invocation}
The act of calling a subprogram, instantiating a generic, or activating a
task.
@item
@emph{Scenario} @emph{Scenario}
A construct that is elaborated or executed by elaboration code is referred to A construct that is elaborated or invoked by elaboration code is referred to
as an @emph{elaboration scenario} or simply a @strong{scenario}. GNAT recognizes the as an @emph{elaboration scenario} or simply a @strong{scenario}. GNAT recognizes the
following scenarios: following scenarios:
...@@ -27317,7 +27346,7 @@ end Client; ...@@ -27317,7 +27346,7 @@ end Client;
In the example above, the call to @code{Server.Func} is an elaboration scenario In the example above, the call to @code{Server.Func} is an elaboration scenario
because it appears at the library level of package @code{Client}. Note that the because it appears at the library level of package @code{Client}. Note that the
declaration of package @code{Nested} is ignored according to the definition declaration of package @code{Nested} is ignored according to the definition
given above. As a result, the call to @code{Server.Func} will be executed when given above. As a result, the call to @code{Server.Func} will be invoked when
the spec of unit @code{Client} is elaborated. the spec of unit @code{Client} is elaborated.
@item @item
...@@ -27340,7 +27369,7 @@ end Client; ...@@ -27340,7 +27369,7 @@ end Client;
In the example above, the call to @code{Proc} is an elaboration scenario because In the example above, the call to @code{Proc} is an elaboration scenario because
it appears within the statement sequence of package body @code{Client}. As a it appears within the statement sequence of package body @code{Client}. As a
result, the call to @code{Proc} will be executed when the body of @code{Client} is result, the call to @code{Proc} will be invoked when the body of @code{Client} is
elaborated. elaborated.
@end itemize @end itemize
...@@ -27354,6 +27383,8 @@ executed is referred to as @strong{elaboration order}. ...@@ -27354,6 +27383,8 @@ executed is referred to as @strong{elaboration order}.
Within a single unit, elaboration code is executed in sequential order. Within a single unit, elaboration code is executed in sequential order.
@quotation
@example @example
package body Client is package body Client is
Result : ... := Server.Func; Result : ... := Server.Func;
...@@ -27367,6 +27398,7 @@ begin ...@@ -27367,6 +27398,7 @@ begin
Proc; Proc;
end Client; end Client;
@end example @end example
@end quotation
In the example above, the elaboration order within package body @code{Client} is In the example above, the elaboration order within package body @code{Client} is
as follows: as follows:
...@@ -27414,6 +27446,9 @@ factors: ...@@ -27414,6 +27446,9 @@ factors:
@emph{with}ed units @emph{with}ed units
@item @item
parent units
@item
purity of units purity of units
@item @item
...@@ -27421,10 +27456,15 @@ preelaborability of units ...@@ -27421,10 +27456,15 @@ preelaborability of units
@item @item
presence of elaboration control pragmas presence of elaboration control pragmas
@item
invocations performed in elaboration code
@end itemize @end itemize
A program may have several elaboration orders depending on its structure. A program may have several elaboration orders depending on its structure.
@quotation
@example @example
package Server is package Server is
function Func (Index : Integer) return Integer; function Func (Index : Integer) return Integer;
...@@ -27453,16 +27493,20 @@ end Client; ...@@ -27453,16 +27493,20 @@ end Client;
with Client; with Client;
procedure Main is begin null; end Main; procedure Main is begin null; end Main;
@end example @end example
@end quotation
The following elaboration order exhibits a fundamental problem referred to as The following elaboration order exhibits a fundamental problem referred to as
@emph{access-before-elaboration} or simply @strong{ABE}. @emph{access-before-elaboration} or simply @strong{ABE}.
@quotation
@example @example
spec of Server spec of Server
spec of Client spec of Client
body of Server body of Server
body of Main body of Main
@end example @end example
@end quotation
The elaboration of @code{Server}'s spec materializes function @code{Func}, making it The elaboration of @code{Server}'s spec materializes function @code{Func}, making it
callable. The elaboration of @code{Client}'s spec elaborates the declaration of callable. The elaboration of @code{Client}'s spec elaborates the declaration of
...@@ -27480,19 +27524,23 @@ vein as index or null exclusion checks. A failed ABE check raises exception ...@@ -27480,19 +27524,23 @@ vein as index or null exclusion checks. A failed ABE check raises exception
The following elaboration order avoids the ABE problem and the program can be The following elaboration order avoids the ABE problem and the program can be
successfully elaborated. successfully elaborated.
@quotation
@example @example
spec of Server spec of Server
body of Server body of Server
spec of Client spec of Client
body of Main body of Main
@end example @end example
@end quotation
Ada states that a total elaboration order must exist, but it does not define Ada states that a total elaboration order must exist, but it does not define
what this order is. A compiler is thus tasked with choosing a suitable what this order is. A compiler is thus tasked with choosing a suitable
elaboration order which satisfies the dependencies imposed by @emph{with} clauses, elaboration order which satisfies the dependencies imposed by @emph{with} clauses,
unit categorization, and elaboration control pragmas. Ideally an order which unit categorization, elaboration control pragmas, and invocations performed in
avoids ABE problems should be chosen, however a compiler may not always find elaboration code. Ideally an order that avoids ABE problems should be chosen,
such an order due to complications with respect to control and data flow. however a compiler may not always find such an order due to complications with
respect to control and data flow.
@node Checking the Elaboration Order,Controlling the Elaboration Order in Ada,Elaboration Order,Elaboration Order Handling in GNAT @node Checking the Elaboration Order,Controlling the Elaboration Order in Ada,Elaboration Order,Elaboration Order Handling in GNAT
@anchor{gnat_ugn/elaboration_order_handling_in_gnat id4}@anchor{231}@anchor{gnat_ugn/elaboration_order_handling_in_gnat checking-the-elaboration-order}@anchor{232} @anchor{gnat_ugn/elaboration_order_handling_in_gnat id4}@anchor{231}@anchor{gnat_ugn/elaboration_order_handling_in_gnat checking-the-elaboration-order}@anchor{232}
...@@ -27517,7 +27565,7 @@ always elaborated prior to Client. The same principle applies to child units ...@@ -27517,7 +27565,7 @@ always elaborated prior to Client. The same principle applies to child units
@emph{Dynamic semantics} @emph{Dynamic semantics}
Dynamic checks are performed at run time, to ensure that a target is Dynamic checks are performed at run time, to ensure that a target is
elaborated prior to a scenario that executes it, thus avoiding ABE problems. elaborated prior to a scenario that invokes it, thus avoiding ABE problems.
A failed run-time check raises exception @code{Program_Error}. The following A failed run-time check raises exception @code{Program_Error}. The following
restrictions apply: restrictions apply:
...@@ -27546,8 +27594,7 @@ associated task type has been elaborated. ...@@ -27546,8 +27594,7 @@ associated task type has been elaborated.
The restrictions above can be summarized by the following rule: The restrictions above can be summarized by the following rule:
@emph{If a target has a body, then this body must be elaborated prior to the @emph{If a target has a body, then this body must be elaborated prior to the
execution of the scenario that invokes, instantiates, or activates the scenario that invokes the target.}
target.}
@item @item
@emph{Elaboration control} @emph{Elaboration control}
...@@ -27623,7 +27670,7 @@ but still strong enough to prevent ABE problems within a unit. ...@@ -27623,7 +27670,7 @@ but still strong enough to prevent ABE problems within a unit.
Pragma @code{Elaborate_Body} requires that the body of a unit is elaborated Pragma @code{Elaborate_Body} requires that the body of a unit is elaborated
immediately after its spec. This restriction guarantees that no client immediately after its spec. This restriction guarantees that no client
scenario can execute a server target before the target body has been scenario can invoke a server target before the target body has been
elaborated because the spec and body are effectively "glued" together. elaborated because the spec and body are effectively "glued" together.
@example @example
...@@ -27884,7 +27931,7 @@ Note that one additional advantage of using @code{Elaborate} and @code{Elaborate ...@@ -27884,7 +27931,7 @@ Note that one additional advantage of using @code{Elaborate} and @code{Elaborate
is that the program continues to stay in the last state (one or more correct is that the program continues to stay in the last state (one or more correct
orders exist) even if maintenance changes the bodies of targets. orders exist) even if maintenance changes the bodies of targets.
@node Controlling the Elaboration Order in GNAT,Common Elaboration-model Traits,Controlling the Elaboration Order in Ada,Elaboration Order Handling in GNAT @node Controlling the Elaboration Order in GNAT,Mixing Elaboration Models,Controlling the Elaboration Order in Ada,Elaboration Order Handling in GNAT
@anchor{gnat_ugn/elaboration_order_handling_in_gnat id6}@anchor{235}@anchor{gnat_ugn/elaboration_order_handling_in_gnat controlling-the-elaboration-order-in-gnat}@anchor{236} @anchor{gnat_ugn/elaboration_order_handling_in_gnat id6}@anchor{235}@anchor{gnat_ugn/elaboration_order_handling_in_gnat controlling-the-elaboration-order-in-gnat}@anchor{236}
@section Controlling the Elaboration Order in GNAT @section Controlling the Elaboration Order in GNAT
...@@ -27901,12 +27948,34 @@ elaboration order and to diagnose elaboration problems. ...@@ -27901,12 +27948,34 @@ elaboration order and to diagnose elaboration problems.
@item @item
@emph{Dynamic elaboration model} @emph{Dynamic elaboration model}
This is the most permissive of the three elaboration models. When the This is the most permissive of the three elaboration models and emulates the
dynamic model is in effect, GNAT assumes that all code within all units in behavior specified by the Ada Reference Manual. When the dynamic model is in
a partition is elaboration code. GNAT performs very few diagnostics and effect, GNAT makes the following assumptions:
generates run-time checks to verify the elaboration order of a program. This
behavior is identical to that specified by the Ada Reference Manual. The
dynamic model is enabled with compiler switch @code{-gnatE}. @itemize -
@item
All code within all units in a partition is considered to be elaboration
code.
@item
Some of the invocations in elaboration code may not take place at runtime
due to conditional execution.
@end itemize
GNAT performs extensive diagnostics on a unit-by-unit basis for all scenarios
that invoke internal targets. In addition, GNAT generates run-time checks for
all external targets and for all scenarios that may exhibit ABE problems.
The elaboration order is obtained by honoring all @emph{with} clauses, purity and
preelaborability of units, and elaboration control pragmas. The dynamic model
attempts to take all invocations in elaboration code into account. If an
invocation leads to a circularity, GNAT ignores the invocation based on the
assumptions stated above. An order obtained using the dynamic model may fail
an ABE check at runtime when GNAT ignored an invocation.
The dynamic model is enabled with compiler switch @code{-gnatE}.
@end itemize @end itemize
@geindex Static elaboration model @geindex Static elaboration model
...@@ -27918,12 +27987,31 @@ dynamic model is enabled with compiler switch @code{-gnatE}. ...@@ -27918,12 +27987,31 @@ dynamic model is enabled with compiler switch @code{-gnatE}.
@emph{Static elaboration model} @emph{Static elaboration model}
This is the middle ground of the three models. When the static model is in This is the middle ground of the three models. When the static model is in
effect, GNAT performs extensive diagnostics on a unit-by-unit basis for all effect, GNAT makes the following assumptions:
scenarios that elaborate or execute internal targets. GNAT also generates
run-time checks for all external targets and for all scenarios that may
exhibit ABE problems. Finally, GNAT installs implicit @code{Elaborate} and @itemize -
@code{Elaborate_All} pragmas for server units based on the dependencies of
client units. The static model is the default model in GNAT. @item
Only code at the library level and in package body statements within all
units in a partition is considered to be elaboration code.
@item
All invocations in elaboration will take place at runtime, regardless of
conditional execution.
@end itemize
GNAT performs extensive diagnostics on a unit-by-unit basis for all scenarios
that invoke internal targets. In addition, GNAT generates run-time checks for
all external targets and for all scenarios that may exhibit ABE problems.
The elaboration order is obtained by honoring all @emph{with} clauses, purity and
preelaborability of units, presence of elaboration control pragmas, and all
invocations in elaboration code. An order obtained using the static model is
guaranteed to be ABE problem-free, excluding dispatching calls and
access-to-subprogram types.
The static model is the default model in GNAT.
@end itemize @end itemize
@geindex SPARK elaboration model @geindex SPARK elaboration model
...@@ -27937,21 +28025,34 @@ client units. The static model is the default model in GNAT. ...@@ -27937,21 +28025,34 @@ client units. The static model is the default model in GNAT.
This is the most conservative of the three models and enforces the SPARK This is the most conservative of the three models and enforces the SPARK
rules of elaboration as defined in the SPARK Reference Manual, section 7.7. rules of elaboration as defined in the SPARK Reference Manual, section 7.7.
The SPARK model is in effect only when a scenario and a target reside in a The SPARK model is in effect only when a scenario and a target reside in a
region subject to SPARK_Mode On, otherwise the dynamic or static model is in region subject to @code{SPARK_Mode On}, otherwise the dynamic or static model
effect. is in effect.
The SPARK model is enabled with compiler switch @code{-gnatd.v}.
@end itemize @end itemize
@geindex Legacy elaboration model @geindex Legacy elaboration models
@itemize * @itemize *
@item @item
@emph{Legacy elaboration model} @emph{Legacy elaboration models}
In addition to the three elaboration models outlined above, GNAT provides the In addition to the three elaboration models outlined above, GNAT provides the
elaboration model of pre-18.x versions referred to as @cite{legacy elaboration model}. The legacy elaboration model is enabled with compiler switch following legacy models:
@code{-gnatH}.
@itemize -
@item
@cite{Legacy elaboration-checking model} available in pre-18.x versions of GNAT.
This model is enabled with compiler switch @code{-gnatH}.
@item
@cite{Legacy elaboration-order model} available in pre-20.x versions of GNAT.
This model is enabled with binder switch @code{-H}.
@end itemize
@end itemize @end itemize
@geindex Relaxed elaboration mode @geindex Relaxed elaboration mode
...@@ -27960,878 +28061,536 @@ The dynamic, legacy, and static models can be relaxed using compiler switch ...@@ -27960,878 +28061,536 @@ The dynamic, legacy, and static models can be relaxed using compiler switch
@code{-gnatJ}, making them more permissive. Note that in this mode, GNAT @code{-gnatJ}, making them more permissive. Note that in this mode, GNAT
may not diagnose certain elaboration issues or install run-time checks. may not diagnose certain elaboration issues or install run-time checks.
@node Common Elaboration-model Traits,Dynamic Elaboration Model in GNAT,Controlling the Elaboration Order in GNAT,Elaboration Order Handling in GNAT @node Mixing Elaboration Models,ABE Diagnostics,Controlling the Elaboration Order in GNAT,Elaboration Order Handling in GNAT
@anchor{gnat_ugn/elaboration_order_handling_in_gnat common-elaboration-model-traits}@anchor{237}@anchor{gnat_ugn/elaboration_order_handling_in_gnat id7}@anchor{238} @anchor{gnat_ugn/elaboration_order_handling_in_gnat mixing-elaboration-models}@anchor{237}@anchor{gnat_ugn/elaboration_order_handling_in_gnat id7}@anchor{238}
@section Common Elaboration-model Traits @section Mixing Elaboration Models
All three GNAT models are able to detect elaboration problems related to It is possible to mix units compiled with a different elaboration model,
dispatching calls and a particular kind of ABE referred to as @emph{guaranteed ABE}. however the following rules must be observed:
@itemize * @itemize *
@item @item
@emph{Dispatching calls} A client unit compiled with the dynamic model can only @emph{with} a server unit
that meets at least one of the following criteria:
GNAT installs run-time checks for each primitive subprogram of each tagged
type defined in a partition on the assumption that a dispatching call @itemize -
invoked at elaboration time will execute one of these primitives. As a
result, a dispatching call that executes a primitive whose body has not
been elaborated yet will raise exception @code{Program_Error} at run time. The
checks can be suppressed using pragma @code{Suppress (Elaboration_Check)}.
@item @item
@emph{Guaranteed ABE} The server unit is compiled with the dynamic model.
A guaranteed ABE arises when the body of a target is not elaborated early @item
enough, and causes all scenarios that directly execute the target to fail. The server unit is a GNAT implementation unit from the @code{Ada}, @code{GNAT},
@code{Interfaces}, or @code{System} hierarchies.
@example @item
package body Guaranteed_ABE is The server unit has pragma @code{Pure} or @code{Preelaborate}.
function ABE return Integer;
Val : constant Integer := ABE; @item
The client unit has an explicit @code{Elaborate_All} pragma for the server
unit.
@end itemize
@end itemize
function ABE return Integer is These rules ensure that elaboration checks are not omitted. If the rules are
begin violated, the binder emits a warning:
...
end ABE;
end Guaranteed_ABE;
@end example
In the example above, the elaboration of @code{Guaranteed_ABE}'s body elaborates @quotation
the declaration of @code{Val}. This invokes function @code{ABE}, however the body
of @code{ABE} has not been elaborated yet. GNAT emits similar diagnostics in all
three models:
@example @example
1. package body Guaranteed_ABE is warning: "x.ads" has dynamic elaboration checks and with's
2. function ABE return Integer; warning: "y.ads" which has static elaboration checks
3.
4. Val : constant Integer := ABE;
|
>>> warning: cannot call "ABE" before body seen
>>> warning: Program_Error will be raised at run time
5.
6. function ABE return Integer is
7. begin
8. ...
9. end ABE;
10. end Guaranteed_ABE;
@end example @end example
@end itemize @end quotation
Note that GNAT emits warnings rather than hard errors whenever it encounters an The warnings can be suppressed by binder switch @code{-ws}.
elaboration problem. This is because the elaboration model in effect may be too
conservative, or a particular scenario may not be elaborated or executed due to
data and control flow. The warnings can be suppressed selectively with @code{pragma
Warnigns (Off)} or globally with compiler switch @code{-gnatwL}.
@node Dynamic Elaboration Model in GNAT,Static Elaboration Model in GNAT,Common Elaboration-model Traits,Elaboration Order Handling in GNAT @node ABE Diagnostics,SPARK Diagnostics,Mixing Elaboration Models,Elaboration Order Handling in GNAT
@anchor{gnat_ugn/elaboration_order_handling_in_gnat dynamic-elaboration-model-in-gnat}@anchor{239}@anchor{gnat_ugn/elaboration_order_handling_in_gnat id8}@anchor{23a} @anchor{gnat_ugn/elaboration_order_handling_in_gnat abe-diagnostics}@anchor{239}@anchor{gnat_ugn/elaboration_order_handling_in_gnat id8}@anchor{23a}
@section Dynamic Elaboration Model in GNAT @section ABE Diagnostics
The dynamic model assumes that all code within all units in a partition is GNAT performs extensive diagnostics on a unit-by-unit basis for all scenarios
elaboration code. As a result, run-time checks are installed for each scenario that invoke internal targets, regardless of whether the dynamic, SPARK, or
regardless of whether the target is internal or external. The checks can be static model is in effect.
suppressed using pragma @code{Suppress (Elaboration_Check)}. This behavior is
identical to that specified by the Ada Reference Manual. The following example
showcases run-time checks installed by GNAT to verify the elaboration state of
package @code{Dynamic_Model}.
@example Note that GNAT emits warnings rather than hard errors whenever it encounters an
with Server; elaboration problem. This is because the elaboration model in effect may be too
package body Dynamic_Model is conservative, or a particular scenario may not be invoked due conditional
procedure API is execution. The warnings can be suppressed selectively with @code{pragma Warnings
begin (Off)} or globally with compiler switch @code{-gnatwL}.
...
end API;
<check that the body of Server.Gen is elaborated> A @emph{guaranteed ABE} arises when the body of a target is not elaborated early
package Inst is new Server.Gen; enough, and causes @emph{all} scenarios that directly invoke the target to fail.
T : Server.Task_Type; @quotation
begin @example
<check that the body of Server.Task_Type is elaborated> package body Guaranteed_ABE is
function ABE return Integer;
<check that the body of Server.Proc is elaborated> Val : constant Integer := ABE;
Server.Proc;
end Dynamic_Model;
@end example
The checks verify that the body of a target has been successfully elaborated function ABE return Integer is
before a scenario activates, calls, or instantiates a target. begin
...
end ABE;
end Guaranteed_ABE;
@end example
@end quotation
Note that no scenario within package @code{Dynamic_Model} calls procedure @code{API}. In the example above, the elaboration of @code{Guaranteed_ABE}'s body elaborates
In fact, procedure @code{API} may not be invoked by elaboration code within the the declaration of @code{Val}. This invokes function @code{ABE}, however the body of
partition, however the dynamic model assumes that this can happen. @code{ABE} has not been elaborated yet. GNAT emits the following diagnostic:
The dynamic model emits very few diagnostics, but can make suggestions on @quotation
missing @code{Elaborate} and @code{Elaborate_All} pragmas for library-level
scenarios. This information is available when compiler switch @code{-gnatel}
is in effect.
@example @example
1. with Server; 4. Val : constant Integer := ABE;
2. package body Dynamic_Model is |
3. Val : constant Integer := Server.Func; >>> warning: cannot call "ABE" before body seen
| >>> warning: Program_Error will be raised at run time
>>> info: call to "Func" during elaboration
>>> info: missing pragma "Elaborate_All" for unit "Server"
4. end Dynamic_Model;
@end example @end example
@end quotation
@node Static Elaboration Model in GNAT,SPARK Elaboration Model in GNAT,Dynamic Elaboration Model in GNAT,Elaboration Order Handling in GNAT A @emph{conditional ABE} arises when the body of a target is not elaborated early
@anchor{gnat_ugn/elaboration_order_handling_in_gnat static-elaboration-model-in-gnat}@anchor{23b}@anchor{gnat_ugn/elaboration_order_handling_in_gnat id9}@anchor{23c} enough, and causes @emph{some} scenarios that directly invoke the target to fail.
@section Static Elaboration Model in GNAT
In contrast to the dynamic model, the static model is more precise in its
analysis of elaboration code. The model makes a clear distinction between
internal and external targets, and resorts to different diagnostics and
run-time checks based on the nature of the target.
@itemize *
@item
@emph{Internal targets}
The static model performs extensive diagnostics on scenarios which elaborate @quotation
or execute internal targets. The warnings resulting from these diagnostics
are enabled by default, but can be suppressed selectively with @code{pragma
Warnings (Off)} or globally with compiler switch @code{-gnatwL}.
@example @example
1. package body Static_Model is 1. package body Conditional_ABE is
2. generic 2. procedure Force_Body is null;
3. with function Func return Integer; 3.
4. package Gen is 4. generic
5. Val : constant Integer := Func; 5. with function Func return Integer;
6. end Gen; 6. package Gen is
7. 7. Val : constant Integer := Func;
8. function ABE return Integer; 8. end Gen;
9. 9.
10. function Cause_ABE return Boolean is 10. function ABE return Integer;
11. package Inst is new Gen (ABE); 11.
| 12. function Cause_ABE return Boolean is
>>> warning: in instantiation at line 5 13. package Inst is new Gen (ABE);
>>> warning: cannot call "ABE" before body seen 14. begin
>>> warning: Program_Error may be raised at run time 15. ...
>>> warning: body of unit "Static_Model" elaborated 16. end Cause_ABE;
>>> warning: function "Cause_ABE" called at line 16
>>> warning: function "ABE" called at line 5, instance at line 11
12. begin
13. ...
14. end Cause_ABE;
15.
16. Val : constant Boolean := Cause_ABE;
17. 17.
18. function ABE return Integer is 18. Val : constant Boolean := Cause_ABE;
19. begin 19.
20. ... 20. function ABE return Integer is
21. end ABE; 21. begin
22. end Static_Model; 22. ...
23. end ABE;
24.
25. Safe : constant Boolean := Cause_ABE;
26. end Conditional_ABE;
@end example @end example
@end quotation
The example above illustrates an ABE problem within package @code{Static_Model}, In the example above, the elaboration of package body @code{Conditional_ABE}
which is hidden by several layers of indirection. The elaboration of package elaborates the declaration of @code{Val}. This invokes function @code{Cause_ABE},
body @code{Static_Model} elaborates the declaration of @code{Val}. This invokes which instantiates generic unit @code{Gen} as @code{Inst}. The elaboration of
function @code{Cause_ABE}, which instantiates generic unit @code{Gen} as @code{Inst}. @code{Inst} invokes function @code{ABE}, however the body of @code{ABE} has not been
The elaboration of @code{Inst} invokes function @code{ABE}, however the body of elaborated yet. GNAT emits the following diagnostic:
@code{ABE} has not been elaborated yet.
@item
@emph{External targets}
The static model installs run-time checks to verify the elaboration status @quotation
of server targets only when the scenario that elaborates or executes that
target is part of the elaboration code of the client unit. The checks can be
suppressed using pragma @code{Suppress (Elaboration_Check)}.
@example @example
with Server; 13. package Inst is new Gen (ABE);
package body Static_Model is
generic
with function Func return Integer;
package Gen is
Val : constant Integer := Func;
end Gen;
function Call_Func return Boolean is
<check that the body of Server.Func is elaborated>
package Inst is new Gen (Server.Func);
begin
...
end Call_Func;
Val : constant Boolean := Call_Func;
end Static_Model;
@end example
In the example above, the elaboration of package body @code{Static_Model}
elaborates the declaration of @code{Val}. This invokes function @code{Call_Func},
which instantiates generic unit @code{Gen} as @code{Inst}. The elaboration of
@code{Inst} invokes function @code{Server.Func}. Since @code{Server.Func} is an
external target, GNAT installs a run-time check to verify that its body has
been elaborated.
In addition to checks, the static model installs implicit @code{Elaborate} and
@code{Elaborate_All} pragmas to guarantee safe elaboration use of server units.
This information is available when compiler switch @code{-gnatel} is in
effect.
@example
1. with Server;
2. package body Static_Model is
3. generic
4. with function Func return Integer;
5. package Gen is
6. Val : constant Integer := Func;
7. end Gen;
8.
9. function Call_Func return Boolean is
10. package Inst is new Gen (Server.Func);
| |
>>> info: instantiation of "Gen" during elaboration >>> warning: in instantiation at line 7
>>> info: in instantiation at line 6 >>> warning: cannot call "ABE" before body seen
>>> info: call to "Func" during elaboration >>> warning: Program_Error may be raised at run time
>>> info: in instantiation at line 6 >>> warning: body of unit "Conditional_ABE" elaborated
>>> info: implicit pragma "Elaborate_All" generated for unit "Server" >>> warning: function "Cause_ABE" called at line 18
>>> info: body of unit "Static_Model" elaborated >>> warning: function "ABE" called at line 7, instance at line 13
>>> info: function "Call_Func" called at line 15
>>> info: function "Func" called at line 6, instance at line 10
11. begin
12. ...
13. end Call_Func;
14.
15. Val : constant Boolean := Call_Func;
|
>>> info: call to "Call_Func" during elaboration
16. end Static_Model;
@end example @end example
@end quotation
In the example above, the elaboration of package body @code{Static_Model} Note that the same ABE problem does not occur with the elaboration of
elaborates the declaration of @code{Val}. This invokes function @code{Call_Func}, declaration @code{Safe} because the body of function @code{ABE} has already been
which instantiates generic unit @code{Gen} as @code{Inst}. The elaboration of elaborated at that point.
@code{Inst} invokes function @code{Server.Func}. Since @code{Server.Func} is an
external target, GNAT installs an implicit @code{Elaborate_All} pragma for unit
@code{Server}. The pragma guarantees that both the spec and body of @code{Server},
along with any additional dependencies that @code{Server} may require, are
elaborated prior to the body of @code{Static_Model}.
@end itemize
@node SPARK Elaboration Model in GNAT,Legacy Elaboration Model in GNAT,Static Elaboration Model in GNAT,Elaboration Order Handling in GNAT @node SPARK Diagnostics,Elaboration Circularities,ABE Diagnostics,Elaboration Order Handling in GNAT
@anchor{gnat_ugn/elaboration_order_handling_in_gnat id10}@anchor{23d}@anchor{gnat_ugn/elaboration_order_handling_in_gnat spark-elaboration-model-in-gnat}@anchor{23e} @anchor{gnat_ugn/elaboration_order_handling_in_gnat spark-diagnostics}@anchor{23b}@anchor{gnat_ugn/elaboration_order_handling_in_gnat id9}@anchor{23c}
@section SPARK Elaboration Model in GNAT @section SPARK Diagnostics
The SPARK model is identical to the static model in its handling of internal GNAT enforces the SPARK rules of elaboration as defined in the SPARK Reference
targets. The SPARK model, however, requires explicit @code{Elaborate} or Manual section 7.7 when compiler switch @code{-gnatd.v} is in effect. Note
@code{Elaborate_All} pragmas to be present in the program when a target is that GNAT emits hard errors whenever it encounters a violation of the SPARK
external, and compiler switch @code{-gnatd.v} is in effect. rules.
@quotation
@example @example
1. with Server; 1. with Server;
2. package body SPARK_Model with SPARK_Mode is 2. package body SPARK_Diagnostics with SPARK_Mode is
3. Val : constant Integer := Server.Func; 3. Val : constant Integer := Server.Func;
| |
>>> call to "Func" during elaboration in SPARK >>> call to "Func" during elaboration in SPARK
>>> unit "SPARK_Model" requires pragma "Elaborate_All" for "Server" >>> unit "SPARK_Diagnostics" requires pragma "Elaborate_All" for "Server"
>>> body of unit "SPARK_Model" elaborated >>> body of unit "SPARK_Model" elaborated
>>> function "Func" called at line 3 >>> function "Func" called at line 3
4. end SPARK_Model; 4. end SPARK_Diagnostics;
@end example @end example
@end quotation
@node Legacy Elaboration Model in GNAT,Mixing Elaboration Models,SPARK Elaboration Model in GNAT,Elaboration Order Handling in GNAT @node Elaboration Circularities,Resolving Elaboration Circularities,SPARK Diagnostics,Elaboration Order Handling in GNAT
@anchor{gnat_ugn/elaboration_order_handling_in_gnat legacy-elaboration-model-in-gnat}@anchor{23f} @anchor{gnat_ugn/elaboration_order_handling_in_gnat id10}@anchor{23d}@anchor{gnat_ugn/elaboration_order_handling_in_gnat elaboration-circularities}@anchor{23e}
@section Legacy Elaboration Model in GNAT @section Elaboration Circularities
The legacy elaboration model is provided for compatibility with code bases
developed with pre-18.x versions of GNAT. It is similar in functionality to
the dynamic and static models of post-18.x version of GNAT, but may differ
in terms of diagnostics and run-time checks. The legacy elaboration model is
enabled with compiler switch @code{-gnatH}.
@node Mixing Elaboration Models,Elaboration Circularities,Legacy Elaboration Model in GNAT,Elaboration Order Handling in GNAT
@anchor{gnat_ugn/elaboration_order_handling_in_gnat mixing-elaboration-models}@anchor{240}@anchor{gnat_ugn/elaboration_order_handling_in_gnat id11}@anchor{241}
@section Mixing Elaboration Models
It is possible to mix units compiled with a different elaboration model,
however the following rules must be observed:
@itemize *
@item
A client unit compiled with the dynamic model can only @emph{with} a server unit
that meets at least one of the following criteria:
@itemize -
@item An @strong{elaboration circularity} occurs whenever the elaboration of a set of
The server unit is compiled with the dynamic model. units enters a deadlocked state, where each unit is waiting for another unit
to be elaborated. This situation may be the result of improper use of @emph{with}
@item clauses, elaboration control pragmas, or invocations in elaboration code.
The server unit is a GNAT implementation unit from the Ada, GNAT,
Interfaces, or System hierarchies.
@item The following example showcases an elaboration circularity.
The server unit has pragma @code{Pure} or @code{Preelaborate}.
@item
The client unit has an explicit @code{Elaborate_All} pragma for the server
unit.
@end itemize
@end itemize
These rules ensure that elaboration checks are not omitted. If the rules are @quotation
violated, the binder emits a warning:
@example @example
warning: "x.ads" has dynamic elaboration checks and with's with B; pragma Elaborate (B);
warning: "y.ads" which has static elaboration checks package A is
end A;
@end example @end example
The warnings can be suppressed by binder switch @code{-ws}. @example
package B is
@node Elaboration Circularities,Resolving Elaboration Circularities,Mixing Elaboration Models,Elaboration Order Handling in GNAT procedure Force_Body;
@anchor{gnat_ugn/elaboration_order_handling_in_gnat id12}@anchor{242}@anchor{gnat_ugn/elaboration_order_handling_in_gnat elaboration-circularities}@anchor{243} end B;
@section Elaboration Circularities @end example
@example
with C;
package body B is
procedure Force_Body is null;
If the binder cannot find an acceptable elaboration order, it outputs detailed Elab : constant Integer := C.Func;
diagnostics describing an @strong{elaboration circularity}. end B;
@end example
@example @example
package Server is package C is
function Func return Integer; function Func return Integer;
end Server; end C;
@end example @end example
@example @example
with Client; with A;
package body Server is package body C is
function Func return Integer is function Func return Integer is
begin begin
... ...
end Func; end Func;
end Server; end C;
@end example @end example
@end quotation
@example The binder emits the following diagnostic:
with Server;
package Client is
Val : constant Integer := Server.Func;
end Client;
@end example
@example @quotation
with Client;
procedure Main is begin null; end Main;
@end example
@example @example
error: elaboration circularity detected error: Elaboration circularity detected
info: "server (body)" must be elaborated before "client (spec)" info:
info: reason: implicit Elaborate_All in unit "client (spec)" info: Reason:
info: recompile "client (spec)" with -gnatel for full details info:
info: "server (body)" info: unit "a (spec)" depends on its own elaboration
info: must be elaborated along with its spec: info:
info: "server (spec)" info: Circularity:
info: which is withed by: info:
info: "client (spec)" info: unit "a (spec)" has with clause and pragma Elaborate for unit "b (spec)"
info: "client (spec)" must be elaborated before "server (body)" info: unit "b (body)" is in the closure of pragma Elaborate
info: reason: with clause info: unit "b (body)" invokes a construct of unit "c (body)" at elaboration time
info: unit "c (body)" has with clause for unit "a (spec)"
info:
info: Suggestions:
info:
info: remove pragma Elaborate for unit "b (body)" in unit "a (spec)"
info: use the dynamic elaboration model (compiler switch -gnatE)
@end example @end example
@end quotation
In the example above, @code{Client} must be elaborated prior to @code{Main} by virtue The diagnostic consist of the following sections:
of a @emph{with} clause. The elaboration of @code{Client} invokes @code{Server.Func}, and
static model generates an implicit @code{Elaborate_All} pragma for @code{Server}. The
pragma implies that both the spec and body of @code{Server}, along with any units
they @emph{with}, must be elaborated prior to @code{Client}. However, @code{Server}'s body
@emph{with}s @code{Client}, implying that @code{Client} must be elaborated prior to
@code{Server}. The end result is that @code{Client} must be elaborated prior to
@code{Client}, and this leads to a circularity.
@node Resolving Elaboration Circularities,Resolving Task Issues,Elaboration Circularities,Elaboration Order Handling in GNAT
@anchor{gnat_ugn/elaboration_order_handling_in_gnat id13}@anchor{244}@anchor{gnat_ugn/elaboration_order_handling_in_gnat resolving-elaboration-circularities}@anchor{245}
@section Resolving Elaboration Circularities
When faced with an elaboration circularity, a programmer has several options
available.
@itemize * @itemize *
@item @item
@emph{Fix the program} Reason
The most desirable option from the point of view of long-term maintenance This section provides a short explanation describing why the set of units
is to rearrange the program so that the elaboration problems are avoided. could not be ordered.
One useful technique is to place the elaboration code into separate child
packages. Another is to move some of the initialization code to explicitly
invoked subprograms, where the program controls the order of initialization
explicitly. Although this is the most desirable option, it may be impractical
and involve too much modification, especially in the case of complex legacy
code.
@item @item
@emph{Switch to more permissive elaboration model} Circularity
If the compilation was performed using the static model, enable the dynamic This section enumerates the units comprising the deadlocked set, along with
model with compiler switch @code{-gnatE}. GNAT will no longer generate their interdependencies.
implicit @code{Elaborate} and @code{Elaborate_All} pragmas, resulting in a behavior
identical to that specified by the Ada Reference Manual. The binder will
generate an executable program that may or may not raise @code{Program_Error},
and it is the programmer's responsibility to ensure that it does not raise
@code{Program_Error}.
If the compilation was performed using a post-18.x version of GNAT, consider @item
using the legacy elaboration model, in the following order: Suggestions
This section enumerates various tactics for eliminating the circularity.
@end itemize
@itemize - @node Resolving Elaboration Circularities,Elaboration-related Compiler Switches,Elaboration Circularities,Elaboration Order Handling in GNAT
@anchor{gnat_ugn/elaboration_order_handling_in_gnat id11}@anchor{23f}@anchor{gnat_ugn/elaboration_order_handling_in_gnat resolving-elaboration-circularities}@anchor{240}
@section Resolving Elaboration Circularities
@item
Use the relaxed static elaboration model, with compiler switch
@code{-gnatJ}.
@item The most desirable option from the point of view of long-term maintenance is to
Use the relaxed dynamic elaboration model, with compiler switches rearrange the program so that the elaboration problems are avoided. One useful
@code{-gnatE} @code{-gnatJ}. technique is to place the elaboration code into separate child packages.
Another is to move some of the initialization code to explicitly invoked
subprograms, where the program controls the order of initialization explicitly.
Although this is the most desirable option, it may be impractical and involve
too much modification, especially in the case of complex legacy code.
@item When faced with an elaboration circularity, the programmer should also consider
Use the legacy static elaboration model, with compiler switch the tactics given in the suggestions section of the circularity diagnostic.
@code{-gnatH}. Depending on the units involved in the circularity, their @emph{with} clauses,
purity, preelaborability, presence of elaboration control pragmas and
@item invocations at elaboration time, the binder may suggest one or more of the
Use the legacy dynamic elaboration model, with compiler switches following tactics to eliminate the circularity:
@code{-gnatE} @code{-gnatH}.
@end itemize
@item
@emph{Suppress all elaboration checks}
The drawback of run-time checks is that they generate overhead at run time, @itemize *
both in space and time. If the programmer is absolutely sure that a program
will not raise an elaboration-related @code{Program_Error}, then using the
pragma @code{Suppress (Elaboration_Check)} globally (as a configuration pragma)
will eliminate all run-time checks.
@item @item
@emph{Suppress elaboration checks selectively} Pragma Elaborate elimination
If a scenario cannot possibly lead to an elaboration @code{Program_Error}, @example
and the binder nevertheless complains about implicit @code{Elaborate} and remove pragma Elaborate for unit "..." in unit "..."
@code{Elaborate_All} pragmas that lead to elaboration circularities, it @end example
is possible to suppress the generation of implicit @code{Elaborate} and
@code{Elaborate_All} pragmas, as well as run-time checks. Clearly this can This tactic is suggested when the binder has determine that pragma
be unsafe, and it is the responsibility of the programmer to make sure @code{Elaborate}
that the resulting program has no elaboration anomalies. Pragma
@code{Suppress (Elaboration_Check)} can be used with different levels of
granularity to achieve these effects.
@itemize - @itemize -
@item @item
@emph{Target suppression} Prevents a set of units from being elaborated.
When the pragma is placed in a declarative part, without a second argument @item
naming an entity, it will suppress implicit @code{Elaborate} and The removal of the pragma will not eliminate the semantic effects of the
@code{Elaborate_All} pragma generation, as well as run-time checks, on all pragma. In other words, the argument of the pragma will still be elaborated
targets within the region. prior to the unit containing the pragma.
@example
package Range_Suppress is
pragma Suppress (Elaboration_Check);
function Func return Integer; @item
The removal of the pragma will enable the successful ordering of the units.
@end itemize
generic The programmer should remove the pragma as advised, and rebuild the program.
procedure Gen;
pragma Unsuppress (Elaboration_Check); @item
Pragma Elaborate_All elimination
task type Tsk; @example
end Range_Suppress; remove pragma Elaborate_All for unit "..." in unit "..."
@end example @end example
In the example above, a pair of Suppress/Unsuppress pragmas define a region This tactic is suggested when the binder has determined that pragma
of suppression within package @code{Range_Suppress}. As a result, no implicit @code{Elaborate_All}
@code{Elaborate} and @code{Elaborate_All} pragmas, nor any run-time checks, will
be generated by callers of @code{Func} and instantiators of @code{Gen}. Note that
task type @code{Tsk} is not within this region.
An alternative to the region-based suppression is to use multiple
@code{Suppress} pragmas with arguments naming specific entities for which
elaboration checks should be suppressed:
@example @itemize -
package Range_Suppress is
function Func return Integer;
pragma Suppress (Elaboration_Check, Func);
generic
procedure Gen;
pragma Suppress (Elaboration_Check, Gen);
task type Tsk;
end Range_Suppress;
@end example
@item @item
@emph{Scenario suppression} Prevents a set of units from being elaborated.
When the pragma @code{Suppress} is placed in a declarative or statement @item
part, without an entity argument, it will suppress implicit @code{Elaborate} The removal of the pragma will not eliminate the semantic effects of the
and @code{Elaborate_All} pragma generation, as well as run-time checks, on pragma. In other words, the argument of the pragma along with its @emph{with}
all scenarios within the region. closure will still be elaborated prior to the unit containing the pragma.
@example
with Server;
package body Range_Suppress is
pragma Suppress (Elaboration_Check);
function Func return Integer is @item
begin The removal of the pragma will enable the successful ordering of the units.
return Server.Func; @end itemize
end Func;
procedure Gen is The programmer should remove the pragma as advised, and rebuild the program.
begin
Server.Proc;
end Gen;
pragma Unsuppress (Elaboration_Check); @item
Pragma Elaborate_All downgrade
task body Tsk is @example
begin change pragma Elaborate_All for unit "..." to Elaborate in unit "..."
Server.Proc;
end Tsk;
end Range_Suppress;
@end example @end example
In the example above, a pair of Suppress/Unsuppress pragmas define a region This tactic is always suggested with the pragma @code{Elaborate_All} elimination
of suppression within package body @code{Range_Suppress}. As a result, the tactic. It offers a different alernative of guaranteeing that the argument of
calls to @code{Server.Func} in @code{Func} and @code{Server.Proc} in @code{Gen} will the pragma will still be elaborated prior to the unit containing the pragma.
not generate any implicit @code{Elaborate} and @code{Elaborate_All} pragmas or
run-time checks.
@end itemize
@end itemize
@node Resolving Task Issues,Elaboration-related Compiler Switches,Resolving Elaboration Circularities,Elaboration Order Handling in GNAT The programmer should update the pragma as advised, and rebuild the program.
@anchor{gnat_ugn/elaboration_order_handling_in_gnat id14}@anchor{246}@anchor{gnat_ugn/elaboration_order_handling_in_gnat resolving-task-issues}@anchor{247}
@section Resolving Task Issues
@item
Pragma Elaborate_Body elimination
The model of execution in Ada dictates that elaboration must first take place, @example
and only then can the main program be started. Tasks which are activated during remove pragma Elaborate_Body in unit "..."
elaboration violate this model and may lead to serious concurrent problems at @end example
elaboration time.
A task can be activated in two different ways: This tactic is suggested when the binder has determined that pragma
@code{Elaborate_Body}
@itemize * @itemize -
@item @item
The task is created by an allocator in which case it is activated immediately Prevents a set of units from being elaborated.
after the allocator is evaluated.
@item @item
The task is declared at the library level or within some nested master in The removal of the pragma will enable the successful ordering of the units.
which case it is activated before starting execution of the statement
sequence of the master defining the task.
@end itemize @end itemize
Since the elaboration of a partition is performed by the environment task Note that the binder cannot determine whether the pragma is required for
servicing that partition, any tasks activated during elaboration may be in other purposes, such as guaranteeing the initialization of a variable
a race with the environment task, and lead to unpredictable state and behavior. declared in the spec by elaboration code in the body.
The static model seeks to avoid such interactions by assuming that all code in
the task body is executed at elaboration time, if the task was activated by
elaboration code.
@example
package Decls is
task Lib_Task is
entry Start;
end Lib_Task;
type My_Int is new Integer; The programmer should remove the pragma as advised, and rebuild the program.
function Ident (M : My_Int) return My_Int; @item
end Decls; Use of dynamic elaboration model
@end example
@example
with Utils;
package body Decls is
task body Lib_Task is
begin
accept Start;
Utils.Put_Val (2);
end Lib_Task;
function Ident (M : My_Int) return My_Int is
begin
return M;
end Ident;
end Decls;
@end example
@example
with Decls;
package Utils is
procedure Put_Val (Arg : Decls.My_Int);
end Utils;
@end example
@example @example
with Ada.Text_IO; use Ada.Text_IO; use the dynamic elaboration model (compiler switch -gnatE)
package body Utils is
procedure Put_Val (Arg : Decls.My_Int) is
begin
Put_Line (Arg'Img);
end Put_Val;
end Utils;
@end example @end example
@example This tactic is suggested when the binder has determined that an invocation at
with Decls; elaboration time
procedure Main is
begin
Decls.Lib_Task.Start;
end Main;
@end example
When the above example is compiled with the static model, an elaboration
circularity arises:
@example @itemize -
error: elaboration circularity detected
info: "decls (body)" must be elaborated before "decls (body)"
info: reason: implicit Elaborate_All in unit "decls (body)"
info: recompile "decls (body)" with -gnatel for full details
info: "decls (body)"
info: must be elaborated along with its spec:
info: "decls (spec)"
info: which is withed by:
info: "utils (spec)"
info: which is withed by:
info: "decls (body)"
@end example
In the above example, @code{Decls} must be elaborated prior to @code{Main} by virtue @item
of a with clause. The elaboration of @code{Decls} activates task @code{Lib_Task}. The Prevents a set of units from being elaborated.
static model conservatibely assumes that all code within the body of
@code{Lib_Task} is executed, and generates an implicit @code{Elaborate_All} pragma
for @code{Units} due to the call to @code{Utils.Put_Val}. The pragma implies that
both the spec and body of @code{Utils}, along with any units they @emph{with},
must be elaborated prior to @code{Decls}. However, @code{Utils}'s spec @emph{with}s
@code{Decls}, implying that @code{Decls} must be elaborated before @code{Utils}. The end
result is that @code{Utils} must be elaborated prior to @code{Utils}, and this
leads to a circularity.
In reality, the example above will not exhibit an ABE problem at run time. @item
When the body of task @code{Lib_Task} is activated, execution will wait for entry The use of the dynamic model will enable the successful ordering of the
@code{Start} to be accepted, and the call to @code{Utils.Put_Val} will not take place units.
at elaboration time. Task @code{Lib_Task} will resume its execution after the main @end itemize
program is executed because @code{Main} performs a rendezvous with
@code{Lib_Task.Start}, and at that point all units have already been elaborated.
As a result, the static model may seem overly conservative, partly because it
does not take control and data flow into account.
When faced with a task elaboration circularity, a programmer has several The programmer has two options:
options available:
@itemize * @itemize -
@item @item
@emph{Use the dynamic model} Determine the units involved in the invocation using the detailed
invocation information, and add compiler switch @code{-gnatE} to the
The dynamic model does not generate implicit @code{Elaborate} and compilation arguments of selected files only. This approach will yield
@code{Elaborate_All} pragmas. Instead, it will install checks prior to every safer elaboration orders compared to the other option because it will
call in the example above, thus verifying the successful elaboration of minimize the opportunities presented to the dynamic model for ignoring
@code{Utils.Put_Val} in case the call to it takes place at elaboration time. invocations.
The dynamic model is enabled with compiler switch @code{-gnatE}.
@item @item
@emph{Isolate the tasks} Add compiler switch @code{-gnatE} to the general compilation arguments.
@end itemize
Relocating tasks in their own separate package could decouple them from @item
dependencies that would otherwise cause an elaboration circularity. The Use of detailed invocation information
example above can be rewritten as follows:
@example @example
package Decls1 is -- new use detailed invocation information (compiler switch -gnatd_F)
task Lib_Task is
entry Start;
end Lib_Task;
end Decls1;
@end example @end example
@example This tactic is always suggested with the use of the dynamic model tactic. It
with Utils; causes the circularity section of the circularity diagnostic to describe the
package body Decls1 is -- new flow of elaboration code from a unit to a unit, enumerating all such paths in
task body Lib_Task is the process.
begin
accept Start;
Utils.Put_Val (2);
end Lib_Task;
end Decls1;
@end example
@example The programmer should analyze this information to determine which units
package Decls2 is -- new should be compiled with the dynamic model.
type My_Int is new Integer;
function Ident (M : My_Int) return My_Int;
end Decls2;
@end example
@example @item
with Utils; Forced dependency elimination
package body Decls2 is -- new
function Ident (M : My_Int) return My_Int is
begin
return M;
end Ident;
end Decls2;
@end example
@example @example
with Decls2; remove the dependency of unit "..." on unit "..." from the argument of switch -f
package Utils is
procedure Put_Val (Arg : Decls2.My_Int);
end Utils;
@end example @end example
@example This tactic is suggested when the binder has determined that a dependency
with Ada.Text_IO; use Ada.Text_IO; present in the forced delboration order file indicated by binder switch
package body Utils is @code{-f}
procedure Put_Val (Arg : Decls2.My_Int) is
begin
Put_Line (Arg'Img);
end Put_Val;
end Utils;
@end example
@example
with Decls1; @itemize -
procedure Main is
begin
Decls1.Lib_Task.Start;
end Main;
@end example
@item @item
@emph{Declare the tasks} Prevents a set of units from being elaborated.
The original example uses a single task declaration for @code{Lib_Task}. An @item
explicit task type declaration and a properly placed task object could avoid The removal of the dependency will enable the successful ordering of the
the dependencies that would otherwise cause an elaboration circularity. The units.
example can be rewritten as follows: @end itemize
@example The programmer should edit the forced elaboration order file, remove the
package Decls is dependency, and rebind the program.
task type Lib_Task is -- new
entry Start;
end Lib_Task;
type My_Int is new Integer; @item
All forced dependency elimination
function Ident (M : My_Int) return My_Int; @example
end Decls; remove switch -f
@end example @end example
@example This tactic is suggested in case editing the forced elaboration order file is
with Utils; not an option.
package body Decls is
task body Lib_Task is
begin
accept Start;
Utils.Put_Val (2);
end Lib_Task;
function Ident (M : My_Int) return My_Int is The programmer should remove binder switch @code{-f} from the binder
begin arguments, and rebind.
return M;
end Ident;
end Decls;
@end example
@example @item
with Decls; Multiple circularities diagnostic
package Utils is
procedure Put_Val (Arg : Decls.My_Int);
end Utils;
@end example
@example @example
with Ada.Text_IO; use Ada.Text_IO; diagnose all circularities (binder switch -d_C)
package body Utils is
procedure Put_Val (Arg : Decls.My_Int) is
begin
Put_Line (Arg'Img);
end Put_Val;
end Utils;
@end example @end example
@example By default, the binder will diagnose only the highest precedence circularity.
with Decls; If the program contains multiple circularities, the binder will suggest the
package Obj_Decls is -- new use of binder switch @code{-d_C} in order to obtain the diagnostics of all
Task_Obj : Decls.Lib_Task; circularities.
end Obj_Decls;
@end example
@example The programmer should add binder switch @code{-d_C} to the binder
with Obj_Decls; arguments, and rebind.
procedure Main is @end itemize
begin
Obj_Decls.Task_Obj.Start; -- new
end Main;
@end example
@item If none of the tactics suggested by the binder eliminate the elaboration
@emph{Use restriction No_Entry_Calls_In_Elaboration_Code} circularity, the programmer should consider using one of the legacy elaboration
models, in the following order:
The issue exhibited in the original example under this section revolves
around the body of @code{Lib_Task} blocking on an accept statement. There is
no rule to prevent elaboration code from performing entry calls, however in
practice this is highly unusual. In addition, the pattern of starting tasks
at elaboration time and then immediately blocking on accept or select
statements is quite common.
If a programmer knows that elaboration code will not perform any entry @itemize *
calls, then the programmer can indicate that the static model should not
process the remainder of a task body once an accept or select statement has
been encountered. This behavior can be specified by a configuration pragma:
@example @item
pragma Restrictions (No_Entry_Calls_In_Elaboration_Code); Use the pre-20.x legacy elaboration order model, with binder switch
@end example @code{-H}.
In addition to the change in behavior with respect to task bodies, the @item
static model will verify that no entry calls take place at elaboration time. Use both pre-18.x and pre-20.x legacy elaboration models, with compiler
switch @code{-gnatH} and binder switch @code{-H}.
@item
Use the relaxed static elaboration model, with compiler switches
@code{-gnatH} @code{-gnatJ} and binder switch @code{-H}.
@item
Use the relaxed dynamic elaboration model, with compiler switches
@code{-gnatH} @code{-gnatJ} @code{-gnatE} and binder switch
@code{-H}.
@end itemize @end itemize
@node Elaboration-related Compiler Switches,Summary of Procedures for Elaboration Control,Resolving Task Issues,Elaboration Order Handling in GNAT @node Elaboration-related Compiler Switches,Summary of Procedures for Elaboration Control,Resolving Elaboration Circularities,Elaboration Order Handling in GNAT
@anchor{gnat_ugn/elaboration_order_handling_in_gnat elaboration-related-compiler-switches}@anchor{248}@anchor{gnat_ugn/elaboration_order_handling_in_gnat id15}@anchor{249} @anchor{gnat_ugn/elaboration_order_handling_in_gnat id12}@anchor{241}@anchor{gnat_ugn/elaboration_order_handling_in_gnat elaboration-related-compiler-switches}@anchor{242}
@section Elaboration-related Compiler Switches @section Elaboration-related Compiler Switches
...@@ -28847,7 +28606,7 @@ the elaboration order chosen by the binder. ...@@ -28847,7 +28606,7 @@ the elaboration order chosen by the binder.
Dynamic elaboration checking mode enabled Dynamic elaboration checking mode enabled
When this switch is in effect, GNAT activates the dynamic elaboration model. When this switch is in effect, GNAT activates the dynamic model.
@end table @end table
@geindex -gnatel (gnat) @geindex -gnatel (gnat)
...@@ -28859,6 +28618,10 @@ When this switch is in effect, GNAT activates the dynamic elaboration model. ...@@ -28859,6 +28618,10 @@ When this switch is in effect, GNAT activates the dynamic elaboration model.
Turn on info messages on generated Elaborate[_All] pragmas Turn on info messages on generated Elaborate[_All] pragmas
This switch is only applicable to the pre-20.x legacy elaboration models.
The post-20.x elaboration model no longer relies on implicitly generated
@code{Elaborate} and @code{Elaborate_All} pragmas to order units.
When this switch is in effect, GNAT will emit the following supplementary When this switch is in effect, GNAT will emit the following supplementary
information depending on the elaboration model in effect. information depending on the elaboration model in effect.
...@@ -28874,7 +28637,7 @@ all library-level scenarios within the partition. ...@@ -28874,7 +28637,7 @@ all library-level scenarios within the partition.
@item @item
@emph{Static model} @emph{Static model}
GNAT will indicate all scenarios executed during elaboration. In addition, GNAT will indicate all scenarios invoked during elaboration. In addition,
it will provide detailed traceback when an implicit @code{Elaborate} or it will provide detailed traceback when an implicit @code{Elaborate} or
@code{Elaborate_All} pragma is generated. @code{Elaborate_All} pragma is generated.
...@@ -29008,7 +28771,7 @@ checks. The example above will still fail at run time with an ABE. ...@@ -29008,7 +28771,7 @@ checks. The example above will still fail at run time with an ABE.
@end table @end table
@node Summary of Procedures for Elaboration Control,Inspecting the Chosen Elaboration Order,Elaboration-related Compiler Switches,Elaboration Order Handling in GNAT @node Summary of Procedures for Elaboration Control,Inspecting the Chosen Elaboration Order,Elaboration-related Compiler Switches,Elaboration Order Handling in GNAT
@anchor{gnat_ugn/elaboration_order_handling_in_gnat summary-of-procedures-for-elaboration-control}@anchor{24a}@anchor{gnat_ugn/elaboration_order_handling_in_gnat id16}@anchor{24b} @anchor{gnat_ugn/elaboration_order_handling_in_gnat id13}@anchor{243}@anchor{gnat_ugn/elaboration_order_handling_in_gnat summary-of-procedures-for-elaboration-control}@anchor{244}
@section Summary of Procedures for Elaboration Control @section Summary of Procedures for Elaboration Control
...@@ -29036,13 +28799,8 @@ as their origins. Elaboration warnings are enabled with compiler switch ...@@ -29036,13 +28799,8 @@ as their origins. Elaboration warnings are enabled with compiler switch
@code{-gnatwl}. @code{-gnatwl}.
@item @item
Use switch @code{-gnatel} to obtain messages on generated implicit Cosider the tactics given in the suggestions section of the circularity
@code{Elaborate} and @code{Elaborate_All} pragmas. The trace information could diagnostic.
indicate why a server unit must be elaborated prior to a client unit.
@item
If the warnings produced by the static model indicate that a task is
involved, consider the options in section @ref{246,,Resolving Task Issues}.
@item @item
If none of the steps outlined above resolve the circularity, use a more If none of the steps outlined above resolve the circularity, use a more
...@@ -29052,28 +28810,26 @@ permissive elaboration model, in the following order: ...@@ -29052,28 +28810,26 @@ permissive elaboration model, in the following order:
@itemize - @itemize -
@item @item
Use the dynamic elaboration model, with compiler switch @code{-gnatE}. Use the pre-20.x legacy elaboration order model, with binder switch
@code{-H}.
@item @item
Use the legacy static elaboration model, with compiler switch Use both pre-18.x and pre-20.x legacy elaboration models, with compiler
@code{-gnatH}. switch @code{-gnatH} and binder switch @code{-H}.
@item @item
Use the legacy dynamic elaboration model, with compiler switches Use the relaxed static elaboration model, with compiler switches
@code{-gnatH} @code{-gnatE}. @code{-gnatH} @code{-gnatJ} and binder switch @code{-H}.
@item @item
Use the relaxed legacy static elaboration model, with compiler switches Use the relaxed dynamic elaboration model, with compiler switches
@code{-gnatH} @code{-gnatJ}. @code{-gnatH} @code{-gnatJ} @code{-gnatE} and binder switch
@code{-H}.
@item
Use the relaxed legacy dynamic elaboration model, with compiler switches
@code{-gnatH} @code{-gnatJ} @code{-gnatE}.
@end itemize @end itemize
@end itemize @end itemize
@node Inspecting the Chosen Elaboration Order,,Summary of Procedures for Elaboration Control,Elaboration Order Handling in GNAT @node Inspecting the Chosen Elaboration Order,,Summary of Procedures for Elaboration Control,Elaboration Order Handling in GNAT
@anchor{gnat_ugn/elaboration_order_handling_in_gnat inspecting-the-chosen-elaboration-order}@anchor{24c}@anchor{gnat_ugn/elaboration_order_handling_in_gnat id17}@anchor{24d} @anchor{gnat_ugn/elaboration_order_handling_in_gnat id14}@anchor{245}@anchor{gnat_ugn/elaboration_order_handling_in_gnat inspecting-the-chosen-elaboration-order}@anchor{246}
@section Inspecting the Chosen Elaboration Order @section Inspecting the Chosen Elaboration Order
...@@ -29083,6 +28839,8 @@ elaboration order appears as a sequence of calls to @code{Elab_Body} and ...@@ -29083,6 +28839,8 @@ elaboration order appears as a sequence of calls to @code{Elab_Body} and
@code{Elab_Spec}, interspersed with assignments to @cite{Exxx} which indicates that a @code{Elab_Spec}, interspersed with assignments to @cite{Exxx} which indicates that a
particular unit is elaborated. For example: particular unit is elaborated. For example:
@quotation
@example @example
System.Soft_Links'Elab_Body; System.Soft_Links'Elab_Body;
E14 := True; E14 := True;
...@@ -29118,10 +28876,13 @@ Ada.Text_Io'Elab_Spec; ...@@ -29118,10 +28876,13 @@ Ada.Text_Io'Elab_Spec;
Ada.Text_Io'Elab_Body; Ada.Text_Io'Elab_Body;
E07 := True; E07 := True;
@end example @end example
@end quotation
Note also binder switch @code{-l}, which outputs the chosen elaboration Note also binder switch @code{-l}, which outputs the chosen elaboration
order and provides a more readable form of the above: order and provides a more readable form of the above:
@quotation
@example @example
ada (spec) ada (spec)
interfaces (spec) interfaces (spec)
...@@ -29208,9 +28969,10 @@ ada.text_io (body) ...@@ -29208,9 +28969,10 @@ ada.text_io (body)
text_io (spec) text_io (spec)
gdbstr (body) gdbstr (body)
@end example @end example
@end quotation
@node Inline Assembler,GNU Free Documentation License,Elaboration Order Handling in GNAT,Top @node Inline Assembler,GNU Free Documentation License,Elaboration Order Handling in GNAT,Top
@anchor{gnat_ugn/inline_assembler inline-assembler}@anchor{10}@anchor{gnat_ugn/inline_assembler doc}@anchor{24e}@anchor{gnat_ugn/inline_assembler id1}@anchor{24f} @anchor{gnat_ugn/inline_assembler inline-assembler}@anchor{10}@anchor{gnat_ugn/inline_assembler doc}@anchor{247}@anchor{gnat_ugn/inline_assembler id1}@anchor{248}
@chapter Inline Assembler @chapter Inline Assembler
...@@ -29269,7 +29031,7 @@ and with assembly language programming. ...@@ -29269,7 +29031,7 @@ and with assembly language programming.
@end menu @end menu
@node Basic Assembler Syntax,A Simple Example of Inline Assembler,,Inline Assembler @node Basic Assembler Syntax,A Simple Example of Inline Assembler,,Inline Assembler
@anchor{gnat_ugn/inline_assembler id2}@anchor{250}@anchor{gnat_ugn/inline_assembler basic-assembler-syntax}@anchor{251} @anchor{gnat_ugn/inline_assembler id2}@anchor{249}@anchor{gnat_ugn/inline_assembler basic-assembler-syntax}@anchor{24a}
@section Basic Assembler Syntax @section Basic Assembler Syntax
...@@ -29385,7 +29147,7 @@ Intel: Destination first; for example @code{mov eax, 4}@w{ } ...@@ -29385,7 +29147,7 @@ Intel: Destination first; for example @code{mov eax, 4}@w{ }
@node A Simple Example of Inline Assembler,Output Variables in Inline Assembler,Basic Assembler Syntax,Inline Assembler @node A Simple Example of Inline Assembler,Output Variables in Inline Assembler,Basic Assembler Syntax,Inline Assembler
@anchor{gnat_ugn/inline_assembler a-simple-example-of-inline-assembler}@anchor{252}@anchor{gnat_ugn/inline_assembler id3}@anchor{253} @anchor{gnat_ugn/inline_assembler a-simple-example-of-inline-assembler}@anchor{24b}@anchor{gnat_ugn/inline_assembler id3}@anchor{24c}
@section A Simple Example of Inline Assembler @section A Simple Example of Inline Assembler
...@@ -29534,7 +29296,7 @@ If there are no errors, @code{as} will generate an object file ...@@ -29534,7 +29296,7 @@ If there are no errors, @code{as} will generate an object file
@code{nothing.out}. @code{nothing.out}.
@node Output Variables in Inline Assembler,Input Variables in Inline Assembler,A Simple Example of Inline Assembler,Inline Assembler @node Output Variables in Inline Assembler,Input Variables in Inline Assembler,A Simple Example of Inline Assembler,Inline Assembler
@anchor{gnat_ugn/inline_assembler id4}@anchor{254}@anchor{gnat_ugn/inline_assembler output-variables-in-inline-assembler}@anchor{255} @anchor{gnat_ugn/inline_assembler id4}@anchor{24d}@anchor{gnat_ugn/inline_assembler output-variables-in-inline-assembler}@anchor{24e}
@section Output Variables in Inline Assembler @section Output Variables in Inline Assembler
...@@ -29901,7 +29663,7 @@ end Get_Flags_3; ...@@ -29901,7 +29663,7 @@ end Get_Flags_3;
@end quotation @end quotation
@node Input Variables in Inline Assembler,Inlining Inline Assembler Code,Output Variables in Inline Assembler,Inline Assembler @node Input Variables in Inline Assembler,Inlining Inline Assembler Code,Output Variables in Inline Assembler,Inline Assembler
@anchor{gnat_ugn/inline_assembler id5}@anchor{256}@anchor{gnat_ugn/inline_assembler input-variables-in-inline-assembler}@anchor{257} @anchor{gnat_ugn/inline_assembler id5}@anchor{24f}@anchor{gnat_ugn/inline_assembler input-variables-in-inline-assembler}@anchor{250}
@section Input Variables in Inline Assembler @section Input Variables in Inline Assembler
...@@ -29990,7 +29752,7 @@ _increment__incr.1: ...@@ -29990,7 +29752,7 @@ _increment__incr.1:
@end quotation @end quotation
@node Inlining Inline Assembler Code,Other Asm Functionality,Input Variables in Inline Assembler,Inline Assembler @node Inlining Inline Assembler Code,Other Asm Functionality,Input Variables in Inline Assembler,Inline Assembler
@anchor{gnat_ugn/inline_assembler id6}@anchor{258}@anchor{gnat_ugn/inline_assembler inlining-inline-assembler-code}@anchor{259} @anchor{gnat_ugn/inline_assembler id6}@anchor{251}@anchor{gnat_ugn/inline_assembler inlining-inline-assembler-code}@anchor{252}
@section Inlining Inline Assembler Code @section Inlining Inline Assembler Code
...@@ -30061,7 +29823,7 @@ movl %esi,%eax ...@@ -30061,7 +29823,7 @@ movl %esi,%eax
thus saving the overhead of stack frame setup and an out-of-line call. thus saving the overhead of stack frame setup and an out-of-line call.
@node Other Asm Functionality,,Inlining Inline Assembler Code,Inline Assembler @node Other Asm Functionality,,Inlining Inline Assembler Code,Inline Assembler
@anchor{gnat_ugn/inline_assembler other-asm-functionality}@anchor{25a}@anchor{gnat_ugn/inline_assembler id7}@anchor{25b} @anchor{gnat_ugn/inline_assembler other-asm-functionality}@anchor{253}@anchor{gnat_ugn/inline_assembler id7}@anchor{254}
@section Other @code{Asm} Functionality @section Other @code{Asm} Functionality
...@@ -30076,7 +29838,7 @@ and @code{Volatile}, which inhibits unwanted optimizations. ...@@ -30076,7 +29838,7 @@ and @code{Volatile}, which inhibits unwanted optimizations.
@end menu @end menu
@node The Clobber Parameter,The Volatile Parameter,,Other Asm Functionality @node The Clobber Parameter,The Volatile Parameter,,Other Asm Functionality
@anchor{gnat_ugn/inline_assembler the-clobber-parameter}@anchor{25c}@anchor{gnat_ugn/inline_assembler id8}@anchor{25d} @anchor{gnat_ugn/inline_assembler the-clobber-parameter}@anchor{255}@anchor{gnat_ugn/inline_assembler id8}@anchor{256}
@subsection The @code{Clobber} Parameter @subsection The @code{Clobber} Parameter
...@@ -30140,7 +29902,7 @@ Use 'register' name @code{memory} if you changed a memory location ...@@ -30140,7 +29902,7 @@ Use 'register' name @code{memory} if you changed a memory location
@end itemize @end itemize
@node The Volatile Parameter,,The Clobber Parameter,Other Asm Functionality @node The Volatile Parameter,,The Clobber Parameter,Other Asm Functionality
@anchor{gnat_ugn/inline_assembler the-volatile-parameter}@anchor{25e}@anchor{gnat_ugn/inline_assembler id9}@anchor{25f} @anchor{gnat_ugn/inline_assembler the-volatile-parameter}@anchor{257}@anchor{gnat_ugn/inline_assembler id9}@anchor{258}
@subsection The @code{Volatile} Parameter @subsection The @code{Volatile} Parameter
...@@ -30176,7 +29938,7 @@ to @code{True} only if the compiler's optimizations have created ...@@ -30176,7 +29938,7 @@ to @code{True} only if the compiler's optimizations have created
problems. problems.
@node GNU Free Documentation License,Index,Inline Assembler,Top @node GNU Free Documentation License,Index,Inline Assembler,Top
@anchor{share/gnu_free_documentation_license gnu-fdl}@anchor{1}@anchor{share/gnu_free_documentation_license doc}@anchor{260}@anchor{share/gnu_free_documentation_license gnu-free-documentation-license}@anchor{261} @anchor{share/gnu_free_documentation_license gnu-fdl}@anchor{1}@anchor{share/gnu_free_documentation_license doc}@anchor{259}@anchor{share/gnu_free_documentation_license gnu-free-documentation-license}@anchor{25a}
@chapter GNU Free Documentation License @chapter GNU Free Documentation License
......
...@@ -496,12 +496,6 @@ package body Sem_Elab is ...@@ -496,12 +496,6 @@ package body Sem_Elab is
-- actual subprograms through generic formal subprograms. As a -- actual subprograms through generic formal subprograms. As a
-- result, the calls are not recorded or processed. -- result, the calls are not recorded or processed.
-- --
-- -gnatd_G encode invocation graph in ALI files
--
-- The ABE mechanism encodes the invocation graph of the main
-- unit. This includes elaboration code, as well as invocation
-- constructs.
--
-- -gnatd_i ignore activations and calls to instances for elaboration -- -gnatd_i ignore activations and calls to instances for elaboration
-- --
-- The ABE mechanism ignores calls and task activations when they -- The ABE mechanism ignores calls and task activations when they
...@@ -12192,19 +12186,10 @@ package body Sem_Elab is ...@@ -12192,19 +12186,10 @@ package body Sem_Elab is
Main_Cunit : constant Node_Id := Cunit (Main_Unit); Main_Cunit : constant Node_Id := Cunit (Main_Unit);
begin 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.
if not Debug_Flag_Underscore_GG then
return False;
-- Nothing to do when compiling for GNATprove because the invocation -- Nothing to do when compiling for GNATprove because the invocation
-- graph is not needed. -- graph is not needed.
elsif GNATprove_Mode then if GNATprove_Mode then
return False; return False;
-- Nothing to do when the compilation will not produce an ALI file -- Nothing to do when the compilation will not produce an ALI file
......
...@@ -353,14 +353,11 @@ package body Switch.B is ...@@ -353,14 +353,11 @@ package body Switch.B is
Ptr := Ptr + 1; Ptr := Ptr + 1;
Usage_Requested := True; Usage_Requested := True;
-- ??? Enable the following code when switching from the old to the
-- new elaboration-order mechanism.
-- Processing for H switch -- Processing for H switch
-- when 'H' => when 'H' =>
-- Ptr := Ptr + 1; Ptr := Ptr + 1;
-- Legacy_Elaboration_Order := True; Legacy_Elaboration_Order := True;
-- Processing for i switch -- Processing for i switch
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment