- (1)
- The values of certain implementation-dependent characteristics can be
obtained by interrogating appropriate representation attributes. Some of
these attributes are specifiable via an attribute_definition_clause.
(2)
attribute_definition_clause ::=
for local_name'attribute_designator use expression;
| for local_name'attribute_designator use name;
Name Resolution Rules
- (3)
- For an attribute_definition_clause that specifies an attribute that
denotes a value, the form with an expression shall be used. Otherwise, the
form with a name shall be used.
- (4)
- 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
- (5)
- 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 aspect of representation.
- (6)
- 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
- (7)
- A Size clause is an attribute_definition_clause whose attribute_designator is Size. Similar definitions apply to the other specifiable
attributes.
- (8)
- 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.
- (9)
- The following attributes are defined:
- (10)
- For a prefix X that denotes an object, program unit, or label:
- (11)
- 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.
- (12)
Address may be specified for stand-alone objects and for
program units via an attribute_definition_clause.
Erroneous Execution
- (13)
- If an Address is specified, it is the programmer's responsibility to
ensure that the address is valid; otherwise, program execution is erroneous.
Implementation Advice
- (14)
- For an array X, X'Address should point at the first component of the
array, and not at the array bounds.
- (15)
- The recommended level of support for the Address attribute is:
- (16)
- 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.
- (17)
- An implementation should support Address clauses for imported
subprograms.
- (18)
- Objects (including subcomponents) that are aliased or of a
by-reference type should be allocated on storage element
boundaries.
- (19)
- 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.
-
- (20)
(1) The specification of a link name in a pragma Export (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.
- (21)
(2) 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
- (22)
- For a prefix X that denotes a subtype or object:
- (23)
- X'Alignment
The Address of an object that is allocated under control of
the implementation is an integral multiple of the Alignment
of the object (that is, the Address modulo the Alignment is
zero). The offset of a record component is a multiple of the
Alignment of the component. For an object that is not
allocated under control of the implementation (that is, one
that is imported, that is allocated by a user-defined
allocator, whose Address has been specified, or is designated
by an access value returned by an instance of Unchecked_Conversion), the implementation may assume that the Address
is an integral multiple of its Alignment. The implementation
shall not assume a stricter alignment.
- (24)
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.
- (25)
Alignment may be specified for first subtypes and
stand-alone objects via an attribute_definition_clause; the
expression of such a clause shall be static, and its value
nonnegative. If the Alignment of a subtype is specified,
then the Alignment of an object of the subtype is at least as
strict, unless the object's Alignment is also specified. The
Alignment of an object created by an allocator is that of the
designated subtype.
- (26)
If an Alignment is specified for a composite subtype or
object, this Alignment shall be equal to the least common
multiple of any specified Alignments of the subcomponent
subtypes, or an integer multiple thereof.
Erroneous Execution
- (27)
- Program execution is erroneous if an Address clause is given that
conflicts with the Alignment.
- (28)
- If the Alignment is specified for an object that is not allocated under
control of the implementation, execution is erroneous if the object is not
aligned according to the Alignment.
Implementation Advice
- (29)
- The recommended level of support for the Alignment attribute for
subtypes is:
- (30)
- An implementation should support specified Alignments that are
factors and multiples of the number of storage elements per word,
subject to the following:
- (31)
- An implementation need not support specified Alignments for
combinations of Sizes and Alignments that cannot be easily loaded
and stored by available machine instructions.
- (32)
- An implementation need not support specified Alignments that are
greater than the maximum Alignment the implementation ever
returns by default.
- (33)
- The recommended level of support for the Alignment attribute for objects
is:
- (34)
- Same as above, for subtypes, but in addition:
- (35)
- 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.
-
- (36)
(3) Alignment is a subtype-specific attribute.
- (37)
(4) The Alignment of a composite object is always equal to the least
common multiple of the Alignments of its components, or a multiple
thereof.
- (38)
(5) A component_clause, Component_Size clause, or a pragma Pack can
override a specified Alignment.
Static Semantics
- (39)
- For a prefix X that denotes an object:
- (40)
- X'Size
Denotes the size in bits of the representation of the object.
The value of this attribute is of the type universal_integer.
- (41)
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
- (42)
- The recommended level of support for the Size attribute of objects is:
- (43)
- A Size clause should be supported for an object if the specified
Size is at least as large as its subtype's Size, and corresponds
to a size in storage elements that is a multiple of the object's
Alignment (if the Alignment is nonzero).
Static Semantics
- (44)
- For every subtype S:
- (45)
- S'Size
If S is definite, denotes the size (in bits) that the
implementation would choose for the following objects of
subtype S:
- (46)
- A record component of subtype S when the record
type is packed.
- (47)
- The formal parameter of an instance of Unchecked_Conversion that converts from subtype S to some
other subtype.
- (48)
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
- (49)
- In an implementation, Boolean'Size shall be 1.
Implementation Advice
- (50)
- If the Size of a subtype is specified, and 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:
- (51)
- Aliased objects (including components).
- (52)
- Unaliased components, unless the Size of the component is
determined by a component_clause or Component_Size clause.
- (53)
- A Size clause on a composite subtype should not affect the internal
layout of components.
- (54)
- The recommended level of support for the Size attribute of subtypes is:
- (55)
- 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.
- (56)
- 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.
-
- (57)
(6) Size is a subtype-specific attribute.
- (58)
(7) A component_clause or Component_Size clause can override a specified
Size. A pragma Pack cannot.
Static Semantics
- (59)
- For a prefix T that denotes a task object (after any implicit
dereference):
- (60)
- 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 a
pragma Storage_Size is given, the value of the Storage_Size
attribute is at least the value specified in the pragma.
- (61)
- A pragma Storage_Size specifies the amount of storage to be reserved for
the execution of a task.
Syntax
- (62)
The form of a pragma Storage_Size is as follows:
(63)
pragma Storage_Size(expression);
- (64)
A pragma Storage_Size is allowed only immediately within a task_definition.
Name Resolution Rules
- (65)
- The expression of a pragma Storage_Size is expected to be of any integer
type.
Dynamic Semantics
- (66)
- A pragma Storage_Size is elaborated when an object of the type defined
by the immediately enclosing task_definition is created. For the elaboration
of a pragma Storage_Size, the expression is evaluated; the Storage_Size
attribute of the newly created task object is at least the value of the
expression.
- (67)
- 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
- (68)
- For a prefix X that denotes an array subtype or array object (after any
implicit dereference):
- (69)
- 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.
- (70)
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
- (71)
- The recommended level of support for the Component_Size attribute is:
- (72)
- An implementation need not support specified Component_Sizes that
are less than the Size of the component subtype.
- (73)
- 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 packing is also specified; the
implementation should forbid this combination in cases where it
cannot support a no-gaps representation.
Static Semantics
- (74)
- For every subtype S of a tagged type T (specific or class-wide), the
following attribute is defined:
- (75)
- 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 3.9.2 and 13.13.2.
Implementation Requirements
- (76)
- 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.
-
- (77)
(8) The following language-defined attributes are specifiable, at least
for some of the kinds of entities to which they apply: Address, Size,
Component_Size, Alignment, External_Tag, Small, Bit_Order, Storage_Pool,
Storage_Size, Write, Output, Read, Input, and Machine_Radix.
- (78)
(9) 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
- (79)
- Examples of attribute definition clauses:
(80)
Byte : constant := 8;
Page : constant := 2**12;
(81)
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#);
(82)
type Short is delta 0.01 range -100.0 .. 100.0;
for Short'Size use 15;
(83)
for Car_Name'Storage_Size use -- specify access type's storage pool size
2000*((Car'Size/System.Storage_Unit) +1); -- approximately 2000 cars
(84)
function My_Read(Stream : access Ada.Streams.Root_Stream_Type'Class)
return T;
for T'Read use My_Read; -- see 13.13.2
-
- (85)
(10) 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).
-- Email comments, additions, corrections, gripes, kudos, etc. to:
Magnus Kempe -- Magnus.Kempe@di.epfl.ch
Copyright statement
Page last generated: 95-03-12