13.3 Operational and Representation Attributes
The values
of certain implementation-dependent characteristics can be obtained by
interrogating appropriate operational or representation attributes.
Some
of these attributes are specifiable via an
attribute_definition_clause.
Syntax
Name Resolution Rules
For an
attribute_definition_clause
that specifies an attribute that denotes a value or an object, the expected
type for the expression or
name
is that of the attribute.
For an
attribute_definition_clause
that specifies an attribute that denotes a subprogram, the expected profile
for the
name
is the profile required for the attribute. For an
attribute_definition_clause
that specifies an attribute that denotes some other kind of entity, the
name shall
resolve to denote an entity of the appropriate kind.
Legality Rules
An
attribute_designator
is allowed in an
attribute_definition_clause
only if this International Standard explicitly allows it, or for an implementation-defined
attribute if the implementation allows it.
Each specifiable
attribute constitutes an
operational aspect or aspect
of representation; the name of the aspect is that of the attribute.
For an
attribute_definition_clause
that specifies an attribute that denotes a subprogram, the profile shall
be mode conformant with the one required for the attribute, and the convention
shall be Ada. Additional requirements are defined for particular attributes.
Static Semantics
A
storage
element is an addressable element of storage in the machine.
A
word is the largest amount of storage that can be conveniently
and efficiently manipulated by the hardware, given the implementation's
run-time model. A word consists of an integral number of storage elements.
A
machine scalar is an
amount of storage that can be conveniently and efficiently loaded, stored,
or operated upon by the hardware. Machine scalars consist of an integral
number of storage elements. The set of machine scalars is implementation
defined, but includes at least the storage element and the word. Machine
scalars are used to interpret
component_clauses
when the nondefault bit ordering applies.
The following representation attributes are defined:
Address, Alignment, Size, Storage_Size, Component_Size, Has_Same_Storage,
and Overlaps_Storage.
For a
prefix
X that denotes an object, program unit, or label:
X'Address
Denotes the address of the first
of the storage elements allocated to X. For a program unit or label,
this value refers to the machine code associated with the corresponding
body or
statement.
The value of this attribute is of type System.Address.
The prefix of X'Address shall not statically
denote a subprogram that has convention Intrinsic. X'Address raises Program_Error
if X denotes a subprogram that has convention Intrinsic.
Address
may be specified for stand-alone objects and for program units via an
attribute_definition_clause.
Erroneous Execution
If an Address is specified, it
is the programmer's responsibility to ensure that the address is valid
and appropriate for the entity and its use; otherwise, program execution
is erroneous.
Implementation Advice
For an array X, X'Address should point at the first
component of the array, and not at the array bounds.
The recommended level of support
for the Address attribute is:
X'Address should
produce a useful result if X is an object that is aliased or of a by-reference
type, or is an entity whose Address has been specified.
An implementation should support Address clauses
for imported subprograms.
This paragraph
was deleted.
If the Address of an object is specified, or it
is imported or exported, then the implementation should not perform optimizations
based on assumptions of no aliases.
2 The specification of a link name with
the Link_Name aspect (see
B.1) for a subprogram
or object is an alternative to explicit specification of its link-time
address, allowing a link-time directive to place the subprogram or object
within memory.
3 The rules for the Size attribute imply,
for an aliased object X, that if X'Size = Storage_Unit, then X'Address
points at a storage element containing all of the bits of X, and only
the bits of X.
Static Semantics
For a
prefix
X that denotes an object:
X'Alignment
The value of this attribute is
of type
universal_integer, and nonnegative; zero means that the
object is not necessarily aligned on a storage element boundary. If X'Alignment
is not zero, then X is aligned on a storage unit boundary and X'Address
is an integral multiple of X'Alignment (that is, the Address modulo the
Alignment is zero).
This paragraph was deleted.
Alignment
may be specified for stand-alone objects via an
attribute_definition_clause;
the expression of such a clause shall be static, and its value nonnegative.
This paragraph was deleted.
For every subtype
S:
S'Alignment
The value of this attribute is
of type
universal_integer, and nonnegative.
For an object X of subtype S, if S'Alignment
is not zero, then X'Alignment is a nonzero integral multiple of S'Alignment
unless specified otherwise by a representation item.
Alignment
may be specified for first subtypes via an
attribute_definition_clause;
the expression of such a clause shall be static, and its value nonnegative.
Erroneous Execution
Program execution is erroneous
if an Address clause is given that conflicts with the Alignment.
For an object that is not allocated
under control of the implementation, execution is erroneous if the object
is not aligned according to its Alignment.
Implementation Advice
For any tagged specific subtype S, S'Class'Alignment
should equal S'Alignment.
The recommended level of support
for the Alignment attribute for subtypes is:
An implementation
should support an Alignment clause for a discrete type, fixed point type,
record type, or array type, specifying an Alignment value that is zero
or a power of two, subject to the following:
An implementation need not support an Alignment
clause for a signed integer type specifying an Alignment greater than
the largest Alignment value that is ever chosen by default by the implementation
for any signed integer type. A corresponding limitation may be imposed
for modular integer types, fixed point types, enumeration types, record
types, and array types.
An implementation need not support a nonconfirming
Alignment clause which could enable the creation of an object of an elementary
type which cannot be easily loaded and stored by available machine instructions.
An implementation need not support an Alignment
specified for a derived tagged type which is not a multiple of the Alignment
of the parent type. An implementation need not support a nonconfirming
Alignment specified for a derived untagged by-reference type.
The
recommended level of support for the Alignment attribute for objects
is:
This paragraph
was deleted.
For stand-alone library-level objects of statically
constrained subtypes, the implementation should support all Alignments
supported by the target linker. For example, page alignment is likely
to be supported for such objects, but not for subtypes.
For other objects, an implementation should at
least support the alignments supported for their subtype, subject to
the following:
An implementation need not support Alignments specified
for objects of a by-reference type or for objects of types containing
aliased subcomponents if the specified Alignment is not a multiple of
the Alignment of the subtype of the object.
4 Alignment is a subtype-specific attribute.
This paragraph was
deleted.
5 A
component_clause,
Component_Size clause, or specifying the Pack aspect as True can override
a specified Alignment.
Static Semantics
For a
prefix
X that denotes an object:
X'Size
Denotes the size in bits of the
representation of the object. The value of this attribute is of the type
universal_integer.
Size
may be specified for stand-alone objects via an
attribute_definition_clause;
the expression of such a clause shall be static and its value nonnegative.
Implementation Advice
The size of an array object should not include
its bounds.
The recommended level of support
for the Size attribute of objects is the same as for subtypes (see below),
except that only a confirming Size clause need be supported for an aliased
elementary object.
This paragraph
was deleted.
Static Semantics
For every subtype S:
S'Size
If S is definite, denotes the
size (in bits) that the implementation would choose for the following
objects of subtype S:
A record component of subtype S when the
record type is packed.
The formal parameter of an instance of
Unchecked_Conversion that converts from subtype S to some other subtype.
If S is indefinite, the meaning is implementation
defined. The value of this attribute is of the type
universal_integer.
The Size of an object is at least
as large as that of its subtype, unless the object's Size is determined
by a Size clause, a component_clause, or a Component_Size clause. Size
may be specified for first subtypes via an
attribute_definition_clause;
the expression of such a clause shall be static and its value nonnegative.
Implementation Requirements
In an implementation, Boolean'Size shall be 1.
Implementation Advice
If the Size of a subtype
allows for efficient independent addressability (see
9.10)
on the target architecture, then the Size of the following objects of
the subtype should equal the Size of the subtype:
Aliased objects (including components).
Unaliased components, unless the Size of the component
is determined by a
component_clause
or Component_Size clause.
A Size clause on a composite subtype should not affect
the internal layout of components.
The
recommended level of support for the Size attribute of subtypes is:
The Size (if not specified) of a static discrete
or fixed point subtype should be the number of bits needed to represent
each value belonging to the subtype using an unbiased representation,
leaving space for a sign bit only if the subtype contains negative values.
If such a subtype is a first subtype, then an implementation should support
a specified Size for it that reflects this representation.
For a subtype implemented with levels of indirection,
the Size should include the size of the pointers, but not the size of
what they point at.
An implementation
should support a Size clause for a discrete type, fixed point type, record
type, or array type, subject to the following:
An implementation need not support
a Size clause for a signed integer type specifying a Size greater than
that of the largest signed integer type supported by the implementation
in the absence of a size clause (that is, when the size is chosen by
default). A corresponding limitation may be imposed for modular integer
types, fixed point types, enumeration types, record types, and array
types.
A nonconfirming size clause for
the first subtype of a derived untagged by-reference type need not be
supported.
6 Size is a subtype-specific attribute.
7 A
component_clause
or Component_Size clause can override a specified Size. Aspect Pack cannot.
Static Semantics
For a
prefix
T that denotes a task object (after any implicit dereference):
T'Storage_Size
Denotes the number of storage
elements reserved for the task. The value of this attribute is of the
type
universal_integer. The Storage_Size includes the size of
the task's stack, if any. The language does not specify whether or not
it includes other storage associated with the task (such as the “task
control block” used by some implementations.) If the aspect Storage_Size
is specified for the type of the object, the value of the Storage_Size
attribute is at least the value determined by the aspect.
Aspect Storage_Size specifies the amount of storage
to be reserved for the execution of a task.
Static Semantics
For a task type (including
the anonymous type of a
single_task_declaration),
the following language-defined representation aspect may be specified:
Storage_Size
The Storage_Size aspect is an
expression,
which shall be of any integer type.
Legality Rules
The Storage_Size aspect shall not be specified
for a task interface type.
Dynamic Semantics
When a task object is created, the
expression
(if any) associated with the Storage_Size aspect of its type is evaluated;
the Storage_Size attribute of the newly created task object is at least
the value of the
expression.
At
the point of task object creation, or upon task activation, Storage_Error
is raised if there is insufficient free storage to accommodate the requested
Storage_Size.
Static Semantics
For a
prefix
X that denotes an array subtype or array object (after any implicit dereference):
X'Component_Size
Denotes the size in bits of components
of the type of X. The value of this attribute is of type
universal_integer.
Component_Size
may be specified for array types via an
attribute_definition_clause;
the expression of such a clause shall be static, and its value nonnegative.
Implementation Advice
The
recommended level of support for the Component_Size attribute is:
An implementation need not support specified Component_Sizes
that are less than the Size of the component subtype.
An implementation should support specified Component_Sizes
that are factors and multiples of the word size. For such Component_Sizes,
the array should contain no gaps between components. For other Component_Sizes
(if supported), the array should contain no gaps between components when
Pack is also specified; the implementation should forbid this combination
in cases where it cannot support a no-gaps representation.
Static Semantics
For a
prefix
X that denotes an object:
X'Has_Same_Storage
X'Has_Same_Storage denotes a
function with the following specification:
function X'Has_Same_Storage (Arg : any_type)
return Boolean
The actual parameter shall be a name that
denotes an object. The object denoted by the actual parameter can be
of any type. This function evaluates the names of the objects involved.
It returns True if the representation of the object denoted by the actual
parameter occupies exactly the same bits as the representation of the
object denoted by X and the objects occupy at least one bit; otherwise,
it returns False.
For a
prefix
X that denotes an object:
X'Overlaps_Storage
X'Overlaps_Storage denotes a
function with the following specification:
function X'Overlaps_Storage (Arg : any_type)
return Boolean
The actual parameter shall be a name that
denotes an object. The object denoted by the actual parameter can be
of any type. This function evaluates the names of the objects involved
and returns True if the representation of the object denoted by the actual
parameter shares at least one bit with the representation of the object
denoted by X; otherwise, it returns False.
8 X'Has_Same_Storage(Y) implies X'Overlaps_Storage(Y).
9 X'Has_Same_Storage(Y) and X'Overlaps_Storage(Y)
are not considered to be reads of X and Y.
Static Semantics
The following type-related operational attribute
is defined: External_Tag.
For every subtype S
of a tagged type T (specific or class-wide):
S'External_Tag
S'External_Tag
denotes an external string representation for S'Tag; it is of the predefined
type String. External_Tag may be specified for a specific tagged type
via an
attribute_definition_clause;
the expression of such a clause shall be static.
The default external tag representation is implementation defined. See
13.13.2. The value of External_Tag is never
inherited; the default value is always used unless a new value is directly
specified for a type.
Dynamic Semantics
If a user-specified external tag S'External_Tag
is the same as T'External_Tag for some other tagged type declared by
a different declaration in the partition, Program_Error is raised by
the elaboration of the
attribute_definition_clause.
Implementation Requirements
In an implementation, the default external tag for
each specific tagged type declared in a partition shall be distinct,
so long as the type is declared outside an instance of a generic body.
If the compilation unit in which a given tagged type is declared, and
all compilation units on which it semantically depends, are the same
in two different partitions, then the external tag for the type shall
be the same in the two partitions. What it means for a compilation unit
to be the same in two different partitions is implementation defined.
At a minimum, if the compilation unit is not recompiled between building
the two different partitions that include it, the compilation unit is
considered the same in the two partitions.
Implementation Permissions
If a user-specified external tag S'External_Tag
is the same as T'External_Tag for some other tagged type declared by
a different declaration in the partition, the partition may be rejected.
10 The following language-defined attributes
are specifiable, at least for some of the kinds of entities to which
they apply: Address, Alignment, Bit_Order, Component_Size, External_Tag,
Input, Machine_Radix, Output, Read, Size, Small, Storage_Pool, Storage_Size,
Stream_Size, and Write.
11 It follows from the general rules in
13.1 that if one writes “
for
X'Size
use Y;” then the X'Size
attribute_reference
will return Y (assuming the implementation allows the Size clause). The
same is true for all of the specifiable attributes except Storage_Size.
Examples
Examples of attribute
definition clauses:
Byte : constant := 8;
Page : constant := 2**12;
type Medium is range 0 .. 65_000;
for Medium'Size use 2*Byte;
for Medium'Alignment use 2;
Device_Register : Medium;
for Device_Register'Size use Medium'Size;
for Device_Register'Address use System.Storage_Elements.To_Address(16#FFFF_0020#);
type Short is delta 0.01 range -100.0 .. 100.0;
for Short'Size use 15;
for Car_Name'Storage_Size use -- specify access type's storage pool size
2000*((Car'Size/System.Storage_Unit) +1); -- approximately 2000 cars
function My_Input(Stream :
not null access Ada.Streams.Root_Stream_Type'Class)
return T;
for T'Input
use My_Input; --
see 13.13.2
12 Notes on the examples: In the
Size clause for Short, fifteen bits is the minimum necessary, since the
type definition requires Short'Small <= 2**(–7).
Ada 2005 and 2012 Editions sponsored in part by Ada-Europe