Record representation clauses may be given for all record types, including types obtained by record extension. Component clauses are allowed for any static component. The restrictions on component clauses depend on the type of the component.
For all components of an elementary type, the only restriction on component clauses is that the size must be at least the 'Size value of the type (actually the Value_Size). There are no restrictions due to alignment, and such components may freely cross storage boundaries.
Packed arrays with a size up to and including 64 bits are represented internally using a modular type with the appropriate number of bits, and thus the same lack of restriction applies. For example, if you declare:
type R is array (1 .. 49) of Boolean; pragma Pack (R); for R'Size use 49;
then a component clause for a component of type R may start on any specified bit boundary, and may specify a value of 49 bits or greater.
Packed bit arrays that are longer than 64 bits must always be placed on a storage unit (byte) boundary. Any component clause that does not meet this requirement will be rejected.
The rules for other types are different for GNAT 3 and GNAT 5 versions (based on GCC 2 and GCC 3 respectively). In GNAT 5, larger components (other than packed arrays) may also be placed on arbitrary boundaries, so for example, the following is permitted:
type R is array (1 .. 10) of Boolean; for R'Size use 80; type Q is record G, H : Boolean; L, M : R; end record; for Q use record G at 0 range 0 .. 0; H at 0 range 1 .. 1; L at 0 range 2 .. 81; R at 0 range 82 .. 161; end record;
In GNAT 3, there are more severe restrictions on larger components. For non-primitive types, including packed arrays with a size greater than 64 bits, component clauses must respect the alignment requirement of the type, in particular, always starting on a byte boundary, and the length must be a multiple of the storage unit.
The following rules regarding tagged types are enforced in both GNAT 3 and GNAT 5:
The tag field of a tagged type always occupies an address sized field at the start of the record. No component clause may attempt to overlay this tag.
In the case of a record extension T1, of a type T, no component clause applied to the type T1 can specify a storage location that would overlap the first T'Size bytes of the record.