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:
with'ed unit, or instantiate a generic package in a
with'ed unit, then if the
with'ed unit does not have pragma
Preelaborate, then the client should have an
Elaborate_Allpragma for the
In the case of instantiating a generic subprogram, it is always
sufficient to have only an
Elaborate pragma for the
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
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_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_All pragmas so portability to other compilers than GNAT is not
If it is important to guarantee portability, then the compilations should
(warn on elaboration problems) switch. This will cause warning messages
to be generated indicating the missing
Consider the following source program:
|with k; package j is m : integer := k.r; end;|
where it is clear that there
should be a pragma
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
switch, then the compiler outputs a warning:
|1. with k; 2. package j is 3. m : integer := k.r; | >>> warning: call to "r" may raise Program_Error >>> warning: missing pragma Elaborate_All for "k" 4. end;|
and these warnings can be used as a guide for supplying manually
the missing pragmas. It is usually a bad idea to use this warning
option during development. That's because it will warn you when
you need to put in a pragma, but cannot warn 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:
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 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.