[GNAT] This restriction ensures at compile time that no elaboration code is
generated. Note that this is not the same condition as is enforced
Preelaborate. There are cases in which pragma
Preelaborate still permits code to be generated (e.g., code
to initialize a large array to all zeroes), and there are cases of units
which do not meet the requirements for pragma
but for which no elaboration code is generated. Generally, it is
the case that preelaborable units will meet the restrictions, with
the exception of large aggregates initialized with an others_clause,
and exception declarations (which generate calls to a run-time
registry procedure). This restriction is enforced on
a unit by unit basis, it need not be obeyed consistently
throughout a partition.
In the case of aggregates with others, if the aggregate has a dynamic
size, there is no way to eliminate the elaboration code (such dynamic
bounds would be incompatible with
Preelaborate in any case). If
the bounds are static, then use of this restriction actually modifies
the code choice of the compiler to avoid generating a loop, and instead
generate the aggregate statically if possible, no matter how many times
the data for the others clause must be repeatedly generated.
It is not possible to precisely document the constructs which are compatible with this restriction, since, unlike most other restrictions, this is not a restriction on the source code, but a restriction on the generated object code. For example, if the source contains a declaration:
Val : constant Integer := X;
where X is not a static constant, it may be possible, depending on complex optimization circuitry, for the compiler to figure out the value of X at compile time, in which case this initialization can be done by the loader, and requires no initialization code. It is not possible to document the precise conditions under which the optimizer can figure this out.
Note that this the implementation of this restriction requires full code generation. If it is used in conjunction with “semantics only” checking, then some cases of violations may be missed.
When this restriction is active, we are not requesting control-flow preservation with -fpreserve-control-flow, and the static elaboration model is used, the compiler is allowed to suppress the elaboration counter normally associated with the unit. This counter is typically used to check for access before elaboration and to control multiple elaboration attempts.