Next: , Previous: Checking the Elaboration Order, Up: Elaboration Order Handling in GNAT


11.3 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:

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:

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:

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.