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