13.1 Operational and Representation Aspects
{
8652/0009}
{
AI95-00137-01}
{
AI05-0295-1}
[
Two kinds of aspects of entities can be specified:
representation aspects and operational aspects. Representation aspects
affect how the types and other entities of the language are to be mapped
onto the underlying machine. Operational aspects determine other properties
of entities.]
Term entry: operational
aspect — aspect that indicates a logical property of an entity,
such as the precondition of a subprogram, or the procedure used to write
a given type of object to a stream
Term entry: representation
aspect — aspect that indicates how an entity is mapped onto
the underlying hardware, for example the size or alignment of an object
{
AI05-0183-1}
{
AI05-0295-1}
[Either kind of aspect of an entity may be specified by means of an
aspect_specification
(see
13.1.1), which is an optional element
of most kinds of declarations and applies to the entity or entities being
declared. Aspects may also be specified by certain other constructs occurring
subsequent to the declaration of the affected entity: a representation
aspect value may be specified by means of a representation item and an
operational aspect value may be specified by means of an operational
item.]
{
8652/0009}
{
AI95-00137-01}
[An operational item or a representation item applies to an entity identified
by a
local_name,
which denotes an entity declared local to the current declarative region,
or a library unit declared immediately preceding a representation pragma
in a
compilation.]
Language Design Principles
{
8652/0009}
{
AI95-00137-01}
{
AI05-0295-1}
Representation aspects are intended to refer to properties that need
to be known before the compiler can generate code to create or access
an entity. For instance, the size of an object needs to be known before
the object can be created. Conversely, operational aspects are those
that only need to be known before they can be used. For instance, how
an object is read from a stream only needs to be known when a stream
read is executed. Thus, representation aspects have stricter rules as
to when they can be specified.
{
AI95-00291-02}
{
AI05-0295-1}
Confirming the value of an aspect should never change the semantics of
the aspect. Thus Size = 8 (for example) means the same thing whether
it was specified with a representation item or whether the compiler chose
this value by default.
Term entry: aspect
— specifiable property of an entity
Note: An aspect can be specified by an aspect_specification
on the declaration of the entity. Some aspects can be queried via attributes.
Syntax
Name Resolution Rules
{
8652/0009}
{
AI95-00137-01}
In an operational item or representation item, if the
local_name
is a
direct_name,
then it shall resolve to denote a declaration (or, in the case of a
pragma,
one or more declarations) that occurs immediately within the same declarative
region as the item. If the
local_name
has an
attribute_designator,
then it shall resolve to denote an implementation-defined component (see
13.5.1) or a class-wide type implicitly
declared immediately within the same declarative region as the item.
A
local_name
that is a
library_unit_name
(only permitted in a representation pragma) shall resolve to denote the
library_item
that immediately precedes (except for other pragmas) the representation
pragma.
Reason: {
8652/0009}
{
AI95-00137-01}
This is a Name Resolution Rule, because we don't want an operational
or representation item for X to be ambiguous just because there's another
X declared in an outer declarative region. It doesn't make much difference,
since most operational or representation items are for types or subtypes,
and type and subtype names can't be overloaded.
Ramification: {
8652/0009}
{
AI95-00137-01}
The visibility rules imply that the declaration has to occur before the
operational or representation item.
{
8652/0009}
{
AI95-00137-01}
For objects, this implies that operational or representation items can
be applied only to stand-alone objects.
Legality Rules
Ramification: The “statically denote”
part implies that it is impossible to specify the representation of an
object that is not a stand-alone object, except in the case of a representation
item like pragma Atomic that is allowed inside a
component_list
(in which case the representation item specifies the representation of
components of all objects of the type). It also prevents the problem
of renamings of things like “P.
all” (where P is an
access-to-subprogram value) or “E(I)” (where E is an entry
family).
The part about where the denoted entity has
to have been declared appears twice — once as a Name Resolution
Rule, and once as a Legality Rule. Suppose P renames Q, and we have a
representation item in a
declarative_part
whose
local_name
is P. The fact that the representation item has to appear in the same
declarative_part
as P is a Name Resolution Rule, whereas the fact that the representation
item has to appear in the same
declarative_part
as Q is a Legality Rule. This is subtle, but it seems like the least
confusing set of rules.
{
AI95-00291-02}
{
AI12-0445-1}
The
representation of
an object consists of a certain number of bits (the
size of the
object). For an object of an elementary type, these are the bits that
are normally read or updated by the machine code when loading, storing,
or operating-on the value of the object. For an object of a composite
type, these are the bits reserved for this object, and include bits occupied
by subcomponents of the object. If the size of an object is greater than
that of its subtype, the additional bits are padding bits.
For
an elementary object, these padding bits are normally read and updated
along with the others. For a composite object,
it
is unspecified whether padding bits
are might
not be read or updated in any given composite operation
,
depending on the implementation.
To be honest: {
AI95-00291-02}
Discontiguous representations
are allowed, but the ones we're interested in here are generally contiguous
sequences of bits. For a discontiguous representation, the size doesn't
necessarily describe the “footprint” of the object in memory
(that is, the amount of space taken in the address space for the object).
Discussion: {
AI95-00291-02}
In the case of composite objects, we want the implementation to have
the flexibility to either do operations component-by-component, or with
a block operation covering all of the bits. We carefully avoid giving
a preference in the wording. There is no requirement for the choice to
be documented, either, as the implementation can make that choice based
on many factors, and could make a different choice for different operations
on the same object.
{
AI95-00291-02}
In the case of a properly aligned, contiguous object whose size is a
multiple of the storage unit size, no other bits should be read or updated
as part of operating on the object. We don't say this normatively because
it would be difficult to normatively define “properly aligned”
or “contiguous”.
Ramification:
Two objects with the same value do not necessarily have the same
representation. For example, an implementation might represent False
as zero and True as any odd value. Similarly, two objects (of the same
type) with the same sequence of bits do not necessarily have the same
value. For example, an implementation might use a biased representation
in some cases but not others:
{
AI05-0229-1}
subtype S
is Integer
range 1..256;
type A
is array(Natural
range 1..4)
of S
with Pack;
X : S := 3;
Y : A := (1, 2, 3, 4);
The implementation might use a biased-by-1 representation
for the array elements, but not for X. X and Y(3) have the same value,
but different representation: the representation of X is a sequence of
(say) 32 bits: 0...011, whereas the representation of Y(3) is a sequence
of 8 bits: 00000010 (assuming a two's complement representation).
Such tricks are not required, but are allowed.
Discussion: The value of any padding
bits is not specified by the language, though for a numeric type, it
will be much harder to properly implement the predefined operations if
the padding bits are not either all zero, or a sign extension.
Ramification: {
AI05-0229-1}
For example, suppose S'Size = 2, and an object X is of subtype S. If
the machine code typically uses a 32-bit load instruction to load the
value of X, then X'Size should be 32, even though 30 bits of the value
are just zeros or sign-extension bits. On the other hand, if the machine
code typically masks out those 30 bits, then X'Size should be 2. Usually,
such masking only happens for components of a composite type for which
Pack, Component_Size, or record layout is specified.
Note, however, that the formal parameter of
an instance of Unchecked_Conversion is a special case. Its Size is required
to be the same as that of its subtype.
Note that we don't generally talk about the
representation of a value. A value is considered to be an amorphous blob
without any particular representation. An object is considered to be
more concrete.
{
AI05-0112-1}
{
AI05-0295-1}
{
AI12-0396-1}
{
AI12-0407-1}
A representation
item
directly specifies a
representation aspect of the
entity denoted by the
local_name,
except in the case of a type-related representation item, whose
local_name
shall denote a first subtype, and which directly specifies an aspect
of the subtype's type.
A
representation item that names a subtype is either
subtype-specific
(Size
, Object_Size, and Alignment clauses)
or
type-related (all others).
[Subtype-specific
aspects may differ for different subtypes of the same type.]
This paragraph
was deleted.To be honest: {
AI12-0407-1}
Type-related and subtype-specific
are defined likewise for the corresponding aspects of representation.
To be honest: Some representation items
directly specify more than one aspect.
Discussion: {
AI05-0229-1}
For example, a
pragma
Export (see
J.15.5) specifies the convention
of an entity, and also specifies that it is exported. Such items are
obsolescent; directly specifying the associated aspects is preferred.
{
AI05-0112-1}
We give a default naming for representation aspects of representation
pragmas so we don't have to do that for every pragma. Operational and
representation attributes are given a default naming in
13.3.
We don't want any anonymous aspects; that would make other rules more
difficult to write and understand.
Ramification:
The following representation items are type-related:
Component_Size clause
Small clause
Bit_Order clause
Storage_Pool clause
Storage_Size clause
Machine_Radix clause
pragma Pack
pragmas Import, Export, and Convention (when
applied to a type)
{
AI05-0009-1}
pragmas Atomic, Independent, and Volatile (when applied to a type)
{
AI05-0009-1}
pragmas Atomic_Components, Independent_Components, and Volatile_Components
(when applied to a type)
pragma Discard_Names (when applied to an enumeration
or tagged type)
{
AI12-0005-1}
pragmas Priority and Interrupt_Priority (when applied
to a task or protected type)
{
AI12-0005-1}
pragma CPU (when applied to a task or protected
type)
{
AI12-0005-1}
pragma Relative_Deadline (when applied to a task
or protected type)
The following
representation items are subtype-specific:
Alignment clause (when applied to a first
subtype)
Size clause (when applied to a first subtype)
The following
representation items do not apply to subtypes, so they are neither type-related
nor subtype-specific:
Address clause (applies to objects and program
units)
Alignment clause (when applied to an object)
Size clause (when applied to an object)
pragmas Import, Export, and Convention (when
applied to anything other than a type)
pragmas Atomic and Volatile (when applied
to an object or a component)
{
AI05-0009-1}
pragmas Atomic_Components, Independent_Components, and Volatile_Components
(when applied to an array object)
pragma Discard_Names (when applied to an exception)
pragma Asynchronous (applies to procedures)
{
AI12-0005-1}
pragmas Attach_Handler and Interrupt_Handler (apply
to protected units)
{
AI12-0005-1}
pragmas Priority and Interrupt_Priority (when applied
to a subprogram)
{
AI12-0005-1}
pragma CPU (when applied to a subprogram)
{
AI12-0005-1}
pragma Relative_Deadline (when applied to a subprogram)
{
AI05-0229-1}
{
AI12-0005-1}
While an
aspect_specification
is not a representation item, a similar categorization applies to the
aspect that corresponds to each of these representation items
.
In addition, there are representation (along
with aspects that do not have associated representation items
).
{
AI12-0005-1}
The following representation aspects that do not
have associated representation items are type-related:
aspect Default_Value
aspect Default_Component_Value
aspect Exclusive_Functions
aspects Link_Name and
External_Name (when applied to a type)
aspect Max_Entry_Queue_Length
(when applied to a task or protected type)
{
AI12-0005-1}
There are no subtype-specific representation aspects
that do not have associated representation items.
{
AI12-0005-1}
The following representation aspects that do not
have associated representation items also do not apply to subtypes, so
they are neither type-related nor subtype-specific:
aspect Static (applies
to expression functions)
aspect Synchronization
(applies to procedures)
aspects Link_Name and
External_Name (when applied to anything other than a type)
aspect Max_Entry_Queue_Length
(when applied to an entry)
{
8652/0009}
{
AI95-00137-01}
{
AI05-0183-1}
An operational item
directly specifies an
operational aspect
of the entity denoted by the
local_name,
except in the case of a type-related operational item, whose
local_name
shall denote a first subtype, and which directly specifies an aspect
of the type of the subtype.
External_Tag clause
Read clause
Write clause
Input clause
Output clause
{
AI12-0407-1}
Aspects that can be specified for types and subtypes
are also classified into type-related or subtype-specific aspects. Representation
aspects that can be specified for types and subtypes are considered type-related
unless specified otherwise. In contrast, the classification of operational
aspects are given with the definition of the aspect. Type-related aspects
have the same value for all subtypes of (a view of) a type[, while subtype-specific
aspects may differ for different subtypes of the same type].
Discussion: We
talk about “type-related aspects”, which of course include
both type-related representation aspects and type-related operational
aspects. Aspects Size, Object_Size, and Alignment are subtype-specific,
as that is specified above. All other representation aspects are either
type-related or not specifiable for a type or subtype. Unlike representation
aspects, there is no default for operational aspects; whether they are
type-related or subtype-specific should be part of the definition of
the aspect.
{
AI05-0183-1}
{
AI12-0116-1}
{
AI12-0181-1}
{
AI12-0222-1}
A representation item or operational item that
directly specifies an aspect of an entity shall appear before the entity
is frozen (see 13.14). A representation item that directly specifies an aspect of a subtype
or type shall appear after the type is completely defined (see 3.11.1)
and before the subtype or type is frozen (see 13.14). If a representation item or aspect_specification
is given that directly specifies an aspect of an entity, then it is illegal
to give another representation item or aspect_specification
that directly specifies the same aspect of the entity.
Ramification: {
8652/0009}
{
AI95-00137-01}
{
AI12-0222-1}
The fact that a representation item (or operational item
,
see next paragraph) that directly specifies an aspect of an entity
is required to appear before the entity is frozen prevents changing the
representation of an entity after using the entity in ways that require
the representation to be known.
This paragraph
was deleted.To be honest: {
AI05-0183-1}
{
AI12-0116-1}
The rule preventing multiple specification is also
intended to cover other ways to specify representation aspects, such
as obsolescent pragma
Priority. Priority is not a representation pragma, and as such is neither
a representation item nor an aspect_specification.
Regardless, giving both a pragma
Priority and an aspect_specification
for Priority is illegal. We didn't want to complicate the wording solely
to support obsolescent features.
Ramification: Unlike representation items,
operational items can be specified on partial views. Since they don't
affect the representation, the full declaration need not be known to
determine their legality.
Ramification: {
AI12-0116-1}
{
AI12-0396-1}
This rule applies to all aspects, not just those
that have are operational items aspects or representation items aspects.
For instance, it applies to subtype predicates and type invariants.
To be honest: {
AI12-0116-1}
This rule is also intended to cover other ways
to specify representation aspects, such as obsolescent pragma
Priority. Priority is not a representation pragma, and as such is neither
a representation item nor an aspect_specification.
Regardless, giving both a pragma
Priority and an aspect_specification
for Priority is illegal. We didn't want to complicate the wording solely
to support obsolescent features.
Reason: {
AI12-0064-2}
Specifying an aspect on a generic formal parameter implies an added contract
for a generic unit. That contract needs to be defined via generic parameter
matching rules, and, as aspects vary widely, that has to be done for
each such aspect. Since most aspects do not need this complexity
(including all language-defined aspects as of this writing), we
avoid the complexity by saying that such contract-forming aspect specifications
are banned unless the rules defining them explicitly exist. Note that
the method of specification does not matter:
aspect_specifications,
representation items, and operational items are all covered by this
rule(and
similar) rules.
{
AI05-0295-1}
{
AI12-0109-1}
{
AI12-0376-1}
{
AI12-0427-1}
A by-reference primitive
is a user-defined primitive subprogram for a type T that has an
access result designating type T, or that has a formal parameter
that is an access parameter designating type T or is aliased and
of type T. For an untagged derived
typeIt it
is illegal to specify a
nonconfirming type-related
representation aspect
for an untagged type T
if it is derived from if the parent type
is a by-reference type
or inherits one or
more by-reference primitives, or
if one
or more types has any user-defined primitive
subprograms. Similarly, it is illegal to specify a nonconfirming type-related representation
aspect for an untagged by-reference type after one or more types have been derived from T prior to
the specification of the aspect and type T is a by-reference type
or defines one or more by-reference primitives that are inherited by
these descendants it.
Ramification: {
8652/0009}
{
AI95-00137-01}
{
AI05-0295-1}
On the other hand, subtype-specific representation aspects may be specified
for the first subtype of such a type, as can operational aspects.
Reason: {
AI05-0229-1}
{
AI05-0295-1}
{
AI12-0109-1}
{
AI12-0376-1}
{
AI12-0427-1}
The reason for forbidding specification of type-related representation
aspects on untagged by-reference types is because a change of representation
is impossible when passing by reference (to an inherited subprogram).
(A by-reference object cannot be copied to change its representation.)
The reason for forbidding specification of type-related representation
aspects on untagged types with
by-reference primitives
is that access parameters, access results, and aliased parameters cannot
be converted as part of invoking an inherited subprogram if the representation
of the designated types might be different user-defined
primitive subprograms was to prevent implicit change of representation
for type-related aspects of representation upon calling inherited subprograms,
because such changes of representation are likely to be expensive at
run time. Changes of subtype-specific representation attributes, however,
are likely to be cheap. This rule is not needed for tagged types,
because other rules prevent a type-related representation aspect from
changing the representation of the parent part; we want to allow specifying
a type-related representation aspect on a type extension to specify aspects
of the extension part. For example, specifying aspect Pack will cause
packing of the extension part, but not of the parent part.
Discussion: {
AI12-0109-1}
“By-reference type” usually cannot
be used in Legality Rules, as it is privacy breaking. Our use here is
privacy breaking, but we're stuck with it for compatibility reasons.
Since representation aspects cannot be specified on partial views, privacy
violations only can happen when a type includes a component of a private
type. In that case, whether these rules are triggered depends on the
full type of the private type — which is clearly privacy breaking.
{
8652/0009}
{
AI95-00137-01}
{
8652/0011} {
AI95-00117-01}
{
AI95-00326-01}
{
AI05-0295-1}
{
AI12-0396-1}
{
AI12-0409-1}
If a type-related aspect is defined for the partial
view of a type, then it has the same definition for the full view of
the type, except for certain Boolean-valued operational aspects where
the language specifies that the partial view can have the value False
even when the full view has the value True. Type-related aspects [cannot
be specified, and] are not defined for an incomplete view of a type.
Representation Operational and representation
aspects of a generic formal parameter are the same as those of the actual.
Operational and representation aspects are the
same for all views of a type. Specification of a type-related
representation aspect is not allowed for a descendant of a generic formal
untagged type.
Ramification: {
8652/0009}
{
AI95-00137-01}
{
AI05-0295-1}
Specifying representation aspects is allowed for types whose subcomponent
types or index subtypes are generic formal types. Specifying operational
aspects and subtype-related representation aspects is allowed on descendants
of generic formal types.
Reason: {
AI05-0295-1}
Since it is not known whether a formal type has user-defined primitive
subprograms, specifying type-related representation aspects for them
is not allowed, unless they are tagged (in which case only the extension
part is affected in any case).
This paragraph
was deleted.Ramification: {
AI95-00326-01}
{
AI12-0396-1}
All views of a type, including the incomplete and
partial views, have the same operational and representation aspects.
That's important so that the properties don't change when changing views.
While most aspects are not available for an incomplete view, we don't
want to leave any holes by not saying that they are the same.
{
AI05-0083-1}
{
AI12-0396-1}
Different views of an entity can have different
representation and operational aspects. Most type-related aspects are
the same for all views of a type; but specific aspects may have different
rules. Similarly, different However, this
does not apply to objects. Different views of an object can have
different representation aspects. For instance, an actual object passed
by reference and the associated formal parameter may have different values
for Alignment even though the formal parameter is merely a view of the
actual object. This is necessary to maintain the language design principle
that Alignments are always known at compile time.
Discussion: {
AI12-0409-1}
For type-related aspects, the aspect of the partial
view (if any) and full view have to be the same, with an exception for
certain Boolean-valued aspects. The exception is intended for aspect
Preelaborable_Initialization, where it would be wildly incompatible (as
well as unfriendly) to require the (possibly implicit) state of the full
view to be repeated explicitly on the partial view. Aspect Nonblocking
has a similar rule for similar reasons, though it is a subtype-specific
aspect.
{
AI05-0295-1}
The specification of the Size aspect for a given subtype, or the size
or storage place for an object (including a component) of a given subtype,
shall allow for enough storage space to accommodate any value of the
subtype.
{
8652/0009}
{
AI95-00137-01}
{
AI05-0295-1}
{
AI12-0396-1}
{
AI12-0444-1}
The specification of certain language-defined aspects
is not required to be supported by all implementations; in such an implementation,
the specification for such an aspect If
a specification of a representation or operational aspect is not supported
by the implementation, it is illegal or raises an exception at
run time.
Ramification: There
is an Implementation Permission below that allows an implementation to
put restrictions on any representation aspect; this rule applies if that
permission is used for an aspect. This rule only applies to an operational
aspect if the aspect explicitly allows the aspect to not be supported.
{
AI95-00251-01}
{
AI05-0295-1}
A
type_declaration
is illegal if it has one or more progenitors, and a nonconfirming value
was specified for a representation aspect of an ancestor, and this conflicts
with the representation of some other ancestor. The cases that cause
conflicts are implementation defined.
Implementation defined: The cases that
cause conflicts between the representation of the ancestors of a
type_declaration.
Reason: {
AI05-0295-1}
This rule is needed because it may be the case that only the combination
of types in a type declaration causes a conflict. Thus it is not possible,
in general, to reject the original representation item or
aspect_specification.
For instance:
package Pkg1 is
type Ifc is interface;
type T is tagged record
Fld : Integer;
end record;
for T use record
Fld at 0 range 0 .. Integer'Size - 1;
end record;
end Pkg1;
Assume the implementation
uses a single tag with a default offset of zero, and that it allows the
use of nondefault locations for the tag (and thus accepts representation
items like the one above). The representation item will force a nondefault
location for the tag (by putting a component other than the tag into
the default location). Clearly, this package will be accepted by the
implementation. However, other declarations could cause trouble. For
instance, the implementation could reject:
with Pkg1;
package Pkg2 is
type NewT is new Pkg1.T and Pkg1.Ifc with null record;
end Pkg2;
{
AI05-0295-1}
because the declarations of T and Ifc have a conflict in their representation
items. This is clearly necessary (it's hard to imagine how Ifc'Class
could work with the tag at a location other than the one it is expecting
without introducing distributed overhead).
{
AI05-0295-1}
Conflicts will usually involve implementation-defined attributes (for
specifying the location of the tag, for instance), although the example
above shows that doesn't have to be the case. For this reason, we didn't
try to specify exactly what causes a conflict; it will depend on the
implementation's implementation model and what representation aspects
it allows to be changed.
Implementation Note: {
AI05-0295-1}
An implementation can only use this rule to reject
type_declarations
where one of its ancestors had a nonconfirming representation value specified.
An implementation must ensure that the default representations of ancestors
cannot conflict.
{
AI12-0427-1}
When specifying an aspect that denotes a subprogram,
the profile of the subprogram shall be mode conformant with the one required
for the aspect, and the convention shall be Ada. Additional requirements
are defined for particular aspects.
This
rule implies, for example, that if one writes:
type T is ...
with Read => R;
R has to be a procedure
with two parameters with the appropriate subtypes and modes as shown
in 13.13.2.
Static Semantics
{
AI12-0059-1}
If two subtypes statically match, then their subtype-specific aspects
(
for example, Size and Alignment) are the
same.
Reason: {
AI05-0295-1}
{
AI12-0059-1}
This is necessary because we allow (for example) conversion between access
types whose designated subtypes statically match. Note that most aspects
(including the subtype-specific aspects Size and Alignment) may not be
specified for a nonfirst subtype. The only language-defined exceptions
to this rule are the
Object_Size, Static_Predicate
,
and Dynamic_Predicate aspects.
Consider, for
example:
{
AI12-0005-1}
package P1
is
subtype S1
is Integer
range 0..2**16-1
with Size =>;
for S1'Size use 16; --
Illegal!
--
S1'Size would be 16 by default.
type A1
is access all S1;
X1: A1;
end P1;
{
AI12-0005-1}
package P2
is
subtype S2
is Integer
range 0..2**16-1
with Size =>;
for S2'Size use 32; --
Illegal!
type A2
is access all S2;
X2: A2;
end P2;
{
AI05-0229-1}
procedure Q
is
use P1, P2;
type Array1
is array(Integer
range <>)
of aliased S1
with Pack;
Obj1: Array1(1..100);
type Array2
is array(Integer
range <>)
of aliased S2
with Pack;
Obj2: Array2(1..100);
begin
X1 := Obj2(17)'Unchecked_Access;
X2 := Obj1(17)'Unchecked_Access;
end Q;
Loads and stores through X1 would read and write
16 bits, but X1 points to a 32-bit location. Depending on the endianness
of the machine, loads might load the wrong 16 bits. Stores would fail
to zero the other half in any case.
Loads and stores through X2 would read and write
32 bits, but X2 points to a 16-bit location. Thus, adjacent memory locations
would be trashed.
Hence, the above is illegal. Furthermore, the
compiler is forbidden from choosing different Sizes by default, for the
same reason.
{
AI12-0059-1}
The same issues apply to Alignment.
Similar issues
apply to Object_Size, Static_Predicate, and Dynamic_Predicate, but the
chosen solution is different: explicit rules in 4.9.1
that ensure that the aspects are the same if specified.
{
AI12-0059-1}
The above static matching rule combined with the
definition of static matching in 4.9.1 (after
updating to add Object_Size) does not cause incompatibilities in existing
Ada 2012 code that does not mention Object_Size. But it does constrain
the implementation-defined value of Object_Size when it is not specified
for a subtype; the above rule applies even in that case. (The effects
noted in the example above would occur otherwise.)
{
AI12-0059-1}
We need this rule even though static matching explicitly
excludes confirming values of Object_Size. That's because a general access
type can designate any aliased object whose subtype statically matches
the designated subtype. Since the Object_Size of a subtype determines
the number of bits allocated for an aliased object of the subtype, if
we allowed different Object_Sizes for statically matching subtypes, we'd
be allowing the access type to designate objects with differing numbers
of bits. That isn't going to work.
{
8652/0040}
{
AI95-00108-01}
{
AI05-0009-1}
{
AI05-0295-1}
A derived type inherits each type-related representation aspect of its
parent type that was directly specified before the declaration of the
derived type, or (in the case where the parent is derived) that was inherited
by the parent type from the grandparent type. A derived subtype inherits
each subtype-specific representation aspect of its parent subtype that
was directly specified before the declaration of the derived type, or
(in the case where the parent is derived) that was inherited by the parent
subtype from the grandparent subtype, but only if the parent subtype
statically matches the first subtype of the parent type. An inherited
representation aspect is overridden by a subsequent
aspect_specification
or representation item that specifies a different value for the same
aspect of the type or subtype.
To be honest: A
record_representation_clause
for a record extension does not override the layout of the parent part;
if the layout was specified for the parent type, it is inherited by the
record extension.
Ramification: If a representation item
for the parent appears after the
derived_type_definition,
then inheritance does not happen for that representation item.
{
AI05-0009-1}
{
AI05-0295-1}
If an inherited aspect is confirmed by an
aspect_specification
or a later representation item for a derived type, the confirming specification
does not override the inherited one. Thus the derived type has both a
specified confirming value and an inherited nonconfirming representation
value — this means that rules that apply only to nonconfirming
representation values still apply to this type.
{
AI12-0109-1}
If an aspect was specified by an aspect_specification
and the parent type has not yet been frozen, then the inherited aspect
might not yet have been resolved and evaluated. The implementation will
need to have a mechanism to handle such an aspect.
{
8652/0040}
{
AI95-00108-01}
{
AI95-00444-01}
{
AI05-0183-1}
{
AI05-0295-1}
{
AI12-0396-1}
In contrast, whether
type-related operational
aspects are inherited by a derived type depends on each specific aspect;
unless specified, an operational aspect is not inherited. When
type-related
operational aspects are inherited by a derived type, aspects that
were directly specified by
aspect_specifications
or operational items that are visible at
any the
point
within the immediate scope of the
derived type declaration, or (in the case where the parent is derived)
that were inherited by the parent type from the grandparent type
,
are inherited. An inherited operational aspect is overridden by
an a
subsequent aspect_specification
or operational item that specifies the same aspect of the type.
Ramification: As with representation
items, if an operational item for the parent appears after the
derived_type_definition,
then inheritance does not happen for that operational item.
{
AI12-0396-1}
Unlike representation aspects, operational aspects
can be inherited at any point in the immediate scope, and can be overridden
by aspect_specifications or operational items that occur at a point before
or after the inheritance takes place.
{
AI12-0396-1}
When a type-related operational aspect is inherited,
the rules for inheritance depend on the nature of the aspect (see 13.1.1).
Unless otherwise specified for a given aspect, these rules are as follows:
For an operational aspect
that is a value, the inherited aspect has the same value;
For
an operational aspect that is a name:
if the name
denotes one or more primitive subprograms of the type, the inherited
aspect is a name
that denotes the corresponding primitive subprogram(s) of the derived
type;
Discussion: {
AI12-0005-1}
A primitive subprogram that is declared after the
end of the enclosing declaration list of a derived type (in particular,
in the private part of a package if the derived type is declared in the
package's visible part) is not the “corresponding primitive subprogram”
in the sense of this rule. In a case like this, the corresponding primitive
subprogram is actually the inherited subprogram. This doesn't make a
difference for tagged types, because of the “dispatching”
semantics used, which means a call on the inherited subprogram actually
“reaches” the body of the overriding. But for untagged types,
overriding an inherited subprogram of an untagged derived type in the
private part is “too late” to have an effect on external
uses of the primitive, since non-visible overridings are not generally
reachable, and a call that only “sees” the inherited subprogram
goes to the body of the parent's operation, effectively ignoring the
private overriding. This same rule applies to aspects that denote an
inherited subprogram of an untagged derived type — the private
overriding is effectively ignored.
otherwise, the inherited
aspect is a name
that denotes the same entity or entities as the original aspect;
{
AI12-0396-1}
{
AI12-0423-1}
For an operational aspect that is an identifier
specific to the aspect, the inherited aspect is the same identifier;
{
AI95-00444-01}
{
AI12-0419-1}
When an aspect that is a subprogram is inherited,
the derived type inherits the aspect in the same way that a derived type
inherits a user-defined primitive subprogram from its parent (see 3.4).
Reason: This defines
the parameter names and types, and the needed implicit conversions.
Each aspect of representation
of an entity is as follows:
If the aspect is
specified
for the entity, meaning that it is either directly specified or inherited,
then that aspect of the entity is as specified, except in the case of
Storage_Size, which specifies a minimum.
Ramification: This rule implies that
queries of the aspect return the specified value. For example, if the
user writes “for X'Size use 32;”, then a query
of X'Size will return 32.
If an aspect of representation
of an entity is not specified, it is chosen by default in an unspecified
manner.
The rules forbid things like “for
S'Base'Alignment use ...” and “for S'Base use
record ...”.
Discussion: The intent is that implementations
will represent the components of a composite value in the same way for
all subtypes of a given composite type. Hence, Component_Size and record
layout are type-related aspects.
Ramification: {
AI05-0083-1}
As noted previously, in the case of an object, the entity mentioned in
this text is a specific view of an object. That means that only references
to the same view of an object that has a specified value for a representation
aspect
R necessarily have that value for the aspect
R.
The value of the aspect
R for a different view of that object
is unspecified. In particular, this means that the representation values
for by-reference parameters is unspecified; they do not have to be the
same as those of the underlying object.
{
8652/0040}
{
AI95-00108-01}
{
AI12-0396-1}
If an operational aspect is
specified for
an entity (meaning that it is either directly specified or
,
if type-related or subtype-specific, inherited), then that aspect
of the entity is as specified. Otherwise, the aspect of the entity has
the default value for that aspect.
[ For aspects
that are neither type-related nor subtype-specific, the terms “specified”
and “directly specified” are equivalent.]
Proof: {
AI12-0396-1}
Aspect inheritance is only defined for types and
subtypes.
{
AI95-00291-02}
{
AI05-0295-1}
{
AI12-0396-1}
An
aspect_specification
or representation item that specifies a representation aspect that would
have been chosen in the absence of the
aspect_specification
or representation item is said to be
confirming.
The aspect value specified in this case is said to be a
confirming
representation aspect value. Other values of the aspect are said to be
nonconfirming, as are the
aspect_specifications
and representation items that specified them.
Similarly,
an aspect_specification
or operational item that specifies an operational aspect to be the same
as the definition it would have by default is said to be confirming;
otherwise it is nonconfirming.
Discussion: {
AI12-0005-1}
As noted at the beginning of this subclause, we
have a Language Design Principle that confirming aspects do not change
the semantics. However, it is not a Language Design Principle principle
that one can always specify a confirming aspect. Some aspects can never
be confirmed. For instance, the default implementation of a stream-oriented
attribute cannot be confirmed, as any subprogram that can be specified
is not the same as the default subprogram, and thus is nonconfirming.
Whether the effect is the same is not relevant for this purpose; it would
be very difficult to formally define what it means to have the same effect.
(Note that one can name any implementation for a stream-oriented attribute
by using the associated attribute but specifying that by name would violate
the circular aspect definition rule.) This is true for any implicitly
composed aspect. Similarly, aspect Default_Value cannot be confirmed
as the default is that there is no default value; any value that can
be specified is not that.
Dynamic Semantics
Ramification: {
AI05-0299-1}
Elaboration of representation pragmas is covered by the general rules
for pragmas in
2.8.
Implementation Permissions
{
AI05-0295-1}
An implementation may interpret representation aspects in an implementation-defined
manner. An implementation may place implementation-defined restrictions
on the specification of representation aspects.
A
recommended level of support is defined for the specification
of representation aspects and related features in each subclause. These
recommendations are changed to requirements for implementations that
support the Systems Programming Annex (see
C.2,
“
Required Representation Support”).
Implementation defined: The interpretation
of each representation aspect.
Implementation defined: Any restrictions
placed upon the specification of representation aspects.
Ramification: Implementation-defined
restrictions may be enforced either at compile time or at run time. There
is no requirement that an implementation justify any such restrictions.
They can be based on avoiding implementation complexity, or on avoiding
excessive inefficiency, for example.
Implementation Advice
{
AI05-0295-1}
The recommended level of support for the specification
of all representation aspects is qualified as follows:
To be honest: {
AI05-0295-1}
A confirming representation aspect value might not be possible for some
entities. For instance, consider an unconstrained array. The size of
such a type is implementation-defined, and might not actually be a representable
value, or might not be static.
{
AI05-0295-1}
{
AI12-0444-1}
An implementation
is not required to need
not support the specification for a representation aspect that
contains nonstatic expressions, unless each nonstatic expression is a
name that
statically denotes a constant declared before the entity.
Reason: This
is to avoid the following sort of thing:
{
AI12-0005-1}
X : Integer := F(...)
with Address => Y;
Y : Address := G(...);
for X'Address use Y;
In the above, we have to evaluate the initialization
expression for X before we know where to put the result. This seems like
an unreasonable implementation burden.
The above code
should instead be written like this:
{
AI12-0005-1}
Y :
constant Address := G(...);
X : Integer := F(...)
with Address =>;
for X'Address use Y;
This allows the expression “Y” to
be safely evaluated before X is created.
The constant could be a formal parameter of
mode in.
An implementation can support other nonstatic
expressions if it wants to. Expressions of type Address are hardly ever
static, but their value might be known at compile time anyway in many
cases.
{
AI12-0059-1}
{
AI12-0444-1}
An implementation
is not required to need
not support a specification for the
Object_Size
or Size for a given composite subtype, nor the size or storage
place for an object (including a component) of a given composite subtype,
unless the constraints on the subtype and its composite subcomponents
(if any) are all static constraints.
Reason: {
AI12-0059-1}
We don't want to require that Object_Size or Size
be supported on types that might have a representation not completely
specified at compile time, or are represented discontiguously, or are
represented differently for different constraints.
{
AI95-00291-02}
{
AI05-0295-1}
{
AI12-0444-1}
An implementation
is not required to need
not support specifying a nonconfirming representation aspect value
if it
can could
cause an aliased object or an object of a by-reference type to be allocated
at a nonaddressable location or, when the alignment attribute of the
subtype of such an object is nonzero, at an address that is not an integral
multiple of that alignment.
Reason: The intent is that access types,
type System.Address, and the pointer used for a by-reference parameter
should be implementable as a single machine address — bit-field
pointers should not be required. (There is no requirement that this implementation
be used — we just want to make sure it's feasible.)
Implementation Note: {
AI95-00291-02}
We want subprograms to be able to assume the properties of the types
of their parameters inside of subprograms. While many objects can be
copied to allow this (and thus do not need limitations), aliased or by-reference
objects cannot be copied (their memory location is part of their identity).
Thus, the above rule does not apply to types that merely allow by-reference
parameter passing; for such types, a copy typically needs to be made
at the call site when a bit-aligned component is passed as a parameter.
{
AI95-00291-02}
{
AI05-0295-1}
{
AI12-0444-1}
An implementation
is not required to need
not support specifying a nonconfirming representation aspect value
if it
can could
cause an aliased object of an elementary type to have a size other than
that which would have been chosen by default.
Reason: Since all bits of elementary
objects participate in operations, aliased objects must not have a different
size than that assumed by users of the access type.
{
AI95-00291-02}
{
AI05-0295-1}
{
AI12-0444-1}
An implementation
is not required to need
not support specifying a nonconfirming representation aspect value
if it
can could
cause an aliased object of a composite type, or an object whose type
is by-reference, to have a size smaller than that which would have been
chosen by default.
Reason: Unlike elementary objects, there
is no requirement that all bits of a composite object participate in
operations. Thus, as long as the object is the same or larger in size
than that expected by the access type, all is well.
Ramification: This rule presumes that
the implementation allocates an object of a size specified to be larger
than the default size in such a way that access of the default size suffices
to correctly read and write the value of the object.
{
AI95-00291-02}
{
AI05-0295-1}
{
AI12-0444-1}
An implementation
is not required to need
not support specifying a nonconfirming subtype-specific representation
aspect value for an indefinite or abstract subtype.
Reason: {
AI05-0295-1}
Representation aspects are often not well-defined for such types.
{
AI95-00291-02}
{
AI05-0295-1}
{
AI12-0444-1}
For purposes of these rules, the determination of whether specifying
a representation aspect value for a type
can could cause an object to have some property is based solely on the properties
of the type itself, not on any available information about how the type
is used. In particular, it presumes that minimally aligned objects of
this type
can might
be declared at some point.
Implementation Advice: The recommended
level of support for all representation items should be followed.
NOTE {
AI05-0229-1}
Aspects that can be specified are defined throughout this document, and
are summarized in
K.1.
Incompatibilities With Ada 83
It is now illegal for a
representation item to cause a derived by-reference type to have a different
record layout from its parent. This is necessary for by-reference parameter
passing to be feasible. This only affects programs that specify the representation
of types derived from types containing tasks; most by-reference types
are new to Ada 95. For example, if A1 is an array of tasks, and A2 is
derived from A1, it is illegal to apply a
pragma
Pack to A2.
Extensions to Ada 83
Wording Changes from Ada 83
{
8652/0009}
{
AI95-00137-01}
The syntax rule for
type_representation_clause
is removed; the right-hand side of that rule is moved up to where it
was used, in
aspect_clause.
There are two references to “type representation clause”
in RM83, both in Section 13; these have been reworded. Also, the
representation_clause
has been renamed the
aspect_clause
to reflect that it can be used to control more than just representation
aspects.
{
8652/0009}
{
AI95-00137-01}
{
AI95-00114-01}
We have defined a new term “representation item”, which includes
all representation clauses and representation pragmas, as well as
component_clauses.
This is convenient because the rules are almost identical for all of
them. We have also defined the new terms “operational item”
and “operational aspects” in order to conveniently handle
new types of specifiable entities.
All of the forcing occurrence stuff has been
moved into its own subclause (see
13.14),
and rewritten to use the term “freezing”.
RM83-13.1(10) requires implementation-defined
restrictions on representation items to be enforced at compile time.
However, that is impossible in some cases. If the user specifies a junk
(nonstatic) address in an address clause, and the implementation chooses
to detect the error (for example, using hardware memory management with
protected pages), then it's clearly going to be a run-time error. It
seems silly to call that “semantics” rather than “a
restriction”.
RM83-13.1(10) tries to pretend that representation_clauses
don't affect the semantics of the program. One counter-example is the
Small clause. Ada 95 has more counter-examples. We have noted the opposite
above.
Extensions to Ada 95
{
AI95-00291-02}
Amendment Correction: Confirming representation
items are defined, and the recommended level of support is now that they
always be supported.
Wording Changes from Ada 95
{
8652/0009}
{
AI95-00137-01}
Corrigendum: Added operational items in order to eliminate unnecessary
restrictions and permissions on stream attributes. As part of this,
representation_clause
was renamed to
aspect_clause.
{
8652/0009}
{
AI95-00137-01}
{
AI95-00326-01}
Corrigendum: Added wording to say that the partial and full views
have the same operational and representation aspects. Ada 2005 extends
this to cover all views, including the incomplete view.
{
8652/0040}
{
AI95-00108-01}
Corrigendum: Changed operational items to have inheritance specified
for each such aspect.
{
AI95-00251-01}
Added wording to allow the rejection of types with progenitors that have
conflicting representation items.
{
AI95-00291-02}
The description of the representation of an object was clarified (with
great difficulty reaching agreement). Added wording to say that representation
items on aliased and by-reference objects never need be supported if
they would not be implementable without distributed overhead even if
other recommended level of support says otherwise. This wording matches
the rules with reality.
{
AI95-00444-01}
{
AI05-0005-1}
Added wording so that inheritance depends on whether operational items
are visible rather than whether they occur before the declaration (we
don't want to look into private parts). Also limited operational inheritance
to untagged types to avoid anomalies with private extensions (this is
not incompatible, no existing operational attribute used this capability).
Also added wording to clearly define that subprogram inheritance works
like derivation of subprograms.
Incompatibilities With Ada 2005
{
AI05-0106-1}
{
AI12-0064-2}
{
AI12-0396-1}
Correction: Specifying a language-defined
aspect for a generic formal parameter is no longer allowed. Most aspects
could not be specified on these anyway; moreover, this was not allowed
in Ada 83, so it is unlikely that compilers are supporting this as a
capability (and it is not likely that they have a consistent definition
of what it means if it is allowed). Thus, we expect this to occur rarely
in existing programs.
Note: This correction is
repealed in Ada 2022, as a number of aspects are allowed on formals in
that later language version.
Wording Changes from Ada 2005
{
AI05-0009-1}
{
AI12-0005-1}
Correction: Defined that overriding of
a an
representation aspect only happens for a nonconfirming representation
item. This prevents a derived type from being considered to have only
a confirming representation item when the value would be nonconfirming
if given on a type that does not inherit any aspects of representation.
This change just eliminates a wording confusion and ought not change
any behavior.
{
AI05-0112-1}
Correction: Defined a default naming for representation aspects
that are representation pragmas.
{
AI05-0183-1}
Added text ensuring that the rules for representational and operational
items also apply appropriately to
aspect_specifications;
generalized operational aspects so that they can be defined for entities
other than types. Any extensions are documented elsewhere.
{
AI05-0295-1}
Rewrote many rules to be in terms of "specifying a representation
aspect" rather than use of a "representation item". This
better separates
how an aspect is specified from
what rules
apply to the value of the aspect.
Incompatibilities With Ada 2012
{
AI12-0109-1}
Corrigendum: Added a
rule that makes it illegal to specify a representation value after a
type is derived from an untagged by-reference type. This restriction
is incompatible, but since the implementation would have had to copy
an object that does not allow copying in order to change the representation
for any implicit or explicit conversion between the original and the
derived type, it is unlikely that any program could exist without running
into internal compiler errors or bogus results.
{
AI12-0181-1}
Correction: Added a rule preventing self-referencing
representation or operational aspects. This is technically incompatible,
but since the similar representation or operational item has been illegal
since they've existed, and they don't make any sense, it's unlikely that
any implementation accepted them or that they appear in any program.
{
AI12-0222-1}
Correction: Added a rule preventing giving
a representation aspect on a partial view. Since this has always been
prohibited for other kinds of representation items, it's unlikely that
any implementation accepted them or that they appear in any program.
Extensions to Ada 2012
{
AI12-0376-1}
It is now allowed to specify
type-related representation aspects for an untagged derived type that
has primitive operations, so long as the type is not a by-reference type.
Wording Changes from Ada 2012
{
AI12-0116-1}
{
AI12-0396-1}
Corrigendum: Clarified that an aspect (any
aspect) can be specified only once for an entity, no matter what means
of specifying it are used. We did not document this as an incompatibility as only aspects that are
neither operational nor representation could change behavior and there
is no known implementation of these new aspects that allows multiple
definitions.
{
AI12-0059-1}
Added wording changes to support Object_Size.
{
AI12-0396-1}
Correction: Clarified that many of these
rules only make sense for type-related aspects.
{
AI12-0427-1}
Move the general requirements for aspects that
are subprograms here from 13.3.
Ada 2005 and 2012 Editions sponsored in part by Ada-Europe