.. |with| replace:: *with*
.. |withs| replace:: *with*\ s
.. |withed| replace:: *with*\ ed
.. |withing| replace:: *with*\ ing

.. -- Example: A |withing| unit has a |with| clause, it |withs| a |withed| unit


.. _Elaboration_Order_Handling_in_GNAT:

**********************************
Elaboration Order Handling in GNAT
**********************************

.. index:: Order of elaboration
.. index:: Elaboration control

This appendix describes the handling of elaboration code in Ada and
in GNAT, and discusses how the order of elaboration of program units can
be controlled in GNAT, either automatically or with explicit programming
features.

.. _Elaboration_Code:

Elaboration Code
================

Ada provides rather general mechanisms for executing code at elaboration
time, that is to say before the main program starts executing. Such code arises
in three contexts:

* *Initializers for variables*

  Variables declared at the library level, in package specs or bodies, can
  require initialization that is performed at elaboration time, as in:

  .. code-block:: ada

       Sqrt_Half : Float := Sqrt (0.5);

* *Package initialization code*

  Code in a `BEGIN-END` section at the outer level of a package body is
  executed as part of the package body elaboration code.

* *Library level task allocators*

  Tasks that are declared using task allocators at the library level
  start executing immediately and hence can execute at elaboration time.

Subprogram calls are possible in any of these contexts, which means that
any arbitrary part of the program may be executed as part of the elaboration
code. It is even possible to write a program which does all its work at
elaboration time, with a null main program, although stylistically this
would usually be considered an inappropriate way to structure
a program.

An important concern arises in the context of elaboration code:
we have to be sure that it is executed in an appropriate order. What we
have is a series of elaboration code sections, potentially one section
for each unit in the program. It is important that these execute
in the correct order. Correctness here means that, taking the above
example of the declaration of `Sqrt_Half`,
if some other piece of
elaboration code references `Sqrt_Half`,
then it must run after the
section of elaboration code that contains the declaration of
`Sqrt_Half`.

There would never be any order of elaboration problem if we made a rule
that whenever you |with| a unit, you must elaborate both the spec and body
of that unit before elaborating the unit doing the |withing|:

.. code-block:: ada

     with Unit_1;
     package Unit_2 is ...

would require that both the body and spec of `Unit_1` be elaborated
before the spec of `Unit_2`. However, a rule like that would be far too
restrictive. In particular, it would make it impossible to have routines
in separate packages that were mutually recursive.

You might think that a clever enough compiler could look at the actual
elaboration code and determine an appropriate correct order of elaboration,
but in the general case, this is not possible. Consider the following
example.

In the body of `Unit_1`, we have a procedure `Func_1`
that references
the variable `Sqrt_1`, which is declared in the elaboration code
of the body of `Unit_1`:

.. code-block:: ada

     Sqrt_1 : Float := Sqrt (0.1);

The elaboration code of the body of `Unit_1` also contains:

.. code-block:: ada

     if expression_1 = 1 then
        Q := Unit_2.Func_2;
     end if;

`Unit_2` is exactly parallel,
it has a procedure `Func_2` that references
the variable `Sqrt_2`, which is declared in the elaboration code of
the body `Unit_2`:

.. code-block:: ada

      Sqrt_2 : Float := Sqrt (0.1);

The elaboration code of the body of `Unit_2` also contains:

.. code-block:: ada

     if expression_2 = 2 then
        Q := Unit_1.Func_1;
     end if;

Now the question is, which of the following orders of elaboration is
acceptable:

::

     Spec of Unit_1
     Spec of Unit_2
     Body of Unit_1
     Body of Unit_2

or

::

     Spec of Unit_2
     Spec of Unit_1
     Body of Unit_2
     Body of Unit_1

If you carefully analyze the flow here, you will see that you cannot tell
at compile time the answer to this question.
If `expression_1` is not equal to 1,
and `expression_2` is not equal to 2,
then either order is acceptable, because neither of the function calls is
executed. If both tests evaluate to true, then neither order is acceptable
and in fact there is no correct order.

If one of the two expressions is true, and the other is false, then one
of the above orders is correct, and the other is incorrect. For example,
if `expression_1` /= 1 and `expression_2` = 2,
then the call to `Func_1`
will occur, but not the call to `Func_2.`
This means that it is essential
to elaborate the body of `Unit_1` before
the body of `Unit_2`, so the first
order of elaboration is correct and the second is wrong.

By making `expression_1` and `expression_2`
depend on input data, or perhaps
the time of day, we can make it impossible for the compiler or binder
to figure out which of these expressions will be true, and hence it
is impossible to guarantee a safe order of elaboration at run time.

.. _Checking_the_Elaboration_Order:

Checking the Elaboration Order
==============================

In some languages that involve the same kind of elaboration problems,
e.g., Java and C++, the programmer needs to take these
ordering problems into account, and it is common to
write a program in which an incorrect elaboration order  gives
surprising results, because it references variables before they
are initialized.
Ada is designed to be a safe language, and a programmer-beware approach is
clearly not sufficient. Consequently, the language provides three lines
of defense:

* *Standard rules*

  Some standard rules restrict the possible choice of elaboration
  order. In particular, if you |with| a unit, then its spec is always
  elaborated before the unit doing the |with|. Similarly, a parent
  spec is always elaborated before the child spec, and finally
  a spec is always elaborated before its corresponding body.

.. index:: Elaboration checks
.. index:: Checks, elaboration

* *Dynamic elaboration checks*

  Dynamic checks are made at run time, so that if some entity is accessed
  before it is elaborated (typically  by means of a subprogram call)
  then the exception (`Program_Error`) is raised.

* *Elaboration control*

  Facilities are provided for the programmer to specify the desired order
  of elaboration.

Let's look at these facilities in more detail. First, the rules for
dynamic checking. One possible rule would be simply to say that the
exception is raised if you access a variable which has not yet been
elaborated. The trouble with this approach is that it could require
expensive checks on every variable reference. Instead Ada has two
rules which are a little more restrictive, but easier to check, and
easier to state:

* *Restrictions on calls*

  A subprogram can only be called at elaboration time if its body
  has been elaborated. The rules for elaboration given above guarantee
  that the spec of the subprogram has been elaborated before the
  call, but not the body. If this rule is violated, then the
  exception `Program_Error` is raised.

* *Restrictions on instantiations*

  A generic unit can only be instantiated if the body of the generic
  unit has been elaborated. Again, the rules for elaboration given above
  guarantee that the spec of the generic unit has been elaborated
  before the instantiation, but not the body. If this rule is
  violated, then the exception `Program_Error` is raised.

The idea is that if the body has been elaborated, then any variables
it references must have been elaborated; by checking for the body being
elaborated we guarantee that none of its references causes any
trouble. As we noted above, this is a little too restrictive, because a
subprogram that has no non-local references in its body may in fact be safe
to call. However, it really would be unsafe to rely on this, because
it would mean that the caller was aware of details of the implementation
in the body. This goes against the basic tenets of Ada.

A plausible implementation can be described as follows.
A Boolean variable is associated with each subprogram
and each generic unit. This variable is initialized to False, and is set to
True at the point body is elaborated. Every call or instantiation checks the
variable, and raises `Program_Error` if the variable is False.

Note that one might think that it would be good enough to have one Boolean
variable for each package, but that would not deal with cases of trying
to call a body in the same package as the call
that has not been elaborated yet.
Of course a compiler may be able to do enough analysis to optimize away
some of the Boolean variables as unnecessary, and `GNAT` indeed
does such optimizations, but still the easiest conceptual model is to
think of there being one variable per subprogram.

.. _Controlling_the_Elaboration_Order:

Controlling the Elaboration Order
=================================

In the previous section we discussed the rules in Ada which ensure
that `Program_Error` is raised if an incorrect elaboration order is
chosen. This prevents erroneous executions, but we need mechanisms to
specify a correct execution and avoid the exception altogether.
To achieve this, Ada provides a number of features for controlling
the order of elaboration. We discuss these features in this section.

First, there are several ways of indicating to the compiler that a given
unit has no elaboration problems:

* *packages that do not require a body*

  A library package that does not require a body does not permit
  a body (this rule was introduced in Ada 95).
  Thus if we have a such a package, as in:

  .. code-block:: ada

       package Definitions is
          generic
             type m is new integer;
          package Subp is
             type a is array (1 .. 10) of m;
             type b is array (1 .. 20) of m;
          end Subp;
       end Definitions;

  A package that |withs| `Definitions` may safely instantiate
  `Definitions.Subp` because the compiler can determine that there
  definitely is no package body to worry about in this case

.. index:: pragma Pure

* *pragma Pure*

  This pragma places sufficient restrictions on a unit to guarantee that
  no call to any subprogram in the unit can result in an
  elaboration problem. This means that the compiler does not need
  to worry about the point of elaboration of such units, and in
  particular, does not need to check any calls to any subprograms
  in this unit.

.. index:: pragma Preelaborate

* *pragma Preelaborate*

  This pragma places slightly less stringent restrictions on a unit than
  does pragma Pure,
  but these restrictions are still sufficient to ensure that there
  are no elaboration problems with any calls to the unit.

.. index:: pragma Elaborate_Body

* *pragma Elaborate_Body*

  This pragma requires that the body of a unit be elaborated immediately
  after its spec. Suppose a unit `A` has such a pragma,
  and unit `B` does
  a |with| of unit `A`. Recall that the standard rules require
  the spec of unit `A`
  to be elaborated before the |withing| unit; given the pragma in
  `A`, we also know that the body of `A`
  will be elaborated before `B`, so
  that calls to `A` are safe and do not need a check.

  Note that, unlike pragma `Pure` and pragma `Preelaborate`,
  the use of `Elaborate_Body` does not guarantee that the program is
  free of elaboration problems, because it may not be possible
  to satisfy the requested elaboration order.
  Let's go back to the example with `Unit_1` and `Unit_2`.
  If a programmer marks `Unit_1` as `Elaborate_Body`,
  and not `Unit_2,` then the order of
  elaboration will be::

       Spec of Unit_2
       Spec of Unit_1
       Body of Unit_1
       Body of Unit_2

  Now that means that the call to `Func_1` in `Unit_2`
  need not be checked,
  it must be safe. But the call to `Func_2` in
  `Unit_1` may still fail if
  `Expression_1` is equal to 1,
  and the programmer must still take
  responsibility for this not being the case.

  If all units carry a pragma `Elaborate_Body`, then all problems are
  eliminated, except for calls entirely within a body, which are
  in any case fully under programmer control. However, using the pragma
  everywhere is not always possible.
  In particular, for our `Unit_1`/`Unit_2` example, if
  we marked both of them as having pragma `Elaborate_Body`, then
  clearly there would be no possible elaboration order.

The above pragmas allow a server to guarantee safe use by clients, and
clearly this is the preferable approach. Consequently a good rule
is to mark units as `Pure` or `Preelaborate` if possible,
and if this is not possible,
mark them as `Elaborate_Body` if possible.
As we have seen, there are situations where neither of these
three pragmas can be used.
So we also provide methods for clients to control the
order of elaboration of the servers on which they depend:

.. index:: pragma Elaborate

* *pragma Elaborate (unit)*

  This pragma is placed in the context clause, after a |with| clause,
  and it requires that the body of the named unit be elaborated before
  the unit in which the pragma occurs. The idea is to use this pragma
  if the current unit calls at elaboration time, directly or indirectly,
  some subprogram in the named unit.


.. index:: pragma Elaborate_All

* *pragma Elaborate_All (unit)*

  This is a stronger version of the Elaborate pragma. Consider the
  following example::

        Unit A |withs| unit B and calls B.Func in elab code
        Unit B |withs| unit C, and B.Func calls C.Func


  Now if we put a pragma `Elaborate (B)`
  in unit `A`, this ensures that the
  body of `B` is elaborated before the call, but not the
  body of `C`, so
  the call to `C.Func` could still cause `Program_Error` to
  be raised.

  The effect of a pragma `Elaborate_All` is stronger, it requires
  not only that the body of the named unit be elaborated before the
  unit doing the |with|, but also the bodies of all units that the
  named unit uses, following |with| links transitively. For example,
  if we put a pragma `Elaborate_All (B)` in unit `A`,
  then it requires not only that the body of `B` be elaborated before `A`,
  but also the body of `C`, because `B` |withs| `C`.

We are now in a position to give a usage rule in Ada for avoiding
elaboration problems, at least if dynamic dispatching and access to
subprogram values are not used. We will handle these cases separately
later.

The rule is simple:

*If a unit has elaboration code that can directly or
indirectly make a call to a subprogram in a |withed| unit, or instantiate
a generic package in a |withed| unit,
then if the |withed| unit does not have
pragma `Pure` or `Preelaborate`, then the client should have
a pragma `Elaborate_All`for the |withed| unit.**

By following this rule a client is
assured that calls can be made without risk of an exception.

For generic subprogram instantiations, the rule can be relaxed to
require only a pragma `Elaborate` since elaborating the body
of a subprogram cannot cause any transitive elaboration (we are
not calling the subprogram in this case, just elaborating its
declaration).

If this rule is not followed, then a program may be in one of four
states:

* *No order exists*

  No order of elaboration exists which follows the rules, taking into
  account any `Elaborate`, `Elaborate_All`,
  or `Elaborate_Body` pragmas. In
  this case, an Ada compiler must diagnose the situation at bind
  time, and refuse to build an executable program.

* *One or more orders exist, all incorrect*

  One or more acceptable elaboration orders exist, and all of them
  generate an elaboration order problem. In this case, the binder
  can build an executable program, but `Program_Error` will be raised
  when the program is run.

* *Several orders exist, some right, some incorrect*

  One or more acceptable elaboration orders exists, and some of them
  work, and some do not. The programmer has not controlled
  the order of elaboration, so the binder may or may not pick one of
  the correct orders, and the program may or may not raise an
  exception when it is run. This is the worst case, because it means
  that the program may fail when moved to another compiler, or even
  another version of the same compiler.

* *One or more orders exists, all correct*

  One ore more acceptable elaboration orders exist, and all of them
  work. In this case the program runs successfully. This state of
  affairs can be guaranteed by following the rule we gave above, but
  may be true even if the rule is not followed.

Note that one additional advantage of following our rules on the use
of `Elaborate` and `Elaborate_All`
is that the program continues to stay in the ideal (all orders OK) state
even if maintenance
changes some bodies of some units. Conversely, if a program that does
not follow this rule happens to be safe at some point, this state of affairs
may deteriorate silently as a result of maintenance changes.

You may have noticed that the above discussion did not mention
the use of `Elaborate_Body`. This was a deliberate omission. If you
|with| an `Elaborate_Body` unit, it still may be the case that
code in the body makes calls to some other unit, so it is still necessary
to use `Elaborate_All` on such units.


.. _Controlling_Elaboration_in_GNAT_-_Internal_Calls:

Controlling Elaboration in GNAT - Internal Calls
================================================

In the case of internal calls, i.e., calls within a single package, the
programmer has full control over the order of elaboration, and it is up
to the programmer to elaborate declarations in an appropriate order. For
example writing:

.. code-block:: ada

     function One return Float;

     Q : Float := One;

     function One return Float is
     begin
          return 1.0;
     end One;

will obviously raise `Program_Error` at run time, because function
One will be called before its body is elaborated. In this case GNAT will
generate a warning that the call will raise `Program_Error`::

     1. procedure y is
     2.    function One return Float;
     3.
     4.    Q : Float := One;
                        |
        >>> warning: cannot call "One" before body is elaborated
        >>> warning: Program_Error will be raised at run time

     5.
     6.    function One return Float is
     7.    begin
     8.         return 1.0;
     9.    end One;
    10.
    11. begin
    12.    null;
    13. end;


Note that in this particular case, it is likely that the call is safe, because
the function `One` does not access any global variables.
Nevertheless in Ada, we do not want the validity of the check to depend on
the contents of the body (think about the separate compilation case), so this
is still wrong, as we discussed in the previous sections.

The error is easily corrected by rearranging the declarations so that the
body of `One` appears before the declaration containing the call
(note that in Ada 95 as well as later versions of the Ada standard,
declarations can appear in any order, so there is no restriction that
would prevent this reordering, and if we write:

.. code-block:: ada

     function One return Float;

     function One return Float is
     begin
          return 1.0;
     end One;

     Q : Float := One;

then all is well, no warning is generated, and no
`Program_Error` exception
will be raised.
Things are more complicated when a chain of subprograms is executed:

.. code-block:: ada

     function A return Integer;
     function B return Integer;
     function C return Integer;

     function B return Integer is begin return A; end;
     function C return Integer is begin return B; end;

     X : Integer := C;

     function A return Integer is begin return 1; end;

Now the call to `C`
at elaboration time in the declaration of `X` is correct, because
the body of `C` is already elaborated,
and the call to `B` within the body of
`C` is correct, but the call
to `A` within the body of `B` is incorrect, because the body
of `A` has not been elaborated, so `Program_Error`
will be raised on the call to `A`.
In this case GNAT will generate a
warning that `Program_Error` may be
raised at the point of the call. Let's look at the warning::

     1. procedure x is
     2.    function A return Integer;
     3.    function B return Integer;
     4.    function C return Integer;
     5.
     6.    function B return Integer is begin return A; end;
                                                        |
        >>> warning: call to "A" before body is elaborated may
                     raise Program_Error
        >>> warning: "B" called at line 7
        >>> warning: "C" called at line 9

     7.    function C return Integer is begin return B; end;
     8.
     9.    X : Integer := C;
    10.
    11.    function A return Integer is begin return 1; end;
    12.
    13. begin
    14.    null;
    15. end;


Note that the message here says 'may raise', instead of the direct case,
where the message says 'will be raised'. That's because whether
`A` is
actually called depends in general on run-time flow of control.
For example, if the body of `B` said

.. code-block:: ada

     function B return Integer is
     begin
        if some-condition-depending-on-input-data then
           return A;
        else
           return 1;
        end if;
     end B;

then we could not know until run time whether the incorrect call to A would
actually occur, so `Program_Error` might
or might not be raised. It is possible for a compiler to
do a better job of analyzing bodies, to
determine whether or not `Program_Error`
might be raised, but it certainly
couldn't do a perfect job (that would require solving the halting problem
and is provably impossible), and because this is a warning anyway, it does
not seem worth the effort to do the analysis. Cases in which it
would be relevant are rare.

In practice, warnings of either of the forms given
above will usually correspond to
real errors, and should be examined carefully and eliminated.
In the rare case where a warning is bogus, it can be suppressed by any of
the following methods:

* Compile with the *-gnatws* switch set

* Suppress `Elaboration_Check` for the called subprogram

* Use pragma `Warnings_Off` to turn warnings off for the call

For the internal elaboration check case,
GNAT by default generates the
necessary run-time checks to ensure
that `Program_Error` is raised if any
call fails an elaboration check. Of course this can only happen if a
warning has been issued as described above. The use of pragma
`Suppress (Elaboration_Check)` may (but is not guaranteed to) suppress
some of these checks, meaning that it may be possible (but is not
guaranteed) for a program to be able to call a subprogram whose body
is not yet elaborated, without raising a `Program_Error` exception.


.. _Controlling_Elaboration_in_GNAT_-_External_Calls:

Controlling Elaboration in GNAT - External Calls
================================================

The previous section discussed the case in which the execution of a
particular thread of elaboration code occurred entirely within a
single unit. This is the easy case to handle, because a programmer
has direct and total control over the order of elaboration, and
furthermore, checks need only be generated in cases which are rare
and which the compiler can easily detect.
The situation is more complex when separate compilation is taken into account.
Consider the following:

.. code-block:: ada

      package Math is
         function Sqrt (Arg : Float) return Float;
      end Math;

      package body Math is
         function Sqrt (Arg : Float) return Float is
         begin
               ...
         end Sqrt;
      end Math;

      with Math;
      package Stuff is
         X : Float := Math.Sqrt (0.5);
      end Stuff;

      with Stuff;
      procedure Main is
      begin
         ...
      end Main;

where `Main` is the main program. When this program is executed, the
elaboration code must first be executed, and one of the jobs of the
binder is to determine the order in which the units of a program are
to be elaborated. In this case we have four units: the spec and body
of `Math`,
the spec of `Stuff` and the body of `Main`).
In what order should the four separate sections of elaboration code
be executed?

There are some restrictions in the order of elaboration that the binder
can choose. In particular, if unit U has a |with|
for a package `X`, then you
are assured that the spec of `X`
is elaborated before U , but you are
not assured that the body of `X`
is elaborated before U.
This means that in the above case, the binder is allowed to choose the
order::

     spec of Math
     spec of Stuff
     body of Math
     body of Main

but that's not good, because now the call to `Math.Sqrt`
that happens during
the elaboration of the `Stuff`
spec happens before the body of `Math.Sqrt` is
elaborated, and hence causes `Program_Error` exception to be raised.
At first glance, one might say that the binder is misbehaving, because
obviously you want to elaborate the body of something you |with| first, but
that is not a general rule that can be followed in all cases. Consider

.. code-block:: ada

      package X is ...

      package Y is ...

      with X;
      package body Y is ...

      with Y;
      package body X is ...

This is a common arrangement, and, apart from the order of elaboration
problems that might arise in connection with elaboration code, this works fine.
A rule that says that you must first elaborate the body of anything you
|with| cannot work in this case:
the body of `X` |withs| `Y`,
which means you would have to
elaborate the body of `Y` first, but that |withs| `X`,
which means
you have to elaborate the body of `X` first, but ... and we have a
loop that cannot be broken.

It is true that the binder can in many cases guess an order of elaboration
that is unlikely to cause a `Program_Error`
exception to be raised, and it tries to do so (in the
above example of `Math/Stuff/Spec`, the GNAT binder will
by default
elaborate the body of `Math` right after its spec, so all will be well).

However, a program that blindly relies on the binder to be helpful can
get into trouble, as we discussed in the previous sections, so GNAT
provides a number of facilities for assisting the programmer in
developing programs that are robust with respect to elaboration order.


.. _Default_Behavior_in_GNAT_-_Ensuring_Safety:

Default Behavior in GNAT - Ensuring Safety
==========================================

The default behavior in GNAT ensures elaboration safety. In its
default mode GNAT implements the
rule we previously described as the right approach. Let's restate it:

*If a unit has elaboration code that can directly or indirectly make a
call to a subprogram in a |withed| unit, or instantiate a generic
package in a |withed| unit, then if the |withed| unit
does not have pragma `Pure` or `Preelaborate`, then the client should have an
`Elaborate_All` pragma for the |withed| unit.*

*In the case of instantiating a generic subprogram, it is always
sufficient to have only an `Elaborate` pragma for the
|withed| unit.*

By following this rule a client is assured that calls and instantiations
can be made without risk of an exception.

In this mode GNAT traces all calls that are potentially made from
elaboration code, and puts in any missing implicit `Elaborate`
and `Elaborate_All` pragmas.
The advantage of this approach is that no elaboration problems
are possible if the binder can find an elaboration order that is
consistent with these implicit `Elaborate` and
`Elaborate_All` pragmas. The
disadvantage of this approach is that no such order may exist.

If the binder does not generate any diagnostics, then it means that it has
found an elaboration order that is guaranteed to be safe. However, the binder
may still be relying on implicitly generated `Elaborate` and
`Elaborate_All` pragmas so portability to other compilers than GNAT is not
guaranteed.

If it is important to guarantee portability, then the compilations should
use the *-gnatel*
(info messages for elaboration pragmas) switch. This will cause info messages
to be generated indicating the missing `Elaborate` and
`Elaborate_All` pragmas.
Consider the following source program:

.. code-block:: ada

     with k;
     package j is
       m : integer := k.r;
     end;

where it is clear that there
should be a pragma `Elaborate_All`
for unit `k`. An implicit pragma will be generated, and it is
likely that the binder will be able to honor it. However, if you want
to port this program to some other Ada compiler than GNAT.
it is safer to include the pragma explicitly in the source. If this
unit is compiled with the *-gnatel*
switch, then the compiler outputs an information message::

     1. with k;
     2. package j is
     3.   m : integer := k.r;
                          |
        >>> info: call to "r" may raise Program_Error
        >>> info: missing pragma Elaborate_All for "k"

     4. end;

and these messages can be used as a guide for supplying manually
the missing pragmas. It is usually a bad idea to use this
option during development. That's because it will tell you when
you need to put in a pragma, but cannot tell you when it is time
to take it out. So the use of pragma `Elaborate_All` may lead to
unnecessary dependencies and even false circularities.

This default mode is more restrictive than the Ada Reference
Manual, and it is possible to construct programs which will compile
using the dynamic model described there, but will run into a
circularity using the safer static model we have described.

Of course any Ada compiler must be able to operate in a mode
consistent with the requirements of the Ada Reference Manual,
and in particular must have the capability of implementing the
standard dynamic model of elaboration with run-time checks.

In GNAT, this standard mode can be achieved either by the use of
the *-gnatE* switch on the compiler (*gcc* or
*gnatmake*) command, or by the use of the configuration pragma:

.. code-block:: ada

      pragma Elaboration_Checks (DYNAMIC);

Either approach will cause the unit affected to be compiled using the
standard dynamic run-time elaboration checks described in the Ada
Reference Manual. The static model is generally preferable, since it
is clearly safer to rely on compile and link time checks rather than
run-time checks. However, in the case of legacy code, it may be
difficult to meet the requirements of the static model. This
issue is further discussed in
:ref:`What_to_Do_If_the_Default_Elaboration_Behavior_Fails`.

Note that the static model provides a strict subset of the allowed
behavior and programs of the Ada Reference Manual, so if you do
adhere to the static model and no circularities exist,
then you are assured that your program will
work using the dynamic model, providing that you remove any
pragma Elaborate statements from the source.


.. _Treatment_of_Pragma_Elaborate:

Treatment of Pragma Elaborate
=============================

.. index:: Pragma Elaborate

The use of `pragma Elaborate`
should generally be avoided in Ada 95 and Ada 2005 programs,
since there is no guarantee that transitive calls
will be properly handled. Indeed at one point, this pragma was placed
in Annex J (Obsolescent Features), on the grounds that it is never useful.

Now that's a bit restrictive. In practice, the case in which
`pragma Elaborate` is useful is when the caller knows that there
are no transitive calls, or that the called unit contains all necessary
transitive `pragma Elaborate` statements, and legacy code often
contains such uses.

Strictly speaking the static mode in GNAT should ignore such pragmas,
since there is no assurance at compile time that the necessary safety
conditions are met. In practice, this would cause GNAT to be incompatible
with correctly written Ada 83 code that had all necessary
`pragma Elaborate` statements in place. Consequently, we made the
decision that GNAT in its default mode will believe that if it encounters
a `pragma Elaborate` then the programmer knows what they are doing,
and it will trust that no elaboration errors can occur.

The result of this decision is two-fold. First to be safe using the
static mode, you should remove all `pragma Elaborate` statements.
Second, when fixing circularities in existing code, you can selectively
use `pragma Elaborate` statements to convince the static mode of
GNAT that it need not generate an implicit `pragma Elaborate_All`
statement.

When using the static mode with *-gnatwl*, any use of
`pragma Elaborate` will generate a warning about possible
problems.


.. _Elaboration_Issues_for_Library_Tasks:

Elaboration Issues for Library Tasks
====================================

.. index:: Library tasks, elaboration issues

.. index:: Elaboration of library tasks

In this section we examine special elaboration issues that arise for
programs that declare library level tasks.

Generally the model of execution of an Ada program is that all units are
elaborated, and then execution of the program starts. However, the
declaration of library tasks definitely does not fit this model. The
reason for this is that library tasks start as soon as they are declared
(more precisely, as soon as the statement part of the enclosing package
body is reached), that is to say before elaboration
of the program is complete. This means that if such a task calls a
subprogram, or an entry in another task, the callee may or may not be
elaborated yet, and in the standard
Reference Manual model of dynamic elaboration checks, you can even
get timing dependent Program_Error exceptions, since there can be
a race between the elaboration code and the task code.

The static model of elaboration in GNAT seeks to avoid all such
dynamic behavior, by being conservative, and the conservative
approach in this particular case is to assume that all the code
in a task body is potentially executed at elaboration time if
a task is declared at the library level.

This can definitely result in unexpected circularities. Consider
the following example

.. code-block:: ada

      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 Text_IO;
      package body Utils is
        procedure Put_Val (Arg : Decls.My_Int) is
        begin
           Text_IO.Put_Line (Decls.My_Int'Image (Decls.Ident (Arg)));
        end Put_Val;
      end Utils;

      with Decls;
      procedure Main is
      begin
         Decls.Lib_Task.Start;
      end;

If the above example is compiled in the default static elaboration
mode, then a circularity occurs. The circularity comes from the call
`Utils.Put_Val` in the task body of `Decls.Lib_Task`. Since
this call occurs in elaboration code, we need an implicit pragma
`Elaborate_All` for `Utils`. This means that not only must
the spec and body of `Utils` be elaborated before the body
of `Decls`, but also the spec and body of any unit that is
|withed| by the body of `Utils` must also be elaborated before
the body of `Decls`. This is the transitive implication of
pragma `Elaborate_All` and it makes sense, because in general
the body of `Put_Val` might have a call to something in a
|withed| unit.

In this case, the body of Utils (actually its spec) |withs|
`Decls`. Unfortunately this means that the body of `Decls`
must be elaborated before itself, in case there is a call from the
body of `Utils`.

Here is the exact chain of events we are worrying about:

* In the body of `Decls` a call is made from within the body of a library
  task to a subprogram in the package `Utils`. Since this call may
  occur at elaboration time (given that the task is activated at elaboration
  time), we have to assume the worst, i.e., that the
  call does happen at elaboration time.

* This means that the body and spec of `Util` must be elaborated before
  the body of `Decls` so that this call does not cause an access before
  elaboration.

* Within the body of `Util`, specifically within the body of
  `Util.Put_Val` there may be calls to any unit |withed|
  by this package.

* One such |withed| package is package `Decls`, so there
  might be a call to a subprogram in `Decls` in `Put_Val`.
  In fact there is such a call in this example, but we would have to
  assume that there was such a call even if it were not there, since
  we are not supposed to write the body of `Decls` knowing what
  is in the body of `Utils`; certainly in the case of the
  static elaboration model, the compiler does not know what is in
  other bodies and must assume the worst.

* This means that the spec and body of `Decls` must also be
  elaborated before we elaborate the unit containing the call, but
  that unit is `Decls`! This means that the body of `Decls`
  must be elaborated before itself, and that's a circularity.

Indeed, if you add an explicit pragma `Elaborate_All` for `Utils` in
the body of `Decls` you will get a true Ada Reference Manual
circularity that makes the program illegal.

In practice, we have found that problems with the static model of
elaboration in existing code often arise from library tasks, so
we must address this particular situation.

Note that if we compile and run the program above, using the dynamic model of
elaboration (that is to say use the *-gnatE* switch),
then it compiles, binds,
links, and runs, printing the expected result of 2. Therefore in some sense
the circularity here is only apparent, and we need to capture
the properties of this program that  distinguish it from other library-level
tasks that have real elaboration problems.

We have four possible answers to this question:


* Use the dynamic model of elaboration.

  If we use the *-gnatE* switch, then as noted above, the program works.
  Why is this? If we examine the task body, it is apparent that the task cannot
  proceed past the
  `accept` statement until after elaboration has been completed, because
  the corresponding entry call comes from the main program, not earlier.
  This is why the dynamic model works here. But that's really giving
  up on a precise analysis, and we prefer to take this approach only if we cannot
  solve the
  problem in any other manner. So let us examine two ways to reorganize
  the program to avoid the potential elaboration problem.

* Split library tasks into separate packages.

  Write separate packages, so that library tasks are isolated from
  other declarations as much as possible. Let us look at a variation on
  the above program.


  .. code-block:: ada

      package Decls1 is
        task Lib_Task is
           entry Start;
        end Lib_Task;
      end Decls1;

      with Utils;
      package body Decls1 is
        task body Lib_Task is
        begin
           accept Start;
           Utils.Put_Val (2);
        end Lib_Task;
      end Decls1;

      package Decls2 is
        type My_Int is new Integer;
        function Ident (M : My_Int) return My_Int;
      end Decls2;

      with Utils;
      package body Decls2 is
        function Ident (M : My_Int) return My_Int is
        begin
           return M;
        end Ident;
      end Decls2;

      with Decls2;
      package Utils is
        procedure Put_Val (Arg : Decls2.My_Int);
      end Utils;

      with Text_IO;
      package body Utils is
        procedure Put_Val (Arg : Decls2.My_Int) is
        begin
           Text_IO.Put_Line (Decls2.My_Int'Image (Decls2.Ident (Arg)));
        end Put_Val;
      end Utils;

      with Decls1;
      procedure Main is
      begin
         Decls1.Lib_Task.Start;
      end;


  All we have done is to split `Decls` into two packages, one
  containing the library task, and one containing everything else. Now
  there is no cycle, and the program compiles, binds, links and executes
  using the default static model of elaboration.

* Declare separate task types.

  A significant part of the problem arises because of the use of the
  single task declaration form. This means that the elaboration of
  the task type, and the elaboration of the task itself (i.e., the
  creation of the task) happen at the same time. A good rule
  of style in Ada is to always create explicit task types. By
  following the additional step of placing task objects in separate
  packages from the task type declaration, many elaboration problems
  are avoided. Here is another modified example of the example program:

  .. code-block:: ada

      package Decls is
        task type Lib_Task_Type is
           entry Start;
        end Lib_Task_Type;

        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_Type is
        begin
           accept Start;
           Utils.Put_Val (2);
        end Lib_Task_Type;

        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 Text_IO;
      package body Utils is
        procedure Put_Val (Arg : Decls.My_Int) is
        begin
           Text_IO.Put_Line (Decls.My_Int'Image (Decls.Ident (Arg)));
        end Put_Val;
      end Utils;

      with Decls;
      package Declst is
         Lib_Task : Decls.Lib_Task_Type;
      end Declst;

      with Declst;
      procedure Main is
      begin
         Declst.Lib_Task.Start;
      end;


  What we have done here is to replace the `task` declaration in
  package `Decls` with a `task type` declaration. Then we
  introduce a separate package `Declst` to contain the actual
  task object. This separates the elaboration issues for
  the `task type`
  declaration, which causes no trouble, from the elaboration issues
  of the task object, which is also unproblematic, since it is now independent
  of the elaboration of  `Utils`.
  This separation of concerns also corresponds to
  a generally sound engineering principle of separating declarations
  from instances. This version of the program also compiles, binds, links,
  and executes, generating the expected output.

.. index:: No_Entry_Calls_In_Elaboration_Code restriction

* Use No_Entry_Calls_In_Elaboration_Code restriction.

  The previous two approaches described how a program can be restructured
  to avoid the special problems caused by library task bodies. in practice,
  however, such restructuring may be difficult to apply to existing legacy code,
  so we must consider solutions that do not require massive rewriting.

  Let us consider more carefully why our original sample program works
  under the dynamic model of elaboration. The reason is that the code
  in the task body blocks immediately on the `accept`
  statement. Now of course there is nothing to prohibit elaboration
  code from making entry calls (for example from another library level task),
  so we cannot tell in isolation that
  the task will not execute the accept statement  during elaboration.

  However, in practice it is very unusual to see elaboration code
  make any entry calls, and the pattern of tasks starting
  at elaboration time and then immediately blocking on `accept` or
  `select` statements is very common. What this means is that
  the compiler is being too pessimistic when it analyzes the
  whole package body as though it might be executed at elaboration
  time.

  If we know that the elaboration code contains no entry calls, (a very safe
  assumption most of the time, that could almost be made the default
  behavior), then we can compile all units of the program under control
  of the following configuration pragma:

  .. code-block:: ada

      pragma Restrictions (No_Entry_Calls_In_Elaboration_Code);

  This pragma can be placed in the :file:`gnat.adc` file in the usual
  manner. If we take our original unmodified program and compile it
  in the presence of a :file:`gnat.adc` containing the above pragma,
  then once again, we can compile, bind, link, and execute, obtaining
  the expected result. In the presence of this pragma, the compiler does
  not trace calls in a task body, that appear after the first `accept`
  or `select` statement, and therefore does not report a potential
  circularity in the original program.

  The compiler will check to the extent it can that the above
  restriction is not violated, but it is not always possible to do a
  complete check at compile time, so it is important to use this
  pragma only if the stated restriction is in fact met, that is to say
  no task receives an entry call before elaboration of all units is completed.


.. _Mixing_Elaboration_Models:

Mixing Elaboration Models
=========================

So far, we have assumed that the entire program is either compiled
using the dynamic model or static model, ensuring consistency. It
is possible to mix the two models, but rules have to be followed
if this mixing is done to ensure that elaboration checks are not
omitted.

The basic rule is that
**a unit compiled with the static model cannot
be |withed| by a unit compiled with the dynamic model**.
The reason for this is that in the static model, a unit assumes that
its clients guarantee to use (the equivalent of) pragma
`Elaborate_All` so that no elaboration checks are required
in inner subprograms, and this assumption is violated if the
client is compiled with dynamic checks.

The precise rule is as follows. A unit that is compiled with dynamic
checks can only |with| a unit that meets at least one of the
following criteria:


* The |withed| unit is itself compiled with dynamic elaboration
  checks (that is with the *-gnatE* switch.

* The |withed| unit is an internal GNAT implementation unit from
  the System, Interfaces, Ada, or GNAT hierarchies.

* The |withed| unit has pragma Preelaborate or pragma Pure.

* The |withing| unit (that is the client) has an explicit pragma
  `Elaborate_All` for the |withed| unit.


If this rule is violated, that is if a unit with dynamic elaboration
checks |withs| a unit that does not meet one of the above four
criteria, then the binder (`gnatbind`) will issue a warning
similar to that in the following example::

     warning: "x.ads" has dynamic elaboration checks and with's
     warning:   "y.ads" which has static elaboration checks

These warnings indicate that the rule has been violated, and that as a result
elaboration checks may be missed in the resulting executable file.
This warning may be suppressed using the *-ws* binder switch
in the usual manner.

One useful application of this mixing rule is in the case of a subsystem
which does not itself |with| units from the remainder of the
application. In this case, the entire subsystem can be compiled with
dynamic checks to resolve a circularity in the subsystem, while
allowing the main application that uses this subsystem to be compiled
using the more reliable default static model.


.. _What_to_Do_If_the_Default_Elaboration_Behavior_Fails:

What to Do If the Default Elaboration Behavior Fails
====================================================

If the binder cannot find an acceptable order, it outputs detailed
diagnostics. For example::

     error: elaboration circularity detected
     info:   "proc (body)" must be elaborated before "pack (body)"
     info:     reason: Elaborate_All probably needed in unit "pack (body)"
     info:     recompile "pack (body)" with -gnatel
     info:                             for full details
     info:       "proc (body)"
     info:         is needed by its spec:
     info:       "proc (spec)"
     info:         which is withed by:
     info:       "pack (body)"
     info:  "pack (body)" must be elaborated before "proc (body)"
     info:     reason: pragma Elaborate in unit "proc (body)"

In this case we have a cycle that the binder cannot break. On the one
hand, there is an explicit pragma Elaborate in `proc` for
`pack`. This means that the body of `pack` must be elaborated
before the body of `proc`. On the other hand, there is elaboration
code in `pack` that calls a subprogram in `proc`. This means
that for maximum safety, there should really be a pragma
Elaborate_All in `pack` for `proc` which would require that
the body of `proc` be elaborated before the body of
`pack`. Clearly both requirements cannot be satisfied.
Faced with a circularity of this kind, you have three different options.


* *Fix the program*

  The most desirable option from the point of view of long-term maintenance
  is to rearrange the program so that the elaboration problems are avoided.
  One useful technique is to place the elaboration code into separate
  child packages. Another is to move some of the initialization code to
  explicitly called 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.

* *Perform dynamic checks*

  If the compilations are done using the *-gnatE*
  (dynamic elaboration check) switch, then GNAT behaves in a quite different
  manner. Dynamic checks are generated for all calls that could possibly result
  in raising an exception. With this switch, the compiler does not generate
  implicit `Elaborate` or `Elaborate_All` pragmas. The behavior then is
  exactly as specified in the :title:`Ada Reference Manual`.
  The binder will generate
  an executable program that may or may not raise `Program_Error`, and then
  it is the programmer's job to ensure that it does not raise an exception. Note
  that it is important to compile all units with the switch, it cannot be used
  selectively.

* *Suppress checks*

  The drawback of dynamic checks is that they generate a
  significant overhead at run time, both in space and time. If you
  are absolutely sure that your program cannot raise any elaboration
  exceptions, and you still want to use the dynamic elaboration model,
  then you can use the configuration pragma
  `Suppress (Elaboration_Check)` to suppress all such checks. For
  example this pragma could be placed in the :file:`gnat.adc` file.

* *Suppress checks selectively*

  When you know that certain calls or instantiations in elaboration code cannot
  possibly lead to an elaboration error, and the binder nevertheless complains
  about implicit `Elaborate` and `Elaborate_All` pragmas that lead to
  elaboration circularities, it is possible to remove those warnings locally and
  obtain a program that will bind. Clearly this can be unsafe, and it is the
  responsibility of the programmer to make sure that the resulting program has no
  elaboration anomalies. The pragma `Suppress (Elaboration_Check)` can be
  used with different granularity to suppress warnings and break elaboration
  circularities:

  * Place the pragma that names the called subprogram in the declarative part
    that contains the call.

  * Place the pragma in the declarative part, without naming an entity. This
    disables warnings on all calls in the corresponding  declarative region.

  * Place the pragma in the package spec that declares the called subprogram,
    and name the subprogram. This disables warnings on all elaboration calls to
    that subprogram.

  * Place the pragma in the package spec that declares the called subprogram,
    without naming any entity. This disables warnings on all elaboration calls to
    all subprograms declared in this spec.

  * Use Pragma Elaborate.

    As previously described in section :ref:`Treatment_of_Pragma_Elaborate`,
    GNAT in static mode assumes that a `pragma` Elaborate indicates correctly
    that no elaboration checks are required on calls to the designated unit.
    There may be cases in which the caller knows that no transitive calls
    can occur, so that a `pragma Elaborate` will be sufficient in a
    case where `pragma Elaborate_All` would cause a circularity.

  These five cases are listed in order of decreasing safety, and therefore
  require increasing programmer care in their application. Consider the
  following program:

  .. code-block:: ada

        package Pack1 is
          function F1 return Integer;
          X1 : Integer;
        end Pack1;

        package Pack2 is
          function F2 return Integer;
          function Pure (x : integer) return integer;
          --  pragma Suppress (Elaboration_Check, On => Pure);  -- (3)
          --  pragma Suppress (Elaboration_Check);              -- (4)
        end Pack2;

        with Pack2;
        package body Pack1 is
          function F1 return Integer is
          begin
            return 100;
          end F1;
          Val : integer := Pack2.Pure (11);    --  Elab. call (1)
        begin
          declare
            --  pragma Suppress(Elaboration_Check, Pack2.F2);   -- (1)
            --  pragma Suppress(Elaboration_Check);             -- (2)
          begin
            X1 := Pack2.F2 + 1;                --  Elab. call (2)
          end;
        end Pack1;

        with Pack1;
        package body Pack2 is
          function F2 return Integer is
          begin
             return Pack1.F1;
          end F2;
          function Pure (x : integer) return integer is
          begin
             return x ** 3 - 3 * x;
          end;
        end Pack2;

        with Pack1, Ada.Text_IO;
        procedure Proc3 is
        begin
          Ada.Text_IO.Put_Line(Pack1.X1'Img); -- 101
        end Proc3;

  In the absence of any pragmas, an attempt to bind this program produces
  the following diagnostics::

       error: elaboration circularity detected
       info:    "pack1 (body)" must be elaborated before "pack1 (body)"
       info:       reason: Elaborate_All probably needed in unit "pack1 (body)"
       info:       recompile "pack1 (body)" with -gnatel for full details
       info:          "pack1 (body)"
       info:             must be elaborated along with its spec:
       info:          "pack1 (spec)"
       info:             which is withed by:
       info:          "pack2 (body)"
       info:             which must be elaborated along with its spec:
       info:          "pack2 (spec)"
       info:             which is withed by:
       info:          "pack1 (body)"

  The sources of the circularity are the two calls to `Pack2.Pure` and
  `Pack2.F2` in the body of `Pack1`. We can see that the call to
  F2 is safe, even though F2 calls F1, because the call appears after the
  elaboration of the body of F1. Therefore the pragma (1) is safe, and will
  remove the warning on the call. It is also possible to use pragma (2)
  because there are no other potentially unsafe calls in the block.

  The call to `Pure` is safe because this function does not depend on the
  state of `Pack2`. Therefore any call to this function is safe, and it
  is correct to place pragma (3) in the corresponding package spec.

  Finally, we could place pragma (4) in the spec of `Pack2` to disable
  warnings on all calls to functions declared therein. Note that this is not
  necessarily safe, and requires more detailed examination of the subprogram
  bodies involved. In particular, a call to `F2` requires that `F1`
  be already elaborated.

It is hard to generalize on which of these four approaches should be
taken. Obviously if it is possible to fix the program so that the default
treatment works, this is preferable, but this may not always be practical.
It is certainly simple enough to use *-gnatE*
but the danger in this case is that, even if the GNAT binder
finds a correct elaboration order, it may not always do so,
and certainly a binder from another Ada compiler might not. A
combination of testing and analysis (for which the
information messages generated with the *-gnatel*
switch can be useful) must be used to ensure that the program is free
of errors. One switch that is useful in this testing is the
*-p (pessimistic elaboration order)* switch for `gnatbind`.
Normally the binder tries to find an order that has the best chance
of avoiding elaboration problems. However, if this switch is used, the binder
plays a devil's advocate role, and tries to choose the order that
has the best chance of failing. If your program works even with this
switch, then it has a better chance of being error free, but this is still
not a guarantee.

For an example of this approach in action, consider the C-tests (executable
tests) from the ACATS suite. If these are compiled and run with the default
treatment, then all but one of them succeed without generating any error
diagnostics from the binder. However, there is one test that fails, and
this is not surprising, because the whole point of this test is to ensure
that the compiler can handle cases where it is impossible to determine
a correct order statically, and it checks that an exception is indeed
raised at run time.

This one test must be compiled and run using the *-gnatE*
switch, and then it passes. Alternatively, the entire suite can
be run using this switch. It is never wrong to run with the dynamic
elaboration switch if your code is correct, and we assume that the
C-tests are indeed correct (it is less efficient, but efficiency is
not a factor in running the ACATS tests.)


.. _Elaboration_for_Indirect_Calls:

Elaboration for Indirect Calls
==============================

.. index:: Dispatching calls
.. index:: Indirect calls

In rare cases, the static elaboration model fails to prevent
dispatching calls to not-yet-elaborated subprograms. In such cases, we
fall back to run-time checks; premature calls to any primitive
operation of a tagged type before the body of the operation has been
elaborated will raise `Program_Error`.

Access-to-subprogram types, however, are handled conservatively in many
cases. This was not true in earlier versions of the compiler; you can use
the *-gnatd.U* debug switch to revert to the old behavior if the new
conservative behavior causes elaboration cycles. Here, 'conservative' means
that if you do `P'Access` during elaboration, the compiler will normally
assume that you might call `P` indirectly during elaboration, so it adds an
implicit `pragma Elaborate_All` on the library unit containing `P`. The
*-gnatd.U* switch is safe if you know there are no such calls. If the
program worked before, it will continue to work with *-gnatd.U*. But beware
that code modifications such as adding an indirect call can cause erroneous
behavior in the presence of *-gnatd.U*.

These implicit Elaborate_All pragmas are not added in all cases, because
they cause elaboration cycles in certain common code patterns. If you want
even more conservative handling of P'Access, you can use the *-gnatd.o*
switch.

See `debug.adb` for documentation on the *-gnatd...* debug switches.


.. _Summary_of_Procedures_for_Elaboration_Control:

Summary of Procedures for Elaboration Control
=============================================

.. index:: Elaboration control

First, compile your program with the default options, using none of
the special elaboration-control switches. If the binder successfully
binds your program, then you can be confident that, apart from issues
raised by the use of access-to-subprogram types and dynamic dispatching,
the program is free of elaboration errors. If it is important that the
program be portable to other compilers than GNAT, then use the
*-gnatel*
switch to generate messages about missing `Elaborate` or
`Elaborate_All` pragmas, and supply the missing pragmas.

If the program fails to bind using the default static elaboration
handling, then you can fix the program to eliminate the binder
message, or recompile the entire program with the
*-gnatE* switch to generate dynamic elaboration checks,
and, if you are sure there really are no elaboration problems,
use a global pragma `Suppress (Elaboration_Check)`.


.. _Other_Elaboration_Order_Considerations:

Other Elaboration Order Considerations
======================================

This section has been entirely concerned with the issue of finding a valid
elaboration order, as defined by the Ada Reference Manual. In a case
where several elaboration orders are valid, the task is to find one
of the possible valid elaboration orders (and the static model in GNAT
will ensure that this is achieved).

The purpose of the elaboration rules in the Ada Reference Manual is to
make sure that no entity is accessed before it has been elaborated. For
a subprogram, this means that the spec and body must have been elaborated
before the subprogram is called. For an object, this means that the object
must have been elaborated before its value is read or written. A violation
of either of these two requirements is an access before elaboration order,
and this section has been all about avoiding such errors.

In the case where more than one order of elaboration is possible, in the
sense that access before elaboration errors are avoided, then any one of
the orders is 'correct' in the sense that it meets the requirements of
the Ada Reference Manual, and no such error occurs.

However, it may be the case for a given program, that there are
constraints on the order of elaboration that come not from consideration
of avoiding elaboration errors, but rather from extra-lingual logic
requirements. Consider this example:

.. code-block:: ada

     with Init_Constants;
     package Constants is
        X : Integer := 0;
        Y : Integer := 0;
     end Constants;

     package Init_Constants is
        procedure P; --* require a body*
     end Init_Constants;

     with Constants;
     package body Init_Constants is
        procedure P is begin null; end;
     begin
        Constants.X := 3;
        Constants.Y := 4;
     end Init_Constants;

     with Constants;
     package Calc is
        Z : Integer := Constants.X + Constants.Y;
     end Calc;

     with Calc;
     with Text_IO; use Text_IO;
     procedure Main is
     begin
        Put_Line (Calc.Z'Img);
     end Main;

In this example, there is more than one valid order of elaboration. For
example both the following are correct orders::

     Init_Constants spec
     Constants spec
     Calc spec
     Init_Constants body
     Main body

and

::

    Init_Constants spec
    Constants spec
    Init_Constants body
    Calc spec
    Main body

There is no language rule to prefer one or the other, both are correct
from an order of elaboration point of view. But the programmatic effects
of the two orders are very different. In the first, the elaboration routine
of `Calc` initializes `Z` to zero, and then the main program
runs with this value of zero. But in the second order, the elaboration
routine of `Calc` runs after the body of Init_Constants has set
`X` and `Y` and thus `Z` is set to 7 before `Main` runs.

One could perhaps by applying pretty clever non-artificial intelligence
to the situation guess that it is more likely that the second order of
elaboration is the one desired, but there is no formal linguistic reason
to prefer one over the other. In fact in this particular case, GNAT will
prefer the second order, because of the rule that bodies are elaborated
as soon as possible, but it's just luck that this is what was wanted
(if indeed the second order was preferred).

If the program cares about the order of elaboration routines in a case like
this, it is important to specify the order required. In this particular
case, that could have been achieved by adding to the spec of Calc:

.. code-block:: ada

     pragma Elaborate_All (Constants);

which requires that the body (if any) and spec of `Constants`,
as well as the body and spec of any unit |withed| by
`Constants` be elaborated before `Calc` is elaborated.

Clearly no automatic method can always guess which alternative you require,
and if you are working with legacy code that had constraints of this kind
which were not properly specified by adding `Elaborate` or
`Elaborate_All` pragmas, then indeed it is possible that two different
compilers can choose different orders.

However, GNAT does attempt to diagnose the common situation where there
are uninitialized variables in the visible part of a package spec, and the
corresponding package body has an elaboration block that directly or
indirectly initializes one or more of these variables. This is the situation
in which a pragma Elaborate_Body is usually desirable, and GNAT will generate
a warning that suggests this addition if it detects this situation.

The `gnatbind` *-p* switch may be useful in smoking
out problems. This switch causes bodies to be elaborated as late as possible
instead of as early as possible. In the example above, it would have forced
the choice of the first elaboration order. If you get different results
when using this switch, and particularly if one set of results is right,
and one is wrong as far as you are concerned, it shows that you have some
missing `Elaborate` pragmas. For the example above, we have the
following output:

.. code-block:: sh

     $ gnatmake -f -q main
     $ main
      7
     $ gnatmake -f -q main -bargs -p
     $ main
      0

It is of course quite unlikely that both these results are correct, so
it is up to you in a case like this to investigate the source of the
difference, by looking at the two elaboration orders that are chosen,
and figuring out which is correct, and then adding the necessary
`Elaborate` or `Elaborate_All` pragmas to ensure the desired order.


.. _Determining_the_Chosen_Elaboration_Order:

Determining the Chosen Elaboration Order
========================================

To see the elaboration order that the binder chooses, you can look at
the last part of the file:`b~xxx.adb` binder output file. Here is an example::

     System.Soft_Links'Elab_Body;
     E14 := True;
     System.Secondary_Stack'Elab_Body;
     E18 := True;
     System.Exception_Table'Elab_Body;
     E24 := True;
     Ada.Io_Exceptions'Elab_Spec;
     E67 := True;
     Ada.Tags'Elab_Spec;
     Ada.Streams'Elab_Spec;
     E43 := True;
     Interfaces.C'Elab_Spec;
     E69 := True;
     System.Finalization_Root'Elab_Spec;
     E60 := True;
     System.Os_Lib'Elab_Body;
     E71 := True;
     System.Finalization_Implementation'Elab_Spec;
     System.Finalization_Implementation'Elab_Body;
     E62 := True;
     Ada.Finalization'Elab_Spec;
     E58 := True;
     Ada.Finalization.List_Controller'Elab_Spec;
     E76 := True;
     System.File_Control_Block'Elab_Spec;
     E74 := True;
     System.File_Io'Elab_Body;
     E56 := True;
     Ada.Tags'Elab_Body;
     E45 := True;
     Ada.Text_Io'Elab_Spec;
     Ada.Text_Io'Elab_Body;
     E07 := True;

Here Elab_Spec elaborates the spec
and Elab_Body elaborates the body. The assignments to the :samp:`E{xx}` flags
flag that the corresponding body is now elaborated.

You can also ask the binder to generate a more
readable list of the elaboration order using the
`-l` switch when invoking the binder. Here is
an example of the output generated by this switch::

     ada (spec)
     interfaces (spec)
     system (spec)
     system.case_util (spec)
     system.case_util (body)
     system.concat_2 (spec)
     system.concat_2 (body)
     system.concat_3 (spec)
     system.concat_3 (body)
     system.htable (spec)
     system.parameters (spec)
     system.parameters (body)
     system.crtl (spec)
     interfaces.c_streams (spec)
     interfaces.c_streams (body)
     system.restrictions (spec)
     system.restrictions (body)
     system.standard_library (spec)
     system.exceptions (spec)
     system.exceptions (body)
     system.storage_elements (spec)
     system.storage_elements (body)
     system.secondary_stack (spec)
     system.stack_checking (spec)
     system.stack_checking (body)
     system.string_hash (spec)
     system.string_hash (body)
     system.htable (body)
     system.strings (spec)
     system.strings (body)
     system.traceback (spec)
     system.traceback (body)
     system.traceback_entries (spec)
     system.traceback_entries (body)
     ada.exceptions (spec)
     ada.exceptions.last_chance_handler (spec)
     system.soft_links (spec)
     system.soft_links (body)
     ada.exceptions.last_chance_handler (body)
     system.secondary_stack (body)
     system.exception_table (spec)
     system.exception_table (body)
     ada.io_exceptions (spec)
     ada.tags (spec)
     ada.streams (spec)
     interfaces.c (spec)
     interfaces.c (body)
     system.finalization_root (spec)
     system.finalization_root (body)
     system.memory (spec)
     system.memory (body)
     system.standard_library (body)
     system.os_lib (spec)
     system.os_lib (body)
     system.unsigned_types (spec)
     system.stream_attributes (spec)
     system.stream_attributes (body)
     system.finalization_implementation (spec)
     system.finalization_implementation (body)
     ada.finalization (spec)
     ada.finalization (body)
     ada.finalization.list_controller (spec)
     ada.finalization.list_controller (body)
     system.file_control_block (spec)
     system.file_io (spec)
     system.file_io (body)
     system.val_uns (spec)
     system.val_util (spec)
     system.val_util (body)
     system.val_uns (body)
     system.wch_con (spec)
     system.wch_con (body)
     system.wch_cnv (spec)
     system.wch_jis (spec)
     system.wch_jis (body)
     system.wch_cnv (body)
     system.wch_stw (spec)
     system.wch_stw (body)
     ada.tags (body)
     ada.exceptions (body)
     ada.text_io (spec)
     ada.text_io (body)
     text_io (spec)
     gdbstr (body)
