Go to the first, previous, next, last section, table of contents.


Declarations and Types

  1. This section describes the types in the language and the rules for declaring constants, variables, and named numbers.

Declarations

  1. The language defines several kinds of named entities that are declared by declarations. The entity's name is defined by the declaration, usually by a defining_identifier, but sometimes by a defining_character_literal or defining_operator_symbol.
  2. There are several forms of declaration. A basic_declaration is a form of declaration defined as follows. Syntax
  3. basic_declaration ::=
         type_declaration         | subtype_declaration
       | object_declaration       | number_declaration
       | subprogram_declaration   | abstract_subprogram_declaration
       | package_declaration      | renaming_declaration
       | exception_declaration    | generic_declaration
       | generic_instantiation
    
  4. defining_identifier ::= identifier
    
    Static Semantics
  5. A declaration is a language construct that associates a name with (a view of) an entity. A declaration may appear explicitly in the program text (an explicit declaration), or may be supposed to occur at a given place in the text as a consequence of the semantics of another construct (an implicit declaration).
  6. Each of the following is defined to be a declaration: any basic_declaration; an enumeration_literal_specification; a discriminant_specification; a component_declaration; a loop_parameter_specification; a parameter_specification; a subprogram_body; an entry_declaration; an entry_index_specification; a choice_parameter_specification; a generic_formal_parameter_declaration.
  7. All declarations contain a definition for a view of an entity. A view consists of an identification of the entity (the entity of the view), plus view-specific characteristics that affect the use of the entity through that view (such as mode of access to an object, formal parameter names and defaults for a subprogram, or visibility to components of a type). In most cases, a declaration also contains the definition for the entity itself (a renaming_declaration is an example of a declaration that does not define a new entity, but instead defines a view of an existing entity See section Renaming Declarations.)
  8. For each declaration, the language rules define a certain region of text called the scope of the declaration See section Scope of Declarations. Most declarations associate an identifier with a declared entity. Within its scope, and only there, there are places where it is possible to use the identifier to refer to the declaration, the view it defines, and the associated entity; these places are defined by the visibility rules See section Visibility. At such places the identifier is said to be a name of the entity (the direct_name or selector_name); the name is said to denote the declaration, the view, and the associated entity See section The Context of Overload Resolution. The declaration is said to declare the name, the view, and in most cases, the entity itself.
  9. As an alternative to an identifier, an enumeration literal can be declared with a character_literal as its name See section Enumeration Types, and a function can be declared with an operator_symbol as its name See section Subprogram Declarations.
  10. The syntax rules use the terms defining_identifier, defining_character_literal, and defining_operator_symbol for the defining occurrence of a name; these are collectively called defining names. The terms direct_name and selector_name are used for usage occurrences of identifiers, character_literals, and operator_symbols. These are collectively called usage names. Dynamic Semantics
  11. The process by which a construct achieves its run-time effect is called execution. This process is also called elaboration for declarations and evaluation for expressions. One of the terms execution, elaboration, or evaluation is defined by this International Standard for each construct that has a run-time effect. NOTES
  12. (1) At compile time, the declaration of an entity declares the entity. At run time, the elaboration of the declaration creates the entity.

Types and Subtypes

Static Semantics

  1. A type is characterized by a set of values, and a set of primitive operations which implement the fundamental aspects of its semantics. An object of a given type is a run-time entity that contains (has) a value of the type.
  2. Types are grouped into classes of types, reflecting the similarity of their values and primitive operations. There exist several language-defined classes of types (see NOTES below). Elementary types are those whose values are logically indivisible; composite types are those whose values are composed of component values.
  3. The elementary types are the scalar types (discrete and real) and the access types (whose values provide access to objects or subprograms). Discrete types are either integer types or are defined by enumeration of their values (enumeration types). Real types are either floating point types or fixed point types.
  4. The composite types are the record types, record extensions, array types, task types, and protected types. A private type or private extension represents a partial view, see section Private Types and Private Extensions, of a type, providing support for data abstraction. A partial view is a composite type.
  5. Certain composite types (and partial views thereof) have special components called discriminants whose values affect the presence, constraints, or initialization of other components. Discriminants can be thought of as parameters of the type.
  6. The term subcomponent is used in this International Standard in place of the term component to indicate either a component, or a component of another subcomponent. Where other subcomponents are excluded, the term component is used instead. Similarly, a part of an object or value is used to mean the whole object or value, or any set of its subcomponents.
  7. The set of possible values for an object of a given type can be subjected to a condition that is called a constraint (the case of a null constraint that specifies no restriction is also included); the rules for which values satisfy a given kind of constraint are given in section Scalar Types for range_constraints, section Index Constraints and Discrete Ranges, for index_constraints, and section Discriminant Constraints, for discriminant_constraints.
  8. A subtype of a given type is a combination of the type, a constraint on values of the type, and certain attributes specific to the subtype. The given type is called the type of the subtype. Similarly, the associated constraint is called the constraint of the subtype. The set of values of a subtype consists of the values of its type that satisfy its constraint. Such values belong to the subtype.
  9. A subtype is called an unconstrained subtype if its type has unknown discriminants, or if its type allows range, index, or discriminant constraints, but the subtype does not impose such a constraint; otherwise, the subtype is called a constrained subtype (since it has no unconstrained characteristics). NOTES
  10. (2) Any set of types that is closed under derivation See section Derived Types and Classes, can be called a "class" of types. However, only certain classes are used in the description of the rules of the language -- generally those that have their own particular set of primitive operations See section Classification of Operations, or that correspond to a set of types that are matched by a given kind of generic formal type See section Formal Types. The following are examples of "interesting" language-defined classes: elementary, scalar, discrete, enumeration, character, boolean, integer, signed integer, modular, real, floating point, fixed point, ordinary fixed point, decimal fixed point, numeric, access, access-to-object, access-to-subprogram, composite, array, string, (untagged) record, tagged, task, protected, nonlimited. Special syntax is provided to define types in each of these classes.
    1. These language-defined classes are organized like this:
    2. all types
         elementary
            scalar
               discrete
                  enumeration
                     character
                     boolean
                     other enumeration
                  integer
                     signed integer
                     modular integer
               real
                  floating point
                  fixed point
                     ordinary fixed point
                     decimal fixed point
            access
               access-to-object
               access-to-subprogram
         composite
            array
               string
               other array
            untagged record
            tagged
            task
            protected
      
    3. The classes "numeric" and "nonlimited" represent other classification dimensions and do not fit into the above strictly hierarchical picture.

Type Declarations

  1. A type_declaration declares a type and its first subtype. Syntax
  2. type_declaration ::=
         full_type_declaration
       | incomplete_type_declaration
       | private_type_declaration
       | private_extension_declaration
    
  3. full_type_declaration ::=
         type defining_identifier [known_discriminant_part]
           is type_definition;
       | task_type_declaration
       | protected_type_declaration
    
  4. type_definition ::=
         enumeration_type_definition | integer_type_definition
       | real_type_definition        | array_type_definition
       | record_type_definition      | access_type_definition
       | derived_type_definition
    
    Legality Rules
  5. A given type shall not have a subcomponent whose type is the given type itself. Static Semantics
  6. The defining_identifier of a type_declaration denotes the first subtype of the type. The known_discriminant_part, if any, defines the discriminants of the type See section Discriminants. The remainder of the type_ declaration defines the remaining characteristics of (the view of) the type.
  7. A type defined by a type_declaration is a named type; such a type has one or more nameable subtypes. Certain other forms of declaration also include type definitions as part of the declaration for an object (including a parameter or a discriminant). The type defined by such a declaration is anonymous -- it has no nameable subtypes. For explanatory purposes, this International Standard sometimes refers to an anonymous type by a pseudo-name, written in italics, and uses such pseudo-names at places where the syntax normally requires an identifier. For a named type whose first subtype is T, this International Standard sometimes refers to the type of T as simply "the type T."
  8. A named type that is declared by a full_type_declaration, or an anonymous type that is defined as part of declaring an object of the type, is called a full type. The type_definition, task_definition, protected_definition, or access_definition that defines a full type is called a full type definition. Types declared by other forms of type_declaration are not separate types; they are partial or incomplete views of some full type.
  9. The definition of a type implicitly declares certain predefined operators that operate on the type, according to what classes the type belongs, as specified in section Operators and Expression Evaluation.
  10. The predefined types (for example the types Boolean, Wide_Character, Integer, root_integer, and universal_integer) are the types that are defined in a predefined library package called Standard; this package also includes the (implicit) declarations of their predefined operators. The package Standard is described in section The Package Standard. Dynamic Semantics
  11. The elaboration of a full_type_declaration consists of the elaboration of the full type definition. Each elaboration of a full type definition creates a distinct type and its first subtype. Examples
  12. Examples of type definitions:
  13. (White, Red, Yellow, Green, Blue, Brown, Black)
    range 1 .. 72
    array(1 .. 10) of Integer
    
  14. Examples of type declarations:
  15. type Color  is (White, Red, Yellow, Green, Blue, Brown, Black);
    type Column is range 1 .. 72;
    type Table  is array(1 .. 10) of Integer;
    
    NOTES
  16. (3) Each of the above examples declares a named type. The identifier given denotes the first subtype of the type. Other named subtypes of the type can be declared with subtype_declarations See section Subtype Declarations. Although names do not directly denote types, a phrase like "the type Column" is sometimes used in this International Standard to refer to the type of Column, where Column denotes the first subtype of the type. For an example of the definition of an anonymous type, see the declaration of the array Color_Table in section Object Declarations, its type is anonymous -- it has no nameable subtypes.

Subtype Declarations

  1. A subtype_declaration declares a subtype of some previously declared type, as defined by a subtype_indication. Syntax
  2. subtype_declaration ::=
       subtype defining_identifier is subtype_indication;
    
  3. subtype_indication ::=  subtype_mark [constraint]
    
  4. subtype_mark ::= subtype_name
    
  5. constraint ::= scalar_constraint | composite_constraint
    
  6. scalar_constraint ::=
       range_constraint | digits_constraint | delta_constraint
    
  7. composite_constraint ::=
       index_constraint | discriminant_constraint
    
    Name Resolution Rules
  8. A subtype_mark shall resolve to denote a subtype. The type determined by a subtype_mark is the type of the subtype denoted by the subtype_mark. Dynamic Semantics
  9. The elaboration of a subtype_declaration consists of the elaboration of the subtype_indication. The elaboration of a subtype_indication creates a new subtype. If the subtype_indication does not include a constraint, the new subtype has the same (possibly null) constraint as that denoted by the subtype_mark. The elaboration of a subtype_indication that includes a constraint proceeds as follows:
    1. The constraint is first elaborated.
    2. A check is then made that the constraint is compatible with the subtype denoted by the subtype_mark.
  1. The condition imposed by a constraint is the condition obtained after elaboration of the constraint. The rules defining compatibility are given for each form of constraint in the appropriate subclause. These rules are such that if a constraint is compatible with a subtype, then the condition imposed by the constraint cannot contradict any condition already imposed by the subtype on its values. The exception Constraint_Error is raised if any check of compatibility fails. NOTES
  2. (4) A scalar_constraint may be applied to a subtype of an appropriate scalar type, see section Scalar Types, see section Fixed Point Types, and section Reduced Accuracy Subtypes, even if the subtype is already constrained. On the other hand, a composite_constraint may be applied to a composite subtype (or an access-to-composite subtype) only if the composite subtype is unconstrained, see section Index Constraints and Discrete Ranges and section Discriminant Constraints. Examples
  3. Examples of subtype declarations:
  4. subtype Rainbow   is Color range Red .. Blue;  -- see section Type Declarations
    subtype Red_Blue  is Rainbow;
    subtype Int       is Integer;
    subtype Small_Int is Integer range -10 .. 10;
    subtype Up_To_K   is Column range 1 .. K;      -- see section Type Declarations
    subtype Square    is Matrix(1 .. 10, 1 .. 10); -- see section Array Types
    subtype Male      is Person(Sex => M);         -- see section Incomplete Type Declarations
    

Classification of Operations

Static Semantics

  1. An operation operates on a type T if it yields a value of type T, if it has an operand whose expected type, see section The Context of Overload Resolution, is T, or if it has an access parameter, see section Subprogram Declarations designating T. A predefined operator, or other language-defined operation such as assignment or a membership test, that operates on a type, is called a predefined operation of the type. The primitive operations of a type are the predefined operations of the type, plus any user-defined primitive subprograms.
  2. The primitive subprograms of a specific type are defined as follows:
    1. The predefined operators of the type, see section Operators and Expression Evaluation,
    2. For a derived type, the inherited, see section Derived Types and Classes, user-defined subprograms;
    3. For an enumeration type, the enumeration literals (which are considered parameterless functions -- see section Enumeration Types.);
    4. For a specific type declared immediately within a package_specification, any subprograms (in addition to the enumeration literals) that are explicitly declared immediately within the same package_specification and that operate on the type;
    5. Any subprograms not covered above that are explicitly declared immediately within the same declarative region as the type and that override, see section Visibility, other implicitly declared primitive subprograms of the type.
  1. A primitive subprogram whose designator is an operator_symbol is called a primitive operator.

Objects and Named Numbers

  1. Objects are created at run time and contain a value of a given type. An object can be created and initialized as part of elaborating a declaration, evaluating an allocator, aggregate, or function_call, or passing a parameter by copy. Prior to reclaiming the storage for an object, it is finalized if necessary, see section Completion and Finalization. Static Semantics
  2. All of the following are objects:
    1. the entity declared by an object_declaration;
    2. a formal parameter of a subprogram, entry, or generic subprogram;
    3. a generic formal object;
    4. a loop parameter;
    5. a choice parameter of an exception_handler;
    6. an entry index of an entry_body;
    7. the result of dereferencing an access-to-object value, see section Names,
    8. the result of evaluating a function_call (or the equivalent operator invocation -- see section Overloading of Operators,
    9. the result of evaluating an aggregate;
    10. a component, slice, or view conversion of another object.
  1. An object is either a constant object or a variable object. The value of a constant object cannot be changed between its initialization and its finalization, whereas the value of a variable object can be changed. Similarly, a view of an object is either a constant or a variable. All views of a constant object are constant. A constant view of a variable object cannot be used to modify the value of the variable. The terms constant and variable by themselves refer to constant and variable views of objects.
  2. The value of an object is read when the value of any part of the object is evaluated, or when the value of an enclosing object is evaluated. The value of a variable is updated when an assignment is performed to any part of the variable, or when an assignment is performed to an enclosing object.
  3. Whether a view of an object is constant or variable is determined by the definition of the view. The following (and no others) represent constants:
    1. an object declared by an object_declaration with the reserved word constant;
    2. a formal parameter or generic formal object of mode in;
    3. a discriminant;
    4. a loop parameter, choice parameter, or entry index;
    5. the dereference of an access-to-constant value;
    6. he result of evaluating a function_call or an aggregate;
    7. a selected_component, indexed_component, slice, or view conversion of a constant.
  1. At the place where a view of an object is defined, a nominal subtype is associated with the view. The object's actual subtype (that is, its subtype) can be more restrictive than the nominal subtype of the view; it always is if the nominal subtype is an indefinite subtype. A subtype is an indefinite subtype if it is an unconstrained array subtype, or if it has unknown discriminants or unconstrained discriminants without defaults See section Discriminants, otherwise the subtype is a definite subtype (all elementary subtypes are definite subtypes). A class-wide subtype is defined to have unknown discriminants, and is therefore an indefinite subtype. An indefinite subtype does not by itself provide enough information to create an object; an additional constraint or explicit initialization expression is necessary See section Object Declarations. A component cannot have an indefinite nominal subtype.
  2. A named number provides a name for a numeric value known at compile time. It is declared by a number_declaration. NOTES
  3. (5) A constant cannot be the target of an assignment operation, nor be passed as an in out or out parameter, between its initialization and finalization, if any.
  4. (6) The nominal and actual subtypes of an elementary object are always the same. For a discriminated or array object, if the nominal subtype is constrained then so is the actual subtype.

Object Declarations

  1. An object_declaration declares a stand-alone object with a given nominal subtype and, optionally, an explicit initial value given by an initialization expression. For an array, task, or protected object, the object_declaration may include the definition of the (anonymous) type of the object. Syntax
  2. object_declaration ::=
        defining_identifier_list : [aliased] [constant]
          subtype_indication [:= expression];
      | defining_identifier_list : [aliased] [constant]
          array_type_definition [:= expression];
      | single_task_declaration
      | single_protected_declaration
    
  3. defining_identifier_list ::=
       defining_identifier {, defining_identifier}
    
    Name Resolution Rules
  4. For an object_declaration with an expression following the compound delimiter :=, the type expected for the expression is that of the object. This expression is called the initialization expression. Legality Rules
  5. An object_declaration without the reserved word constant declares a variable object. If it has a subtype_indication or an array_type_definition that defines an indefinite subtype, then there shall be an initialization expression. An initialization expression shall not be given if the object is of a limited type. Static Semantics
  6. An object_declaration with the reserved word constant declares a constant object. If it has an initialization expression, then it is called a full constant declaration. Otherwise it is called a deferred constant declaration. The rules for deferred constant declarations are given in clause See section Deferred Constants. The rules for full constant declarations are given in this subclause.
  7. Any declaration that includes a defining_identifier_list with more than one defining_identifier is equivalent to a series of declarations each containing one defining_identifier from the list, with the rest of the text of the declaration copied for each declaration in the series, in the same order as the list. The remainder of this International Standard relies on this equivalence; explanations are given for declarations with a single defining_identifier.
  8. The subtype_indication or full type definition of an object_declaration defines the nominal subtype of the object. The object_declaration declares an object of the type of the nominal subtype. Dynamic Semantics
  9. If a composite object declared by an object_declaration has an unconstrained nominal subtype, then if this subtype is indefinite or the object is constant or aliased, see section Access Types, the actual subtype of this object is constrained. The constraint is determined by the bounds or discriminants (if any) of its initial value; the object is said to be constrained by its initial value. In the case of an aliased object, this initial value may be either explicit or implicit; in the other cases, an explicit initial value is required. When not constrained by its initial value, the actual and nominal subtypes of the object are the same. If its actual subtype is constrained, the object is called a constrained object.
  10. For an object_declaration without an initialization expression, any initial values for the object or its subcomponents are determined by the implicit initial values defined for its nominal subtype, as follows:
    1. The implicit initial value for an access subtype is the null value of the access type.
    2. The implicit initial (and only) value for each discriminant of a constrained discriminated subtype is defined by the subtype.
    3. For a (definite) composite subtype, the implicit initial value of each component with a default_expression is obtained by evaluation of this expression and conversion to the component's nominal subtype (which might raise Constraint_Error -- see section Type Conversions.), unless the component is a discriminant of a constrained subtype (the previous case), or is in an excluded variant, see section Variant Parts and Discrete Choices. For each component that does not have a default_expression, any implicit initial values are those determined by the component's nominal subtype.
    4. For a protected or task subtype, there is an implicit component (an entry queue) corresponding to each entry, with its implicit initial value being an empty queue.
  1. The elaboration of an object_declaration proceeds in the following sequence of steps:
    1. The subtype_indication, array_type_definition, single_task_declaration, or single_protected_declaration is first elaborated. This creates the nominal subtype (and the anonymous type in the latter three cases).
    2. If the object_declaration includes an initialization expression, the (explicit) initial value is obtained by evaluating the expression and converting it to the nominal subtype (which might raise Constraint_Error -- see section Type Conversions.).
    3. The object is created, and, if there is not an initialization expression, any per-object expressions, see section Record Types are evaluated and any implicit initial values for the object or for its subcomponents are obtained as determined by the nominal subtype.
    4. Any initial values (whether explicit or implicit) are assigned to the object or to the corresponding subcomponents. As described in See section Assignment Statements, and section User-Defined Assignment and Finalization, Initialize and Adjust procedures can be called.
  1. For the third step above, the object creation and any elaborations and evaluations are performed in an arbitrary order, except that if the default_expression for a discriminant is evaluated to obtain its initial value, then this evaluation is performed before that of the default_expression for any component that depends on the discriminant, and also before that of any default_expression that includes the name of the discriminant. The evaluations of the third step and the assignments of the fourth step are performed in an arbitrary order, except that each evaluation is performed before the resulting value is assigned.
  2. There is no implicit initial value defined for a scalar subtype. In the absence of an explicit initialization, a newly created scalar object might have a value that does not belong to its subtype See section Data Validity, and section Pragma Normalize_Scalars. NOTES
  3. (7) Implicit initial values are not defined for an indefinite subtype, because if an object's nominal subtype is indefinite, an explicit initial value is required.
  4. (8) As indicated above, a stand-alone object is an object declared by an object_declaration. Similar definitions apply to "stand-alone constant" and "stand-alone variable." A subcomponent of an object is not a stand-alone object, nor is an object that is created by an allocator. An object declared by a loop_parameter_specification, parameter_specification, entry_index_specification, choice_parameter_specification, or a formal_object_declaration is not called a stand-alone object.
  5. (9) The type of a stand-alone object cannot be abstract, see section Abstract Types and Subprograms. Examples
  6. Example of a multiple object declaration:
  7. --  the multiple object declaration
    
  8. John, Paul : Person_Name := new Person(Sex => M); --  see section Incomplete Type Declarations
    
  9. --  is equivalent to the two single object
    --  declarations in the order given
    
  10. John : Person_Name := new Person(Sex => M);
    Paul : Person_Name := new Person(Sex => M);
    
  11. Examples of variable declarations:
  12. Count, Sum  : Integer;
    Size        : Integer range 0 .. 10_000 := 0;
    Sorted      : Boolean := False;
    Color_Table : array(1 .. Max) of Color;
    Option      : Bit_Vector(1 .. 10) := (others => True);
    Hello       : constant String := "Hi, world.";
    
  13. Examples of constant declarations:
  14. Limit     : constant Integer := 10_000;
    Low_Limit : constant Integer := Limit/10;
    Tolerance : constant Real := Dispersion(1.15);
    

Number Declarations

  1. A number_declaration declares a named number. Syntax
  2. number_declaration ::=
       defining_identifier_list : constant := static_expression;
    
    Name Resolution Rules
  3. The static_expression given for a number_declaration is expected to be of any numeric type. Legality Rules
  4. The static_expression given for a number declaration shall be a static expression, as defined by clause See section Static Expressions and Static Subtypes. Static Semantics
  5. The named number denotes a value of type universal_integer if the type of the static_expression is an integer type. The named number denotes a value of type universal_real if the type of the static_expression is a real type.
  6. The value denoted by the named number is the value of the static_expression, converted to the corresponding universal type. Dynamic Semantics
  7. The elaboration of a number_declaration has no effect. Examples
  8. Examples of number declarations:
  9. Two_Pi        : constant := 2.0*Ada.Numerics.Pi;
    -- a real number, see section The Numerics Packages
    
  10. Max           : constant := 500;     -- an integer number
    Max_Line_Size : constant := Max/6;   -- the integer 83
    Power_16      : constant := 2**16;   -- the integer 65_536
    One, Un, Eins : constant := 1;       -- three different names for 1
    

Derived Types and Classes

  1. A derived_type_definition defines a new type (and its first subtype) whose characteristics are derived from those of a parent type. Syntax
  2. derived_type_definition ::= [abstract] new
      parent_subtype_indication [record_extension_part]
    
    Legality Rules
  3. The parent_subtype_indication defines the parent subtype; its type is the parent type.
  4. A type shall be completely defined, see section Completions of Declarations, prior to being specified as the parent type in a derived_type_definition -- the full_type_declarations for the parent type and any of its subcomponents have to precede the derived_type_definition.
  5. If there is a record_extension_part, the derived type is called a record extension of the parent type. A record_extension_part shall be provided if and only if the parent type is a tagged type. Static Semantics
  6. The first subtype of the derived type is unconstrained if a known_discriminant_part is provided in the declaration of the derived type, or if the parent subtype is unconstrained. Otherwise, the constraint of the first subtype corresponds to that of the parent subtype in the following sense: it is the same as that of the parent subtype except that for a range constraint (implicit or explicit), the value of each bound of its range is replaced by the corresponding value of the derived type.
  7. The characteristics of the derived type are defined as follows:
    1. Each class of types that includes the parent type also includes the derived type.
    2. If the parent type is an elementary type or an array type, then the set of possible values of the derived type is a copy of the set of possible values of the parent type. For a scalar type, the base range of the derived type is the same as that of the parent type.
    3. If the parent type is a composite type other than an array type, then the components, protected subprograms, and entries that are declared for the derived type are as follows:
      1. The discriminants specified by a new known_discriminant_part, if there is one; otherwise, each discriminant of the parent type (implicitly declared in the same order with the same specifications) -- in the latter case, the discriminants are said to be inherited, or if unknown in the parent, are also unknown in the derived type;
      2. Each nondiscriminant component, entry, and protected subprogram of the parent type, implicitly declared in the same order with the same declarations; these components, entries, and protected subprograms are said to be inherited;
      3. Each component declared in a record_extension_part, if any.
    1. Declarations of components, protected subprograms, and entries, whether implicit or explicit, occur immediately within the declarative region of the type, in the order indicated above, following the parent subtype_indication.
    2. The derived type is limited if and only if the parent type is limited.
    3. For each predefined operator of the parent type, there is a corresponding predefined operator of the derived type.
    4. For each user-defined primitive subprogram (other than a user-defined equality operator -- see below) of the parent type that already exists at the place of the derived_type_definition, there exists a corresponding inherited primitive subprogram of the derived type with the same defining name. Primitive user-defined equality operators of the parent type are also inherited by the derived type, except when the derived type is a nonlimited record extension, and the inherited operator would have a profile that is type conformant with the profile of the corresponding predefined equality operator; in this case, the user-defined equality operator is not inherited, but is rather incorporated into the implementation of the predefined equality operator of the record extension, see section Relational Operators and Membership Tests.
    5. The profile of an inherited subprogram (including an inherited enumeration literal) is obtained from the profile of the corresponding (user-defined) primitive subprogram of the parent type, after systematic replacement of each subtype of its profile, see section Subprogram Declarations, that is of the parent type with a corresponding subtype of the derived type. For a given subtype of the parent type, the corresponding subtype of the derived type is defined as follows:
      1. If the declaration of the derived type has neither a known_discriminant_part nor a record_extension_part, then the corresponding subtype has a constraint that corresponds (as defined above for the first subtype of the derived type) to that of the given subtype.
      2. If the derived type is a record extension, then the corresponding subtype is the first subtype of the derived type.
      3. If the derived type has a new known_discriminant_part but is not a record extension, then the corresponding subtype is constrained to those values that when converted to the parent type belong to the given subtype, see section Type Conversions.
    1. The same formal parameters have default_expressions in the profile of the inherited subprogram. Any type mismatch due to the systematic replacement of the parent type by the derived type is handled as part of the normal type conversion associated with parameter passing -- See section Parameter Associations.
  1. If a primitive subprogram of the parent type is visible at the place of the derived_type_definition, then the corresponding inherited subprogram is implicitly declared immediately after the derived_type_definition. Otherwise, the inherited subprogram is implicitly declared later or not at all, as explained in section Private Operations.
  2. A derived type can also be defined by a private_extension_declaration, See section Private Types and Private Extensions, or a formal_derived_type_definition, see section Formal Private and Derived Types. Such a derived type is a partial view of the corresponding full or actual type.
  3. All numeric types are derived types, in that they are implicitly derived from a corresponding root numeric type (see section Integer Types, and section Real Types. Dynamic Semantics
  4. The elaboration of a derived_type_definition creates the derived type and its first subtype, and consists of the elaboration of the subtype_indication and the record_extension_part, if any. If the subtype_indication depends on a discriminant, then only those expressions that do not depend on a discriminant are evaluated.
  5. For the execution of a call on an inherited subprogram, a call on the corresponding primitive subprogram of the parent type is performed; the normal conversion of each actual parameter to the subtype of the corresponding formal parameter, see section Parameter Associations performs any necessary type conversion as well. If the result type of the inherited subprogram is the derived type, the result of calling the parent's subprogram is converted to the derived type. NOTES
  6. (10) Classes are closed under derivation -- any class that contains a type also contains its derivatives. Operations available for a given class of types are available for the derived types in that class.
  7. (11) Evaluating an inherited enumeration literal is equivalent to evaluating the corresponding enumeration literal of the parent type, and then converting the result to the derived type. This follows from their equivalence to parameterless functions.
  8. (12) A generic subprogram is not a subprogram, and hence cannot be a primitive subprogram and cannot be inherited by a derived type. On the other hand, an instance of a generic subprogram can be a primitive subprogram, and hence can be inherited.
  9. (13) If the parent type is an access type, then the parent and the derived type share the same storage pool; there is a null access value for the derived type and it is the implicit initial value for the type. See section Access Types.
  10. (14) If the parent type is a boolean type, the predefined relational operators of the derived type deliver a result of the predefined type Boolean, see section Relational Operators and Membership Tests. If the parent type is an integer type, the right operand of the predefined exponentiation operator is of the predefined type Integer, see section Highest Precedence Operators.
  11. (15) Any discriminants of the parent type are either all inherited, or completely replaced with a new set of discriminants.
  12. (16) For an inherited subprogram, the subtype of a formal parameter of the derived type need not have any value in common with the first subtype of the derived type.
  13. (17) If the reserved word abstract is given in the declaration of a type, the type is abstract, see section Abstract Types and Subprograms. Examples
  14. Examples of derived type declarations:
  15. type Local_Coordinate is new Coordinate;   --  two different types
    type Midweek is new Day range Tue .. Thu;  --  see section Enumeration Types
    type Counter is new Positive;              --  same range as Positive
    
  16. type Special_Key is new Key_Manager.Key;   --  see section Private Operations
      -- the inherited subprograms have the following specifications:
      --         procedure Get_Key(K : out Special_Key);
      --         function "<"(X,Y : Special_Key) return Boolean;
    

Derivation Classes

  1. In addition to the various language-defined classes of types, types can be grouped into derivation classes. Static Semantics
  2. A derived type is derived from its parent type directly; it is derived indirectly from any type from which its parent type is derived. The derivation class of types for a type T (also called the class rooted at T) is the set consisting of T (the root type of the class) and all types derived from T (directly or indirectly) plus any associated universal or class-wide types (defined below).
  3. Every type is either a specific type, a class-wide type, or a universal type. A specific type is one defined by a type_declaration, a formal_type_declaration, or a full type definition embedded in a declaration for an object. Class-wide and universal types are implicitly defined, to act as representatives for an entire class of types, as follows:
  4. Class-wide types
      Class-wide types are defined for (and belong to) each derivation class rooted at a tagged type, see section Tagged Types and Type Extensions. Given a subtype S of a tagged type T, S'Class is the subtype_mark for a corresponding subtype of the tagged class-wide type T'Class. Such types are called "class-wide" because when a formal parameter is defined to be of a class-wide type T'Class, an actual parameter of any type in the derivation class rooted at T is acceptable, see section The Context of Overload Resolution.
    1. The set of values for a class-wide type T'Class is the discriminated union of the set of values of each specific type in the derivation class rooted at T (the tag acts as the implicit discriminant -- see section Tagged Types and Type Extensions.). Class-wide types have no primitive subprograms of their own. However, as explained in section Dispatching Operations of Tagged Types, operands of a class-wide type T'Class can be used as part of a dispatching call on a primitive subprogram of the type T. The only components (including discriminants) of T'Class that are visible are those of T. If S is a first subtype, then S'Class is a first subtype.
  1. Universal types
      Universal types are defined for (and belong to) the integer, real, and fixed point classes, and are referred to in this standard as respectively, universal_integer, universal_real, and universal_fixed. These are analogous to class-wide types for these language-defined numeric classes. As with class-wide types, if a formal parameter is of a universal type, then an actual parameter of any type in the corresponding class is acceptable. In addition, a value of a universal type (including an integer or real numeric_literal) is "universal" in that it is acceptable where some particular type in the class is expected, see section The Context of Overload Resolution.
    1. The set of values of a universal type is the undiscriminated union of the set of values possible for any definable type in the associated class. Like class-wide types, universal types have no primitive subprograms of their own. However, their "universality" allows them to be used as operands with the primitive subprograms of any type in the corresponding class.
  1. The integer and real numeric classes each have a specific root type in addition to their universal type, named respectively root_integer and root_real.
  2. A class-wide or universal type is said to cover all of the types in its class. A specific type covers only itself.
  3. A specific type T2 is defined to be a descendant of a type T1 if T2 is the same as T1, or if T2 is derived (directly or indirectly) from T1. A class-wide type T2'Class is defined to be a descendant of type T1 if T2 is a descendant of T1. Similarly, the universal types are defined to be descendants of the root types of their classes. If a type T2 is a descendant of a type T1, then T1 is called an ancestor of T2. The ultimate ancestor of a type is the ancestor of the type that is not a descendant of any other type.
  4. An inherited component (including an inherited discriminant) of a derived type is inherited from a given ancestor of the type if the corresponding component was inherited by each derived type in the chain of derivations going back to the given ancestor. NOTES
  5. (18) Because operands of a universal type are acceptable to the predefined operators of any type in their class, ambiguity can result. For universal_integer and universal_real, this potential ambiguity is resolved by giving a preference, see section The Context of Overload Resolution to the predefined operators of the corresponding root types (root_integer and root_real, respectively). Hence, in an apparently ambiguous expression like
  6. 1 + 4 < 7
    
  7. where each of the literals is of type universal_integer, the predefined operators of root_integer will be preferred over those of other specific integer types, thereby resolving the ambiguity.

Scalar Types

  1. Scalar types comprise enumeration types, integer types, and real types. Enumeration types and integer types are called discrete types; each value of a discrete type has a position number which is an integer value. Integer types and real types are called numeric types. All scalar types are ordered, that is, all relational operators are predefined for their values. Syntax
  2. range_constraint ::= range range
    
  3. range ::=
         range_attribute_reference
       | simple_expression .. simple_expression
    
  4. A range has a lower bound and an upper bound and specifies a subset of the values of some scalar type (the type of the range). A range with lower bound L and upper bound R is described by "L .. R". If R is less than L, then the range is a null range, and specifies an empty set of values. Otherwise, the range specifies the values of the type from the lower bound to the upper bound, inclusive. A value belongs to a range if it is of the type of the range, and is in the subset of values specified by the range. A value satisfies a range constraint if it belongs to the associated range. One range is included in another if all values that belong to the first range also belong to the second. Name Resolution Rules
  5. For a subtype_indication containing a range_constraint, either directly or as part of some other scalar_constraint, the type of the range shall resolve to that of the type determined by the subtype_mark of the subtype_indication. For a range of a given type, the simple_expressions of the range (likewise, the simple_expressions of the equivalent range for a range_attribute_reference) are expected to be of the type of the range. Static Semantics
  6. The base range of a scalar type is the range of finite values of the type that can be represented in every unconstrained object of the type; it is also the range supported at a minimum for intermediate values during the evaluation of expressions involving predefined operators of the type.
  7. A constrained scalar subtype is one to which a range constraint applies. The range of a constrained scalar subtype is the range associated with the range constraint of the subtype. The range of an unconstrained scalar subtype is the base range of its type. Dynamic Semantics
  8. A range is compatible with a scalar subtype if and only if it is either a null range or each bound of the range belongs to the range of the subtype. A range_constraint is compatible with a scalar subtype if and only if its range is compatible with the subtype.
  9. The elaboration of a range_constraint consists of the evaluation of the range. The evaluation of a range determines a lower bound and an upper bound. If simple_expressions are given to specify bounds, the evaluation of the range evaluates these simple_expressions in an arbitrary order, and converts them to the type of the range. If a range_attribute_reference is given, the evaluation of the range consists of the evaluation of the range_attribute_reference.
  10. Attributes
  11. For every scalar subtype S, the following attributes are defined:
  12. S'First
    S'First denotes the lower bound of the range of S. The value
    of this attribute is of the type of S.
    
  13. S'Last
    S'Last denotes the upper bound of the range of S. The value
    of this attribute is of the type of S.
    
  14. S'Range
    S'Range is equivalent to the range S'First .. S'Last.
    
  15. S'Base
    S'Base denotes an unconstrained subtype of the type of
    S. This unconstrained subtype is called the base subtype of
    the type.
    
  16. S'Min
      S'Min denotes a function with the following specification:
    1. function S'Min(Left, Right : S'Base)
        return S'Base
      
    2. The function returns the lesser of the values of the two parameters.
  1. S'Max
      S'Max denotes a function with the following specification:
    1. function S'Max(Left, Right : S'Base)
        return S'Base
      
    2. The function returns the greater of the values of the two parameters.
  1. S'Succ
      S'Succ denotes a function with the following specification:
    1. function S'Succ(Arg : S'Base)
        return S'Base
      
    2. For an enumeration type, the function returns the value whose position number is one more than that of the value of Arg; Constraint_Error is raised if there is no such value of the type. For an integer type, the function returns the result of adding one to the value of Arg. For a fixed point type, the function returns the result of adding small to the value of Arg. For a floating point type, the function returns the machine number (as defined in section Floating Point Types.) immediately above the value of Arg; Constraint_Error is raised if there is no such machine number.
  1. S'Pred
      S'Pred denotes a function with the following specification:
    1. function S'Pred(Arg : S'Base)
        return S'Base
      
    2. For an enumeration type, the function returns the value whose position number is one less than that of the value of Arg; Constraint_Error is raised if there is no such value of the type. For an integer type, the function returns the result of subtracting one from the value of Arg. For a fixed point type, the function returns the result of subtracting small from the value of Arg. For a floating point type, the function returns the machine number (as defined in section Floating Point Types.) immediately below the value of Arg; Constraint_Error is raised if there is no such machine number.
  1. S'Wide_Image
      S'Wide_Image denotes a function with the following specification:
    1. function S'Wide_Image(Arg : S'Base)
        return Wide_String
      
    2. The function returns an image of the value of Arg, that is, a sequence of characters representing the value in display form. The lower bound of the result is one.
    3. The image of an integer value is the corresponding decimal literal, without underlines, leading zeros, exponent, or trailing spaces, but with a single leading character that is either a minus sign or a space.
    4. The image of an enumeration value is either the corresponding identifier in upper case or the corresponding character literal (including the two apostrophes); neither leading nor trailing spaces are included. For a nongraphic character (a value of a character type that has no enumeration literal associated with it), the result is a corresponding language-defined or implementation-defined name in upper case (for example, the image of the nongraphic character identified as nul is "NUL" -- the quotes are not part of the image).
    5. The image of a floating point value is a decimal real literal best approximating the value (rounded away from zero if halfway between) with a single leading character that is either a minus sign or a space, a single digit (that is nonzero unless the value is zero), a decimal point, S'Digits-1, see section Operations of Floating Point Types, digits after the decimal point (but one if S'Digits is one), an upper case E, the sign of the exponent (either + or -), and two or more digits (with leading zeros if necessary) representing the exponent. If S'Signed_Zeros is True, then the leading character is a minus sign for a negatively signed zero.
    6. The image of a fixed point value is a decimal real literal best approximating the value (rounded away from zero if halfway between) with a single leading character that is either a minus sign or a space, one or more digits before the decimal point (with no redundant leading zeros), a decimal point, and S'Aft, see section Operations of Fixed Point Types, digits after the decimal point.
  1. S'Image
      S'Image denotes a function with the following specification:
    1. function S'Image(Arg : S'Base)
        return String
      
    2. The function returns an image of the value of Arg as a String. The lower bound of the result is one. The image has the same sequence of graphic characters as that defined for S'Wide_Image if all the graphic characters are defined in Character; otherwise the sequence of characters is implementation defined (but no shorter than that of S'Wide_Image for the same value of Arg).
  1. S'Wide_Width
    S'Wide_Width denotes the maximum length of a Wide_String
    returned by S'Wide_Image over all values of the subtype S. It
    denotes zero for a subtype that has a null range. Its type
    is universal_integer.
    
  2. S'Width
    S'Width denotes the maximum length of a String returned by
    S'Image over all values of the subtype S. It denotes
    zero for a subtype that has a null range. Its type is
    universal_integer.
    
  3. S'Wide_Value
      S'Wide_Value denotes a function with the following specification:
    1. function S'Wide_Value(Arg : Wide_String)
        return S'Base
      
    2. This function returns a value given an image of the value as a Wide_String, ignoring any leading or trailing spaces.
    3. For the evaluation of a call on S'Wide_Value for an enumeration subtype S, if the sequence of characters of the parameter (ignoring leading and trailing spaces) has the syntax of an enumeration literal and if it corresponds to a literal of the type of S (or corresponds to the result of S'Wide_Image for a nongraphic character of the type), the result is the corresponding enumeration value; otherwise Constraint_Error is raised.
    4. For the evaluation of a call on S'Wide_Value (or S'Value) for an integer subtype S, if the sequence of characters of the parameter (ignoring leading and trailing spaces) has the syntax of an integer literal, with an optional leading sign character (plus or minus for a signed type; only plus for a modular type), and the corresponding numeric value belongs to the base range of the type of S, then that value is the result; otherwise Constraint_Error is raised.
    5. For the evaluation of a call on S'Wide_Value (or S'Value) for a real subtype S, if the sequence of characters of the parameter (ignoring leading and trailing spaces) has the syntax of one of the following:
      1. numeric_literal
      2. numeral.[exponent]
      3. .numeral[exponent]
      4. base#based_numeral.#[exponent]
      5. base#.based_numeral#[exponent]
    1. with an optional leading sign character (plus or minus), and if the corresponding numeric value belongs to the base range of the type of S, then that value is the result; otherwise Constraint_Error is raised. The sign of a zero value is preserved (positive if none has been specified) if S'Signed_Zeros is True.
  1. S'Value
      S'Value denotes a function with the following specification:
    1. function S'Value(Arg : String)
        return S'Base
      
    2. This function returns a value given an image of the value as a String, ignoring any leading or trailing spaces.
    3. For the evaluation of a call on S'Value for an enumeration subtype S, if the sequence of characters of the parameter (ignoring leading and trailing spaces) has the syntax of an enumeration literal and if it corresponds to a literal of the type of S (or corresponds to the result of S'Image for a value of the type), the result is the corresponding enumeration value; otherwise Constraint_Error is raised. For a numeric subtype S, the evaluation of a call on S'Value with Arg of type String is equivalent to a call on S'Wide_Value for a corresponding Arg of type Wide_String.

Implementation Permissions

  1. An implementation may extend the Wide_Value, Value, Wide_Image, and Image attributes of a floating point type to support special values such as infinities and NaNs. NOTES
  2. (19) The evaluation of S'First or S'Last never raises an exception. If a scalar subtype S has a nonnull range, S'First and S'Last belong to this range. These values can, for example, always be assigned to a variable of subtype S.
  3. (20) For a subtype of a scalar type, the result delivered by the attributes Succ, Pred, and Value might not belong to the subtype; similarly, the actual parameters of the attributes Succ, Pred, and Image need not belong to the subtype.
  4. (21) For any value V (including any nongraphic character) of an enumeration subtype S, S'Value(S'Image(V)) equals V, as does S'Wide_Value(S'Wide_Image(V)). Neither expression ever raises Constraint_Error. Examples
  5. Examples of ranges:
  6. -10 .. 10
    X .. X + 1
    0.0 .. 2.0*Pi
    Red .. Green     --  see section Enumeration Types
    1 .. 0           -- a null range
    Table'Range      -- a range attribute reference, see section Array Types
    
  7. Examples of range constraints:
  8. range -999.0 .. +999.0
    range S'First+1 .. S'Last-1
    

Enumeration Types

  1. An enumeration_type_definition defines an enumeration type. Syntax
  2. enumeration_type_definition ::=
       (enumeration_literal_specification
         {, enumeration_literal_specification})
    
  3. enumeration_literal_specification ::=
       defining_identifier | defining_character_literal
    
  4. defining_character_literal ::= character_literal
    
    Legality Rules
  5. The defining_identifiers and defining_character_literals listed in an enumeration_type_definition shall be distinct. Static Semantics
  6. Each enumeration_literal_specification is the explicit declaration of the corresponding enumeration literal: it declares a parameterless function, whose defining name is the defining_identifier or defining_character_literal, and whose result type is the enumeration type.
  7. Each enumeration literal corresponds to a distinct value of the enumeration type, and to a distinct position number. The position number of the value of the first listed enumeration literal is zero; the position number of the value of each subsequent enumeration literal is one more than that of its predecessor in the list.
  8. The predefined order relations between values of the enumeration type follow the order of corresponding position numbers.
  9. If the same defining_identifier or defining_character_literal is specified in more than one enumeration_type_definition, the corresponding enumeration literals are said to be overloaded. At any place where an overloaded enumeration literal occurs in the text of a program, the type of the enumeration literal has to be determinable from the context, see section The Context of Overload Resolution. Dynamic Semantics
  10. The elaboration of an enumeration_type_definition creates the enumeration type and its first subtype, which is constrained to the base range of the type.
  11. When called, the parameterless function associated with an enumeration literal returns the corresponding value of the enumeration type. NOTES
  12. (22) If an enumeration literal occurs in a context that does not otherwise suffice to determine the type of the literal, then qualification by the name of the enumeration type is one way to resolve the ambiguity, see section Qualified Expressions. Examples
  13. Examples of enumeration types and subtypes:
  14. type Day    is (Mon, Tue, Wed, Thu, Fri, Sat, Sun);
    type Suit   is (Clubs, Diamonds, Hearts, Spades);
    type Gender is (M, F);
    type Level  is (Low, Medium, Urgent);
    type Color  is (White, Red, Yellow, Green, Blue, Brown, Black);
    type Light  is (Red, Amber, Green); -- Red and Green are overloaded
    
  15. type Hexa   is ('A', 'B', 'C', 'D', 'E', 'F');
    type Mixed  is ('A', 'B', '*', B, None, '?', '%');
    
  16. subtype Weekday is Day   range Mon .. Fri;
    subtype Major   is Suit  range Hearts .. Spades;
    subtype Rainbow is Color range Red .. Blue;
    --  the Color Red, not the Light
    

Character Types

Static Semantics

  1. An enumeration type is said to be a character type if at least one of its enumeration literals is a character_literal.
  2. The predefined type Character is a character type whose values correspond to the 256 code positions of Row 00 (also known as Latin-1) of the ISO 10646 Basic Multilingual Plane (BMP). Each of the graphic characters of Row 00 of the BMP has a corresponding character_literal in Character. Each of the nongraphic positions of Row 00 (0000-001F and 007F-009F) has a corresponding language-defined name, which is not usable as an enumeration literal, but which is usable with the attributes (Wide_)Image and (Wide_)Value; these names are given in the definition of type Character in section The Package Standard, but are set in italics.
  3. The predefined type Wide_Character is a character type whose values correspond to the 65536 code positions of the ISO 10646 Basic Multilingual Plane (BMP). Each of the graphic characters of the BMP has a corresponding character_literal in Wide_Character. The first 256 values of Wide_Character have the same character_literal or language-defined name as defined for Character. The last 2 values of Wide_Character correspond to the nongraphic positions FFFE and FFFF of the BMP, and are assigned the language-defined names FFFE and FFFF. As with the other language-defined names for nongraphic characters, the names FFFE and FFFF are usable only with the attributes (Wide_)Image and (Wide_)Value; they are not usable as enumeration literals. All other values of Wide_Character are considered graphic characters, and have a corresponding character_literal. Implementation Permissions
  4. In a nonstandard mode, an implementation may provide other interpretations for the predefined types Character and Wide_Character, to conform to local conventions. Implementation Advice
  5. If an implementation supports a mode with alternative interpretations for Character and Wide_Character, the set of graphic characters of Character should nevertheless remain a proper subset of the set of graphic characters of Wide_Character. Any character set "localizations" should be reflected in the results of the subprograms defined in the language-defined package Characters.Handling, see section Character Handling, available in such a mode. In a mode with an alternative interpretation of Character, the implementation should also support a corresponding change in what is a legal identifier_letter. NOTES
  6. (23) The language-defined library package Characters.Latin_1, See section The Package Characters.Latin_1, includes the declaration of constants denoting control characters, lower case characters, and special characters of the predefined type Character.
  7. (24) A conventional character set such as EBCDIC can be declared as a character type; the internal codes of the characters can be specified by an enumeration_representation_clause as explained in clause See section Enumeration Representation Clauses. Examples
  8. Example of a character type:
  9. type Roman_Digit is ('I', 'V', 'X', 'L', 'C', 'D', 'M');
    

Boolean Types

Static Semantics

  1. There is a predefined enumeration type named Boolean, declared in the visible part of package Standard. It has the two enumeration literals False and True ordered with the relation False < True. Any descendant of the predefined type Boolean is called a boolean type.

Integer Types

  1. An integer_type_definition defines an integer type; it defines either a signed integer type, or a modular integer type. The base range of a signed integer type includes at least the values of the specified range. A modular type is an integer type with all arithmetic modulo a specified positive modulus; such a type corresponds to an unsigned type with wrap-around semantics. Syntax
  2. integer_type_definition ::=
       signed_integer_type_definition | modular_type_definition
    
  3. signed_integer_type_definition ::=
       range static_simple_expression .. static_simple_expression
    
  4. modular_type_definition ::= mod static_expression
    
    Name Resolution Rules
  5. Each simple_expression in a signed_integer_type_definition is expected to be of any integer type; they need not be of the same type. The expression in a modular_type_definition is likewise expected to be of any integer type. Legality Rules
  6. The simple_expressions of a signed_integer_type_definition shall be static, and their values shall be in the range System.Min_Int .. System.Max_Int.
  7. The expression of a modular_type_definition shall be static, and its value (the modulus) shall be positive, and shall be no greater than System.Max_Binary_Modulus if a power of 2, or no greater than System.Max_Nonbinary_Modulus if not. Static Semantics
  8. The set of values for a signed integer type is the (infinite) set of mathematical integers, though only values of the base range of the type are fully supported for run-time operations. The set of values for a modular integer type are the values from 0 to one less than the modulus, inclusive.
  9. A signed_integer_type_definition defines an integer type whose base range includes at least the values of the simple_expressions and is symmetric about zero, excepting possibly an extra negative value. A signed_integer_type_definition also defines a constrained first subtype of the type, with a range whose bounds are given by the values of the simple_expressions, converted to the type being defined.
  10. A modular_type_definition defines a modular type whose base range is from zero to one less than the given modulus. A modular_type_definition also defines a constrained first subtype of the type with a range that is the same as the base range of the type.
  11. There is a predefined signed integer subtype named Integer, declared in the visible part of package Standard. It is constrained to the base range of its type.
  12. Integer has two predefined subtypes, declared in the visible part of package Standard:
  13. subtype Natural  is Integer range 0 .. Integer'Last;
    subtype Positive is Integer range 1 .. Integer'Last;
    
  14. A type defined by an integer_type_definition is implicitly derived from root_integer, an anonymous predefined (specific) integer type, whose base range is System.Min_Int .. System.Max_Int. However, the base range of the new type is not inherited from root_integer, but is instead determined by the range or modulus specified by the integer_type_definition. Integer literals are all of the type universal_integer, the universal type, see section Derivation Classes, for the class rooted at root_integer, allowing their use with the operations of any integer type.
  15. The position number of an integer value is equal to the value.
  16. For every modular subtype S, the following attribute is defined:
  17. S'Modulus
    S'Modulus yields the modulus of the type of S, as a value of
    the type universal_integer.
    
    Dynamic Semantics
  18. The elaboration of an integer_type_definition creates the integer type and its first subtype.
  19. For a modular type, if the result of the execution of a predefined operator, see section Operators and Expression Evaluation is outside the base range of the type, the result is reduced modulo the modulus of the type to a value that is within the base range of the type.
  20. For a signed integer type, the exception Constraint_Error is raised by the execution of an operation that cannot deliver the correct result because it is outside the base range of the type. For any integer type, Constraint_Error is raised by the operators "/", "rem", and "mod" if the right operand is zero. Implementation Requirements
  21. In an implementation, the range of Integer shall include the range -2**15+1 .. +2**15-1.
  22. If Long_Integer is predefined for an implementation, then its range shall include the range -2**31+1 .. +2**31-1.
  23. System.Max_Binary_Modulus shall be at least 2**16. Implementation Permissions
  24. For the execution of a predefined operation of a signed integer type, the implementation need not raise Constraint_Error if the result is outside the base range of the type, so long as the correct result is produced.
  25. An implementation may provide additional predefined signed integer types, declared in the visible part of Standard, whose first subtypes have names of the form Short_Integer, Long_Integer, Short_Short_Integer, Long_Long_Integer, etc. Different predefined integer types are allowed to have the same base range. However, the range of Integer should be no wider than that of Long_Integer. Similarly, the range of Short_Integer (if provided) should be no wider than Integer. Corresponding recommendations apply to any other predefined integer types. There need not be a named integer type corresponding to each distinct base range supported by an implementation. The range of each first subtype should be the base range of its type.
  26. An implementation may provide nonstandard integer types, descendants of root_integer that are declared outside of the specification of package Standard, which need not have all the standard characteristics of a type defined by an integer_type_definition. For example, a nonstandard integer type might have an asymmetric base range or it might not be allowed as an array or loop index (a very long integer). Any type descended from a nonstandard integer type is also nonstandard. An implementation may place arbitrary restrictions on the use of such types; it is implementation defined whether operators that are predefined for "any integer type" are defined for a particular nonstandard integer type. In any case, such types are not permitted as explicit_generic_actual_parameters for formal scalar types -- See section Formal Scalar Types.
  27. For a one's complement machine, the high bound of the base range of a modular type whose modulus is one less than a power of 2 may be equal to the modulus, rather than one less than the modulus. It is implementation defined for which powers of 2, if any, this permission is exercised. Implementation Advice
  28. An implementation should support Long_Integer in addition to Integer if the target machine supports 32-bit (or longer) arithmetic. No other named integer subtypes are recommended for package Standard. Instead, appropriate named integer subtypes should be provided in the library package Interfaces, see section The Package Interfaces.
  29. An implementation for a two's complement machine should support modular types with a binary modulus up to System.Max_Int*2+2. An implementation should support a nonbinary modulus up to Integer'Last. NOTES
  30. (25) Integer literals are of the anonymous predefined integer type universal_integer. Other integer types have no literals. However, the overload resolution rules, see section The Context of Overload Resolution, allow expressions of the type universal_integer whenever an integer type is expected.
  31. (26) The same arithmetic operators are predefined for all signed integer types defined by a signed_integer_type_definition, see section Operators and Expression Evaluation. For modular types, these same operators are predefined, plus bit-wise logical operators (and, or, xor, and not). In addition, for the unsigned types declared in the language-defined package Interfaces, see section The Package Interfaces, functions are defined that provide bit-wise shifting and rotating.
  32. (27) Modular types match a generic_formal_parameter_declaration of the form "type T is mod <>;"; signed integer types match "type T is range <>;", see section Formal Scalar Types. Examples
  33. Examples of integer types and subtypes:
  34. type Page_Num  is range 1 .. 2_000;
    type Line_Size is range 1 .. Max_Line_Size;
    
  35. subtype Small_Int   is Integer   range -10 .. 10;
    subtype Column_Ptr  is Line_Size range 1 .. 10;
    subtype Buffer_Size is Integer   range 0 .. Max;
    
  36. type Byte        is mod 256; -- an unsigned byte
    type Hash_Index  is mod 97;  -- modulus is prime
    

Operations of Discrete Types

Static Semantics

  1. For every discrete subtype S, the following attributes are defined:
  2. S'Pos
      S'Pos denotes a function with the following specification:
    1. function S'Pos(Arg : S'Base)
        return universal_integer
      
    2. This function returns the position number of the value of Arg, as a value of type universal_integer.
  1. S'Val
      S'Val denotes a function with the following specification:
    1. function S'Val(Arg : universal_integer)
        return S'Base
      
    2. This function returns a value of the type of S whose position number equals the value of Arg. For the evaluation of a call on S'Val, if there is no value in the base range of its type with the given position number, Constraint_Error is raised.

Implementation Advice

  1. For the evaluation of a call on S'Pos for an enumeration subtype, if the value of the operand does not correspond to the internal code for any enumeration literal of its type (perhaps due to an uninitialized variable), then the implementation should raise Program_Error. This is particularly important for enumeration types with noncontiguous internal codes specified by an enumeration_representation_clause. NOTES
  2. (28) Indexing and loop iteration use values of discrete types.
  3. (29) The predefined operations of a discrete type include the assignment operation, qualification, the membership tests, and the relational operators; for a boolean type they include the short-circuit control forms and the logical operators; for an integer type they include type conversion to and from other numeric types, as well as the binary and unary adding operators - and +, the multiplying operators, the unary operator abs, and the exponentiation operator. The assignment operation is described in section Assignment Statements. The other predefined operations are described in Section See section Names and Expressions.
  4. (30) As for all types, objects of a discrete type have Size and Address attributes, see section Representation Attributes.
  5. (31) For a subtype of a discrete type, the result delivered by the attribute Val might not belong to the subtype; similarly, the actual parameter of the attribute Pos need not belong to the subtype. The following relations are satisfied (in the absence of an exception) by these attributes:
  6. S'Val(S'Pos(X)) = X
    S'Pos(S'Val(N)) = N
    
    Examples
  7. Examples of attributes of discrete subtypes:
  8. --  For the types and subtypes declared in subclause
    --  see section Enumeration Types, the following hold:
    
  9. --  Color'First   = White,   Color'Last   = Black
    --  Rainbow'First = Red,     Rainbow'Last = Blue
    
  10. --  Color'Succ(Blue) = Rainbow'Succ(Blue) = Brown
    --  Color'Pos(Blue)  = Rainbow'Pos(Blue)  = 4
    --  Color'Val(0)     = Rainbow'Val(0)     = White
    

Real Types

  1. Real types provide approximations to the real numbers, with relative bounds on errors for floating point types, and with absolute bounds for fixed point types. Syntax
  2. real_type_definition ::=
       floating_point_definition | fixed_point_definition
    
    Static Semantics
  3. A type defined by a real_type_definition is implicitly derived from root_real, an anonymous predefined (specific) real type. Hence, all real types, whether floating point or fixed point, are in the derivation class rooted at root_real.
  4. Real literals are all of the type universal_real, the universal type, See section Derivation Classes, for the class rooted at root_real, allowing their use with the operations of any real type. Certain multiplying operators have a result type of universal_fixed, see section Multiplying Operators, the universal type for the class of fixed point types, allowing the result of the multiplication or division to be used where any specific fixed point type is expected. Dynamic Semantics
  5. The elaboration of a real_type_definition consists of the elaboration of the floating_point_definition or the fixed_point_definition. Implementation Requirements
  6. An implementation shall perform the run-time evaluation of a use of a predefined operator of root_real with an accuracy at least as great as that of any floating point type definable by a floating_point_definition. Implementation Permissions
  7. For the execution of a predefined operation of a real type, the implementation need not raise Constraint_Error if the result is outside the base range of the type, so long as the correct result is produced, or the Machine_Overflows attribute of the type is false, see section Numeric Performance Requirements.
  8. An implementation may provide nonstandard real types, descendants of root_real that are declared outside of the specification of package Standard, which need not have all the standard characteristics of a type defined by a real_type_definition. For example, a nonstandard real type might have an asymmetric or unsigned base range, or its predefined operations might wrap around or "saturate" rather than overflow (modular or saturating arithmetic), or it might not conform to the accuracy model, see section Numeric Performance Requirements. Any type descended from a nonstandard real type is also nonstandard. An implementation may place arbitrary restrictions on the use of such types; it is implementation defined whether operators that are predefined for "any real type" are defined for a particular nonstandard real type. In any case, such types are not permitted as explicit_generic_actual_parameters for formal scalar types -- see section Formal Scalar Types. NOTES
  9. (32) As stated, real literals are of the anonymous predefined real type universal_real. Other real types have no literals. However, the overload resolution rules, see section The Context of Overload Resolution, allow expressions of the type universal_real whenever a real type is expected.

Floating Point Types

  1. For floating point types, the error bound is specified as a relative precision by giving the required minimum number of significant decimal digits. Syntax
  2. floating_point_definition ::=
       digits static_expression [real_range_specification]
    
  3. real_range_specification ::=
       range static_simple_expression .. static_simple_expression
    
    Name Resolution Rules
  4. The requested decimal precision, which is the minimum number of significant decimal digits required for the floating point type, is specified by the value of the expression given after the reserved word digits. This expression is expected to be of any integer type.
  5. Each simple_expression of a real_range_specification is expected to be of any real type; the types need not be the same. Legality Rules
  6. The requested decimal precision shall be specified by a static expression whose value is positive and no greater than System.Max_Base_Digits. Each simple_expression of a real_range_specification shall also be static. If the real_range_specification is omitted, the requested decimal precision shall be no greater than System.Max_Digits.
  7. A floating_point_definition is illegal if the implementation does not support a floating point type that satisfies the requested decimal precision and range. Static Semantics
  8. The set of values for a floating point type is the (infinite) set of rational numbers. The machine numbers of a floating point type are the values of the type that can be represented exactly in every unconstrained variable of the type. The base range, see section Scalar Types, of a floating point type is symmetric around zero, except that it can include some extra negative values in some implementations.
  9. The base decimal precision of a floating point type is the number of decimal digits of precision representable in objects of the type. The safe range of a floating point type is that part of its base range for which the accuracy corresponding to the base decimal precision is preserved by all predefined operations.
  10. A floating_point_definition defines a floating point type whose base decimal precision is no less than the requested decimal precision. If a real_range_specification is given, the safe range of the floating point type (and hence, also its base range) includes at least the values of the simple expressions given in the real_range_specification. If a real_range_specification is not given, the safe (and base) range of the type includes at least the values of the range -10.0**(4*D) .. +10.0**(4*D) where D is the requested decimal precision. The safe range might include other values as well. The attributes Safe_First and Safe_Last give the actual bounds of the safe range.
  11. A floating_point_definition also defines a first subtype of the type. If a real_range_specification is given, then the subtype is constrained to a range whose bounds are given by a conversion of the values of the simple_expressions of the real_range_specification to the type being defined. Otherwise, the subtype is unconstrained.
  12. There is a predefined, unconstrained, floating point subtype named Float, declared in the visible part of package Standard. Dynamic Semantics
  13. The elaboration of a floating_point_definition creates the floating point type and its first subtype. Implementation Requirements
  14. In an implementation that supports floating point types with 6 or more digits of precision, the requested decimal precision for Float shall be at least 6.
  15. If Long_Float is predefined for an implementation, then its requested decimal precision shall be at least 11. Implementation Permissions
  16. An implementation is allowed to provide additional predefined floating point types, declared in the visible part of Standard, whose (unconstrained) first subtypes have names of the form Short_Float, Long_Float, Short_Short_Float, Long_Long_Float, etc. Different predefined floating point types are allowed to have the same base decimal precision. However, the precision of Float should be no greater than that of Long_Float. Similarly, the precision of Short_Float (if provided) should be no greater than Float. Corresponding recommendations apply to any other predefined floating point types. There need not be a named floating point type corresponding to each distinct base decimal precision supported by an implementation. Implementation Advice
  17. An implementation should support Long_Float in addition to Float if the target machine supports 11 or more digits of precision. No other named floating point subtypes are recommended for package Standard. Instead, appropriate named floating point subtypes should be provided in the library package Interfaces, see section The Package Interfaces. NOTES
  18. (33) If a floating point subtype is unconstrained, then assignments to variables of the subtype involve only Overflow_Checks, never Range_Checks. Examples
  19. Examples of floating point types and subtypes:
  20. type Coefficient is digits 10 range -1.0 .. 1.0;
    
  21. type Real is digits 8;
    type Mass is digits 7 range 0.0 .. 1.0E35;
    
  22. subtype Probability is Real range 0.0 .. 1.0;
    --  a subtype with a smaller range
    

Operations of Floating Point Types

Static Semantics

  1. The following attribute is defined for every floating point subtype S:
  2. S'Digits
    S'Digits denotes the requested decimal precision for the
    subtype S. The value of this attribute is of the type
    universal_integer. The requested decimal precision of the
    base subtype of a floating point type T is defined to be the
    largest value of d for which ceiling(d * log(10) /
    log(T'Machine_Radix)) + 1 <= T'Model_Mantissa.
    
    NOTES
  3. (34) The predefined operations of a floating point type include the assignment operation, qualification, the membership tests, and explicit conversion to and from other numeric types. They also include the relational operators and the following predefined arithmetic operators: the binary and unary adding operators - and +, certain multiplying operators, the unary operator abs, and the exponentiation operator.
  4. (35) As for all types, objects of a floating point type have Size and Address attributes, see section Representation Attributes. Other attributes of floating point types are defined in section Attributes of Floating Point Types.

Fixed Point Types

  1. A fixed point type is either an ordinary fixed point type, or a decimal fixed point type. The error bound of a fixed point type is specified as an absolute value, called the delta of the fixed point type. Syntax
  2. fixed_point_definition ::=
       ordinary_fixed_point_definition | decimal_fixed_point_definition
    
  3. ordinary_fixed_point_definition ::=
       delta static_expression real_range_specification
    
  4. decimal_fixed_point_definition ::=
       delta static_expression digits static_expression
         [real_range_specification]
    
  5. digits_constraint ::=
       digits static_expression [range_constraint]
    
    Name Resolution Rules
  6. For a type defined by a fixed_point_definition, the delta of the type is specified by the value of the expression given after the reserved word delta; this expression is expected to be of any real type. For a type defined by a decimal_fixed_point_definition (a decimal fixed point type), the number of significant decimal digits for its first subtype (the digits of the first subtype) is specified by the expression given after the reserved word digits; this expression is expected to be of any integer type. Legality Rules
  7. In a fixed_point_definition or digits_constraint, the expressions given after the reserved words delta and digits shall be static; their values shall be positive.
  8. The set of values of a fixed point type comprise the integral multiples of a number called the small of the type. For a type defined by an ordinary_fixed_point_definition (an ordinary fixed point type), the small may be specified by an attribute_definition_clause, see section Representation Attributes, if so specified, it shall be no greater than the delta of the type. If not specified, the small of an ordinary fixed point type is an implementation-defined power of two less than or equal to the delta.
  9. For a decimal fixed point type, the small equals the delta; the delta shall be a power of 10. If a real_range_specification is given, both bounds of the range shall be in the range -(10**digits-1)*delta .. +(10**digits-1)*delta.
  10. A fixed_point_definition is illegal if the implementation does not support a fixed point type with the given small and specified range or digits.
  11. For a subtype_indication with a digits_constraint, the subtype_mark shall denote a decimal fixed point subtype. Static Semantics
  12. The base range, see section Scalar Types of a fixed point type is symmetric around zero, except possibly for an extra negative value in some implementations.
  13. An ordinary_fixed_point_definition defines an ordinary fixed point type whose base range includes at least all multiples of small that are between the bounds specified in the real_range_specification. The base range of the type does not necessarily include the specified bounds themselves. An ordinary_fixed_point_definition also defines a constrained first subtype of the type, with each bound of its range given by the closer to zero of:
    1. the value of the conversion to the fixed point type of the corresponding expression of the real_range_specification;
    2. the corresponding bound of the base range.
  1. A decimal_fixed_point_definition defines a decimal fixed point type whose base range includes at least the range -(10**digits-1)*delta .. +(10**digits-1)*delta. A decimal_fixed_point_definition also defines a constrained first subtype of the type. If a real_range_specification is given, the bounds of the first subtype are given by a conversion of the values of the expressions of the real_range_specification. Otherwise, the range of the first subtype is -(10**digits-1)*delta .. +(10**digits-1)*delta. Dynamic Semantics
  2. The elaboration of a fixed_point_definition creates the fixed point type and its first subtype.
  3. For a digits_constraint on a decimal fixed point subtype with a given delta, if it does not have a range_constraint, then it specifies an implicit range -(10**D-1)*delta .. +(10**D-1)*delta, where D is the value of the expression. A digits_constraint is compatible with a decimal fixed point subtype if the value of the expression is no greater than the digits of the subtype, and if it specifies (explicitly or implicitly) a range that is compatible with the subtype.
  4. The elaboration of a digits_constraint consists of the elaboration of the range_constraint, if any. If a range_constraint is given, a check is made that the bounds of the range are both in the range -(10**D-1)*delta .. +(10**D-1)*delta, where D is the value of the (static) expression given after the reserved word digits. If this check fails, Constraint_Error is raised. Implementation Requirements
  5. The implementation shall support at least 24 bits of precision (including the sign bit) for fixed point types. Implementation Permissions
  6. Implementations are permitted to support only smalls that are a power of two. In particular, all decimal fixed point type declarations can be disallowed. Note however that conformance with the Information Systems Annex requires support for decimal smalls, and decimal fixed point type declarations with digits up to at least 18. NOTES
  7. (36) The base range of an ordinary fixed point type need not include the specified bounds themselves so that the range specification can be given in a natural way, such as:
  8. type Fraction is delta 2.0**(-15) range -1.0 .. 1.0;
    
  9. With 2's complement hardware, such a type could have a signed 16-bit representation, using 1 bit for the sign and 15 bits for fraction, resulting in a base range of -1.0 .. 1.0-2.0**(-15). Examples
  10. Examples of fixed point types and subtypes:
  11. type Volt is delta 0.125 range 0.0 .. 255.0;
    
  12. --  A pure fraction which requires all the available
    --  space in a word can be declared as the type Fraction:
    
    type Fraction is delta System.Fine_Delta range -1.0 .. 1.0;
    --  Fraction'Last = 1.0 - System.Fine_Delta
    
  13. type Money is delta 0.01 digits 15;  -- decimal fixed point
    subtype Salary is Money digits 10;
      -- Money'Last = 10.0**13 - 0.01, Salary'Last = 10.0**8 - 0.01
    

Operations of Fixed Point Types

Static Semantics

  1. The following attributes are defined for every fixed point subtype S:
  2. S'Small
    S'Small denotes the small of the type of S. The value of
    this attribute is of the type universal_real. Small may
    be specified for nonderived fixed point types via an
    attribute_definition_clause, see section Representation Attributes; the expression
    of such a clause shall be static.
    
  3. S'Delta
    S'Delta denotes the delta of the fixed point subtype S. The
    value of this attribute is of the type universal_real.
    
  4. S'Fore
    S'Fore yields the minimum number of characters needed
    before the decimal point for the decimal representation
    of any value of the subtype S, assuming that the
    representation does not include an exponent, but
    includes a one-character prefix that is either a minus
    sign or a space. (This minimum number does not include
    superfluous zeros or underlines, and is at least 2.) The
    value of this attribute is of the type
    universal_integer.
    
  5. S'Aft
    S'Aft yields the number of decimal digits needed after the
    decimal point to accommodate the delta of the subtype S,
    unless the delta of the subtype S is greater than 0.1, in
    which case the attribute yields the value one. (S'Aft is the
    smallest positive integer N for which (10**N)*S'Delta is
    greater than or equal to one.) The value of this attribute
    is of the type universal_integer.
    
  6. The following additional attributes are defined for every decimal fixed point subtype S:
  7. S'Digits
    S'Digits denotes the digits of the decimal fixed point
    subtype S, which corresponds to the number of decimal digits
    that are representable in objects of the subtype. The value
    of this attribute is of the type universal_integer. Its
    value is determined as follows:
    
    1. For a first subtype or a subtype defined by a subtype_indication with a digits_constraint, the digits is the value of the expression given after the reserved word digits;
    2. For a subtype defined by a subtype_indication without a digits_constraint, the digits of the subtype is the same as that of the subtype denoted by the subtype_mark in the subtype_indication.
    3. The digits of a base subtype is the largest integer D such that the range -(10**D-1)*delta .. +(10**D-1)*delta is included in the base range of the type.
  1. S'Scale
    S'Scale denotes the scale of the subtype S, defined as the
    value N such that S'Delta = 10.0**(-N). The scale indicates
    the position of the point relative to the rightmost
    significant digits of values of subtype S. The value of this
    attribute is of the type universal_integer.
    
  2. S'Round
      S'Round denotes a function with the following specification:
    1. function S'Round(X : universal_real)
        return S'Base
      
    2. The function returns the value obtained by rounding X (away from 0, if X is midway between two values of the type of S).
    NOTES
  1. (37) All subtypes of a fixed point type will have the same value for the Delta attribute, in the absence of delta_constraints, see section Reduced Accuracy Subtypes.
  2. (38) S'Scale is not always the same as S'Aft for a decimal subtype; for example, if S'Delta = 1.0 then S'Aft is 1 while S'Scale is 0.
  3. (39) The predefined operations of a fixed point type include the assignment operation, qualification, the membership tests, and explicit conversion to and from other numeric types. They also include the relational operators and the following predefined arithmetic operators: the binary and unary adding operators - and +, multiplying operators, and the unary operator abs.
  4. (40) As for all types, objects of a fixed point type have Size and Address attributes, see section Representation Attributes. Other attributes of fixed point types are defined in section Attributes of Fixed Point Types.

Array Types

  1. An array object is a composite object consisting of components which all have the same subtype. The name for a component of an array uses one or more index values belonging to specified discrete types. The value of an array object is a composite value consisting of the values of the components. Syntax
  2. array_type_definition ::=
       unconstrained_array_definition | constrained_array_definition
    
  3. unconstrained_array_definition ::=
       array(index_subtype_definition {, index_subtype_definition})
         of component_definition
    
  4. index_subtype_definition ::= subtype_mark range <>
    
  5. constrained_array_definition ::=
       array (discrete_subtype_definition
         {, discrete_subtype_definition}) of component_definition
    
  6. discrete_subtype_definition ::= discrete_subtype_indication | range
    
  7. component_definition ::= [aliased] subtype_indication
    
    Name Resolution Rules
  8. For a discrete_subtype_definition that is a range, the range shall resolve to be of some specific discrete type; which discrete type shall be determined without using any context other than the bounds of the range itself (plus the preference for root_integer -- see section The Context of Overload Resolution.). Legality Rules
  9. Each index_subtype_definition or discrete_subtype_definition in an array_type_definition defines an index subtype; its type (the index type) shall be discrete.
  10. The subtype defined by the subtype_indication of a component_definition (the component subtype) shall be a definite subtype.
  11. Within the definition of a nonlimited composite type (or a limited composite type that later in its immediate scope becomes nonlimited -- See section Private Operations, and section Limited Types.), if a component_definition contains the reserved word aliased and the type of the component is discriminated, then the nominal subtype of the component shall be constrained. Static Semantics
  12. An array is characterized by the number of indices (the dimensionality of the array), the type and position of each index, the lower and upper bounds for each index, and the subtype of the components. The order of the indices is significant.
  13. A one-dimensional array has a distinct component for each possible index value. A multidimensional array has a distinct component for each possible sequence of index values that can be formed by selecting one value for each index position (in the given order). The possible values for a given index are all the values between the lower and upper bounds, inclusive; this range of values is called the index range. The bounds of an array are the bounds of its index ranges. The length of a dimension of an array is the number of values of the index range of the dimension (zero for a null range). The length of a one-dimensional array is the length of its only dimension.
  14. An array_type_definition defines an array type and its first subtype. For each object of this array type, the number of indices, the type and position of each index, and the subtype of the components are as in the type definition; the values of the lower and upper bounds for each index belong to the corresponding index subtype of its type, except for null arrays, see section Index Constraints and Discrete Ranges.
  15. An unconstrained_array_definition defines an array type with an unconstrained first subtype. Each index_subtype_definition defines the corresponding index subtype to be the subtype denoted by the subtype_mark. The compound delimiter <> (called a box) of an index_subtype_definition stands for an undefined range (different objects of the type need not have the same bounds).
  16. A constrained_array_definition defines an array type with a constrained first subtype. Each discrete_subtype_definition defines the corresponding index subtype, as well as the corresponding index range for the constrained first subtype. The constraint of the first subtype consists of the bounds of the index ranges.
  17. The discrete subtype defined by a discrete_subtype_definition is either that defined by the subtype_indication, or a subtype determined by the range as follows:
    1. If the type of the range resolves to root_integer, then the discrete_subtype_definition defines a subtype of the predefined type Integer with bounds given by a conversion to Integer of the bounds of the range;
    2. Otherwise, the discrete_subtype_definition defines a subtype of the type of the range, with the bounds given by the range.
  1. The component_definition of an array_type_definition defines the nominal subtype of the components. If the reserved word aliased appears in the component_definition, then each component of the array is aliased, See section Access Types. Dynamic Semantics
  2. The elaboration of an array_type_definition creates the array type and its first subtype, and consists of the elaboration of any discrete_subtype_definitions and the component_definition.
  3. The elaboration of a discrete_subtype_definition creates the discrete subtype, and consists of the elaboration of the subtype_indication or the evaluation of the range. The elaboration of a component_definition in an array_type_definition consists of the elaboration of the subtype_indication. The elaboration of any discrete_subtype_definitions and the elaboration of the component_definition are performed in an arbitrary order. NOTES
  4. (41) All components of an array have the same subtype. In particular, for an array of components that are one-dimensional arrays, this means that all components have the same bounds and hence the same length.
  5. (42) Each elaboration of an array_type_definition creates a distinct array type. A consequence of this is that each object whose object_declaration contains an array_type_definition is of its own unique type. Examples
  6. Examples of type declarations with unconstrained array definitions:
  7. type Vector     is array(Integer  range <>) of Real;
    
    type Matrix     is array(Integer  range <>, Integer range <>)
      of Real;
    
    type Bit_Vector is array(Integer  range <>) of Boolean;
    
    type Roman      is array(Positive range <>) of
      Roman_Digit;  --  see section Character Types
    
    
  8. Examples of type declarations with constrained array definitions:
  9. type Table    is array(1 .. 10) of Integer;
    type Schedule is array(Day) of Boolean;
    type Line     is array(1 .. Max_Line_Size) of Character;
    
  10. Examples of object declarations with array type definitions:
  11. Grid : array(1 .. 80, 1 .. 100) of Boolean;
    Mix  : array(Color range Red .. Green) of Boolean;
    Page : array(Positive range <>) of Line :=  --  an array of arrays
      (1 | 50  => Line'(1 | Line'Last => '+', others => '-'),
      --  see section Array Aggregates
       2 .. 49 => Line'(1 | Line'Last => '|', others => ' '));
        -- Page is constrained by its initial value to (1..50)
    

Index Constraints and Discrete Ranges

  1. An index_constraint determines the range of possible values for every index of an array subtype, and thereby the corresponding array bounds. Syntax
  2. index_constraint ::= (discrete_range {, discrete_range})
    
  3. discrete_range ::= discrete_subtype_indication | range
    
    Name Resolution Rules
  4. The type of a discrete_range is the type of the subtype defined by the subtype_indication, or the type of the range. For an index_constraint, each discrete_range shall resolve to be of the type of the corresponding index. Legality Rules
  5. An index_constraint shall appear only in a subtype_indication whose subtype_mark denotes either an unconstrained array subtype, or an unconstrained access subtype whose designated subtype is an unconstrained array subtype; in either case, the index_constraint shall provide a discrete_range for each index of the array type. Static Semantics
  6. A discrete_range defines a range whose bounds are given by the range, or by the range of the subtype defined by the subtype_indication. Dynamic Semantics
  7. An index_constraint is compatible with an unconstrained array subtype if and only if the index range defined by each discrete_range is compatible, see section Scalar Types, with the corresponding index subtype. If any of the discrete_ranges defines a null range, any array thus constrained is a null array, having no components. An array value satisfies an index_constraint if at each index position the array value and the index_constraint have the same index bounds.
  8. The elaboration of an index_constraint consists of the evaluation of the discrete_range(s), in an arbitrary order. The evaluation of a discrete_range consists of the elaboration of the subtype_indication or the evaluation of the range. NOTES
  9. (43) The elaboration of a subtype_indication consisting of a subtype_mark followed by an index_constraint checks the compatibility of the index_constraint with the subtype_mark, see section Subtype Declarations.
  10. (44) Even if an array value does not satisfy the index constraint of an array subtype, Constraint_Error is not raised on conversion to the array subtype, so long as the length of each dimension of the array value and the array subtype match. See section Type Conversions. Examples
  11. Examples of array declarations including an index constraint:
  12. Board     : Matrix(1 .. 8,  1 .. 8);  --  see section Array Types
    Rectangle : Matrix(1 .. 20, 1 .. 30);
    Inverse   : Matrix(1 .. N,  1 .. N);  --  N need not be static
    
  13. Filter    : Bit_Vector(0 .. 31);
    
  14. Example of array declaration with a constrained array subtype:
  15. My_Schedule : Schedule;
    --  all arrays of type Schedule have the same bounds
    
  16. Example of record type with a component that is an array:
  17. type Var_Line(Length : Natural) is
       record
          Image : String(1 .. Length);
       end record;
    
  18. Null_Line : Var_Line(0);  --  Null_Line.Image is a null array
    

Operations of Array Types

Legality Rules

  1. The argument N used in the attribute_designators for the N-th dimension of an array shall be a static expression of some integer type. The value of N shall be positive (nonzero) and no greater than the dimensionality of the array. Static Semantics
  2. The following attributes are defined for a prefix A that is of an array type (after any implicit dereference), or denotes a constrained array subtype:
  3. A'First
    A'First denotes the lower bound of the first index range; its
    type is the corresponding index type.
    
  4. A'First(N)
    A'First(N) denotes the lower bound of the N-th index range;
    its type is the corresponding index type.
    
  5. A'Last
    A'Last denotes the upper bound of the first index range; its
    type is the corresponding index type.
    
  6. A'Last(N)
    A'Last(N) denotes the upper bound of the N-th index range;
    its type is the corresponding index type.
    
  7. A'Range
    A'Range is equivalent to the range A'First .. A'Last, except
    that the prefix A is only evaluated once.
    
  8. A'Range(N)
    A'Range(N) is equivalent to the range A'First(N) ..
    A'Last(N), except that the prefix A is only evaluated once.
    
  9. A'Length
    A'Length denotes the number of values of the first index
    range (zero for a null range); its type is universal_integer.
    
  10. A'Length(N)
    A'Length(N) denotes the number of values of the N-th index
    range (zero for a null range); its type is universal_integer.
    
    Implementation Advice
  11. An implementation should normally represent multidimensional arrays in row-major order, consistent with the notation used for multidimensional array aggregates, see section Array Aggregates. However, if a pragma Convention(Fortran, ...) applies to a multidimensional array type, then column-major order should be used instead, see section Interfacing with Fortran. NOTES
  12. (45) The attribute_references A'First and A'First(1) denote the same value. A similar relation exists for the attribute_references A'Last, A'Range, and A'Length. The following relation is satisfied (except for a null array) by the above attributes if the index type is an integer type:
  13. A'Length(N) = A'Last(N) - A'First(N) + 1
    
  14. (46) An array type is limited if its component type is limited, see section Limited Types.
  15. (47) The predefined operations of an array type include the membership tests, qualification, and explicit conversion. If the array type is not limited, they also include assignment and the predefined equality operators. For a one-dimensional array type, they include the predefined concatenation operators (if nonlimited) and, if the component type is discrete, the predefined relational operators; if the component type is boolean, the predefined logical operators are also included.
  16. (48) A component of an array can be named with an indexed_component. A value of an array type can be specified with an array_aggregate, unless the array type is limited. For a one-dimensional array type, a slice of the array can be named; also, string literals are defined if the component type is a character type. Examples
  17. Examples (using arrays declared in the examples of subclause See section Index Constraints and Discrete Ranges.):
  18. --  Filter'First       =   0
    --  Filter'Last        =  31
    --  Filter'Length      =  32
    --  Rectangle'Last(1)  =  20
    --  Rectangle'Last(2)  =  30
    

String Types

Static Semantics

  1. A one-dimensional array type whose component type is a character type is called a string type.
  2. There are two predefined string types, String and Wide_String, each indexed by values of the predefined subtype Positive; these are declared in the visible part of package Standard:
  3. subtype Positive is Integer range 1 .. Integer'Last;
    
  4. type String is array(Positive range <>) of Character;
    type Wide_String is array(Positive range <>) of Wide_Character;
    
    NOTES
  5. (49) String literals, see section String Literals, and section Literals, are defined for all string types. The concatenation operator & is predefined for string types, as for all nonlimited one-dimensional array types. The ordering operators <, <=, >, and >= are predefined for string types, as for all one-dimensional discrete array types; these ordering operators correspond to lexicographic order, see section Relational Operators and Membership Tests. Examples
  6. Examples of string objects:
  7. Stars      : String(1 .. 120) := (1 .. 120 => '*' );
    Question   : constant String  := "How many characters?";
    --  Question'First = 1, Question'Last = 20
    --  Question'Length = 20 (the number of characters)
    
  8. Ask_Twice  : String  := Question & Question;
    --  constrained to (1..40)
    
    Ninety_Six : constant Roman   := "XCVI";
    --  see section Character Types, and section Array Types
    

Discriminants

  1. A composite type (other than an array type) can have discriminants, which parameterize the type. A known_discriminant_part specifies the discriminants of a composite type. A discriminant of an object is a component of the object, and is either of a discrete type or an access type. An unknown_discriminant_part in the declaration of a partial view of a type specifies that the discriminants of the type are unknown for the given view; all subtypes of such a partial view are indefinite subtypes. Syntax
  2. discriminant_part ::=
       unknown_discriminant_part | known_discriminant_part
    
  3. unknown_discriminant_part ::= (<>)
    
  4. known_discriminant_part ::=
       (discriminant_specification {; discriminant_specification})
    
  5. discriminant_specification ::=
         defining_identifier_list : subtype_mark
           [:= default_expression]
       | defining_identifier_list : access_definition
           [:= default_expression]
    
  6. default_expression ::= expression
    
    Name Resolution Rules
  7. The expected type for the default_expression of a discriminant_specification is that of the corresponding discriminant. Legality Rules
  8. A known_discriminant_part is only permitted in a declaration for a composite type that is not an array type (this includes generic formal types); a type declared with a known_discriminant_part is called a discriminated type, as is a type that inherits (known) discriminants.
  9. The subtype of a discriminant may be defined by a subtype_mark, in which case the subtype_mark shall denote a discrete or access subtype, or it may be defined by an access_definition (in which case the subtype_mark of the access_definition may denote any kind of subtype). A discriminant that is defined by an access_definition is called an access discriminant and is of an anonymous general access-to-variable type whose designated subtype is denoted by the subtype_mark of the access_definition.
  10. A discriminant_specification for an access discriminant shall appear only in the declaration for a task or protected type, or for a type with the reserved word limited in its (full) definition or in that of one of its ancestors. In addition to the places where Legality Rules normally apply, see section Generic Instantiation, this rule applies also in the private part of an instance of a generic unit.
  11. Default_expressions shall be provided either for all or for none of the discriminants of a known_discriminant_part. No default_expressions are permitted in a known_discriminant_part in a declaration of a tagged type or a generic formal type.
  12. For a type defined by a derived_type_definition, if a known_discriminant_part is provided in its declaration, then:
    1. The parent subtype shall be constrained;
    2. If the parent type is not a tagged type, then each discriminant of the derived type shall be used in the constraint defining the parent subtype;
    3. If a discriminant is used in the constraint defining the parent subtype, the subtype of the discriminant shall be statically compatible, See section Statically Matching Constraints and Subtypes, with the subtype of the corresponding parent discriminant.
  1. The type of the default_expression, if any, for an access discriminant shall be convertible to the anonymous access type of the discriminant, See section Type Conversions. Static Semantics
  2. A discriminant_specification declares a discriminant; the subtype_mark denotes its subtype unless it is an access discriminant, in which case the discriminant's subtype is the anonymous access-to-variable subtype defined by the access_definition.
  3. For a type defined by a derived_type_definition, each discriminant of the parent type is either inherited, constrained to equal some new discriminant of the derived type, or constrained to the value of an expression. When inherited or constrained to equal some new discriminant, the parent discriminant and the discriminant of the derived type are said to correspond. Two discriminants also correspond if there is some common discriminant to which they both correspond. A discriminant corresponds to itself as well. If a discriminant of a parent type is constrained to a specific value by a derived_type_definition, then that discriminant is said to be specified by that derived_type_definition.
  4. A constraint that appears within the definition of a discriminated type depends on a discriminant of the type if it names the discriminant as a bound or discriminant value. A component_definition depends on a discriminant if its constraint depends on the discriminant, or on a discriminant that corresponds to it.
  5. A component depends on a discriminant if:
    1. Its component_definition depends on the discriminant; or
    2. It is declared in a variant_part that is governed by the discriminant; or
    3. It is a component inherited as part of a derived_type_definition, and the constraint of the parent_subtype_indication depends on the discriminant; or
    4. It is a subcomponent of a component that depends on the discriminant.
  1. Each value of a discriminated type includes a value for each component of the type that does not depend on a discriminant; this includes the discriminants themselves. The values of discriminants determine which other component values are present in the value of the discriminated type.
  2. A type declared with a known_discriminant_part is said to have known discriminants; its first subtype is unconstrained. A type declared with an unknown_discriminant_part is said to have unknown discriminants. A type declared without a discriminant_part has no discriminants, unless it is a derived type; if derived, such a type has the same sort of discriminants (known, unknown, or none) as its parent (or ancestor) type. A tagged class-wide type also has unknown discriminants. Any subtype of a type with unknown discriminants is an unconstrained and indefinite subtype, see section Types and Subtypes, and section Objects and Named Numbers. Dynamic Semantics
  3. An access_definition is elaborated when the value of a corresponding access discriminant is defined, either by evaluation of its default_expression or by elaboration of a discriminant_constraint. The elaboration of an access_definition creates the anonymous access type. When the expression defining the access discriminant is evaluated, it is converted to this anonymous access type, see section Type Conversions. NOTES
  4. (50) If a discriminated type has default_expressions for its discriminants, then unconstrained variables of the type are permitted, and the values of the discriminants can be changed by an assignment to such a variable. If defaults are not provided for the discriminants, then all variables of the type are constrained, either by explicit constraint or by their initial value; the values of the discriminants of such a variable cannot be changed after initialization.
  5. (51) The default_expression for a discriminant of a type is evaluated when an object of an unconstrained subtype of the type is created.
  6. (52) Assignment to a discriminant of an object (after its initialization) is not allowed, since the name of a discriminant is a constant; neither assignment_statements nor assignments inherent in passing as an in out or out parameter are allowed. Note however that the value of a discriminant can be changed by assigning to the enclosing object, presuming it is an unconstrained variable.
  7. (53) A discriminant that is of a named access type is not called an access discriminant; that term is used only for discriminants defined by an access_definition. Examples
  8. Examples of discriminated types:
  9. type Buffer(Size : Buffer_Size := 100) is  --  see section Integer Types
       record
          Pos   : Buffer_Size := 0;
          Value : String(1 .. Size);
       end record;
    
  10. type Matrix_Rec(Rows, Columns : Integer) is
       record
          Mat : Matrix(1 .. Rows, 1 .. Columns);  --  see section Array Types
       end record;
    
  11. type Square(Side : Integer) is new
      Matrix_Rec(Rows => Side, Columns => Side);
    
  12. type Double_Square(Number : Integer) is
       record
          Left  : Square(Number);
          Right : Square(Number);
       end record;
    
    type Item(Number : Positive) is
       record
          Content : Integer;
          --  no component depends on the discriminant
       end record;
    

Discriminant Constraints

  1. A discriminant_constraint specifies the values of the discriminants for a given discriminated type. Syntax
  2. discriminant_constraint ::=
       (discriminant_association {, discriminant_association})
    
  3. discriminant_association ::=
       [discriminant_selector_name
         {| discriminant_selector_name} =>] expression
    
    1. A discriminant_association is said to be named if it has one or more discriminant_selector_names; it is otherwise said to be positional. In a discriminant_constraint, any positional associations shall precede any named associations.

Name Resolution Rules

  1. Each selector_name of a named discriminant_association shall resolve to denote a discriminant of the subtype being constrained; the discriminants so named are the associated discriminants of the named association. For a positional association, the associated discriminant is the one whose discriminant_specification occurred in the corresponding position in the known_discriminant_part that defined the discriminants of the subtype being constrained.
  2. The expected type for the expression in a discriminant_association is that of the associated discriminant(s). Legality Rules
  3. A discriminant_constraint is only allowed in a subtype_indication whose subtype_mark denotes either an unconstrained discriminated subtype, or an unconstrained access subtype whose designated subtype is an unconstrained discriminated subtype.
  4. A named discriminant_association with more than one selector_name is allowed only if the named discriminants are all of the same type. A discriminant_constraint shall provide exactly one value for each discriminant of the subtype being constrained.
  5. The expression associated with an access discriminant shall be of a type convertible to the anonymous access type. Dynamic Semantics
  6. A discriminant_constraint is compatible with an unconstrained discriminated subtype if each discriminant value belongs to the subtype of the corresponding discriminant.
  7. A composite value satisfies a discriminant constraint if and only if each discriminant of the composite value has the value imposed by the discriminant constraint.
  8. For the elaboration of a discriminant_constraint, the expressions in the discriminant_associations are evaluated in an arbitrary order and converted to the type of the associated discriminant (which might raise Constraint_Error -- see section Type Conversions.); the expression of a named association is evaluated (and converted) once for each associated discriminant. The result of each evaluation and conversion is the value imposed by the constraint for the associated discriminant. NOTES
  9. (54) The rules of the language ensure that a discriminant of an object always has a value, either from explicit or implicit initialization. Examples
  10. Examples (using types declared above in clause See section Discriminants.):
  11. Large   : Buffer(200);  --  constrained, always 200 characters
                            --   (explicit discriminant value)
    Message : Buffer;       --  unconstrained, initially 100 characters
                            --   (default discriminant value)
    Basis   : Square(5);    --  constrained, always 5 by 5
    Illegal : Square;       --  illegal, a Square has to be constrained
    

Operations of Discriminated Types

  1. If a discriminated type has default_expressions for its discriminants, then unconstrained variables of the type are permitted, and the discriminants of such a variable can be changed by assignment to the variable. For a formal parameter of such a type, an attribute is provided to determine whether the corresponding actual parameter is constrained or unconstrained. Static Semantics
  2. For a prefix A that is of a discriminated type (after any implicit dereference), the following attribute is defined:
  3. A'Constrained
    Yields the value True if A denotes a constant, a value, or a
    constrained variable, and False otherwise.
    
    Erroneous Execution
  4. The execution of a construct is erroneous if the construct has a constituent that is a name denoting a subcomponent that depends on discriminants, and the value of any of these discriminants is changed by this execution between evaluating the name and the last use (within this execution) of the subcomponent denoted by the name.

Record Types

  1. A record object is a composite object consisting of named components. The value of a record object is a composite value consisting of the values of the components. Syntax
  2. record_type_definition ::=
       [[abstract] tagged] [limited] record_definition
    
  3. record_definition ::=
         record
            component_list
         end record
       | null record
    
  4. component_list ::=
         component_item {component_item}
       | {component_item} variant_part
       |  null;
    
  5. component_item ::= component_declaration | representation_clause
    
  6. component_declaration ::=
       defining_identifier_list : component_definition
         [:= default_expression];
    
    Name Resolution Rules
  7. The expected type for the default_expression, if any, in a component_declaration is the type of the component. Legality Rules
  8. A default_expression is not permitted if the component is of a limited type.
  9. Each component_declaration declares a component of the record type. Besides components declared by component_declarations, the components of a record type include any components declared by discriminant_specifications of the record type declaration. The identifiers of all components of a record type shall be distinct.
  10. Within a type_declaration, a name that denotes a component, protected subprogram, or entry of the type is allowed only in the following cases:
    1. A name that denotes any component, protected subprogram, or entry is allowed within a representation item that occurs within the declaration of the composite type.
    2. A name that denotes a noninherited discriminant is allowed within the declaration of the type, but not within the discriminant_part. If the discriminant is used to define the constraint of a component, the bounds of an entry family, or the constraint of the parent subtype in a derived_type_definition then its name shall appear alone as a direct_name (not as part of a larger expression or expanded name). A discriminant shall not be used to define the constraint of a scalar component.
  1. If the name of the current instance of a type, see section The Context of Overload Resolution, is used to define the constraint of a component, then it shall appear as a direct_name that is the prefix of an attribute_reference whose result is of an access type, and the attribute_reference shall appear alone. Static Semantics
  2. The component_definition of a component_declaration defines the (nominal) subtype of the component. If the reserved word aliased appears in the component_definition, then the component is aliased, see section Access Types.
  3. If the component_list of a record type is defined by the reserved word null and there are no discriminants, then the record type has no components and all records of the type are null records. A record_definition of null record is equivalent to record null; end record. Dynamic Semantics
  4. The elaboration of a record_type_definition creates the record type and its first subtype, and consists of the elaboration of the record_definition. The elaboration of a record_definition consists of the elaboration of its component_list, if any.
  5. The elaboration of a component_list consists of the elaboration of the component_items and variant_part, if any, in the order in which they appear. The elaboration of a component_declaration consists of the elaboration of the component_definition.
  6. Within the definition of a composite type, if a component_definition or discrete_subtype_definition, see section Entries and Accept Statements, includes a name that denotes a discriminant of the type, or that is an attribute_reference whose prefix denotes the current instance of the type, the expression containing the name is called a per-object expression, and the constraint being defined is called a per-object constraint. For the elaboration of a component_definition of a component_declaration, if the constraint of the subtype_indication is not a per-object constraint, then the subtype_indication is elaborated. On the other hand, if the constraint is a per-object constraint, then the elaboration consists of the evaluation of any included expression that is not part of a per-object expression. NOTES
  7. (55) A component_declaration with several identifiers is equivalent to a sequence of single component_declarations, as explained in section Object Declarations.
  8. (56) The default_expression of a record component is only evaluated upon the creation of a default-initialized object of the record type (presuming the object has the component, if it is in a variant_part -- See section Object Declarations.).
  9. (57) The subtype defined by a component_definition, see section Array Types, has to be a definite subtype.
  10. (58) If a record type does not have a variant_part, then the same components are present in all values of the type.
  11. (59) A record type is limited if it has the reserved word limited in its definition, or if any of its components are limited, see section Limited Types.
  12. (60) The predefined operations of a record type include membership tests, qualification, and explicit conversion. If the record type is nonlimited, they also include assignment and the predefined equality operators.
  13. (61) A component of a record can be named with a selected_component. A value of a record can be specified with a record_aggregate, unless the record type is limited. Examples
  14. Examples of record type declarations:
  15. type Date is
       record
          Day   : Integer range 1 .. 31;
          Month : Month_Name;
          Year  : Integer range 0 .. 4000;
       end record;
    
  16. type Complex is
       record
          Re : Real := 0.0;
          Im : Real := 0.0;
       end record;
    
  17. Examples of record variables:
  18. Tomorrow, Yesterday : Date;
    A, B, C : Complex;
    
  19. -- both components of A, B, and C are implicitly initialized to zero
    

Variant Parts and Discrete Choices

  1. A record type with a variant_part specifies alternative lists of components. Each variant defines the components for the value or values of the discriminant covered by its discrete_choice_list. Syntax
  2. variant_part ::=
       case discriminant_direct_name is
          variant
          {variant}
       end case;
    
  3. variant ::=
       when discrete_choice_list =>
          component_list
    
  4. discrete_choice_list ::= discrete_choice {| discrete_choice}
    
  5. discrete_choice ::= expression | discrete_range | others
    
    Name Resolution Rules
  6. The discriminant_direct_name shall resolve to denote a discriminant (called the discriminant of the variant_part) specified in the known_discriminant_part of the full_type_declaration that contains the variant_part. The expected type for each discrete_choice in a variant is the type of the discriminant of the variant_part. Legality Rules
  7. The discriminant of the variant_part shall be of a discrete type.
  8. The expressions and discrete_ranges given as discrete_choices in a variant_part shall be static. The discrete_choice others shall appear alone in a discrete_choice_list, and such a discrete_choice_list, if it appears, shall be the last one in the enclosing construct.
  9. A discrete_choice is defined to cover a value in the following cases:
    1. A discrete_choice that is an expression covers a value if the value equals the value of the expression converted to the expected type.
    2. A discrete_choice that is a discrete_range covers all values (possibly none) that belong to the range.
    3. The discrete_choice others covers all values of its expected type that are not covered by previous discrete_choice_lists of the same construct.
  1. A discrete_choice_list covers a value if one of its discrete_choices covers the value.
  2. The possible values of the discriminant of a variant_part shall be covered as follows:
    1. If the discriminant is of a static constrained scalar subtype, then each non-others discrete_choice shall cover only values in that subtype, and each value of that subtype shall be covered by some discrete_choice (either explicitly or by others);
    2. If the type of the discriminant is a descendant of a generic formal scalar type then the variant_part shall have an others discrete_choice;
    3. Otherwise, each value of the base range of the type of the discriminant shall be covered (either explicitly or by others).
  1. Two distinct discrete_choices of a variant_part shall not cover the same value. Static Semantics
  2. If the component_list of a variant is specified by null, the variant has no components.
  3. The discriminant of a variant_part is said to govern the variant_part and its variants. In addition, the discriminant of a derived type governs a variant_part and its variants if it corresponds, see section Discriminants, to the discriminant of the variant_part. Dynamic Semantics
  4. A record value contains the values of the components of a particular variant only if the value of the discriminant governing the variant is covered by the discrete_choice_list of the variant. This rule applies in turn to any further variant that is, itself, included in the component_list of the given variant.
  5. The elaboration of a variant_part consists of the elaboration of the component_list of each variant in the order in which they appear. Examples
  6. Example of record type with a variant part:
  7. type Device is (Printer, Disk, Drum);
    type State  is (Open, Closed);
    
  8. type Peripheral(Unit : Device := Disk) is
       record
          Status : State;
          case Unit is
             when Printer =>
                Line_Count : Integer range 1 .. Page_Size;
             when others =>
                Cylinder   : Cylinder_Index;
                Track      : Track_Number;
             end case;
          end record;
    
  9. Examples of record subtypes:
  10. subtype Drum_Unit is Peripheral(Drum);
    subtype Disk_Unit is Peripheral(Disk);
    
  11. Examples of constrained record variables:
  12. Writer   : Peripheral(Unit  => Printer);
    Archive  : Disk_Unit;
    

Tagged Types and Type Extensions

  1. Tagged types and type extensions support object-oriented programming, based on inheritance with extension and run-time polymorphism via dispatching operations. Static Semantics
  2. A record type or private type that has the reserved word tagged in its declaration is called a tagged type. When deriving from a tagged type, additional components may be defined. As for any derived type, additional primitive subprograms may be defined, and inherited primitive subprograms may be overridden. The derived type is called an extension of the ancestor type, or simply a type extension. Every type extension is also a tagged type, and is either a record extension or a private extension of some other tagged type. A record extension is defined by a derived_type_definition with a record_extension_part. A private extension, which is a partial view of a record extension, can be declared in the visible part of a package, see section Private Types and Private Extensions, or in a generic formal part, see section Formal Private and Derived Types.
  3. An object of a tagged type has an associated (run-time) tag that identifies the specific tagged type used to create the object originally. The tag of an operand of a class-wide tagged type T'Class controls which subprogram body is to be executed when a primitive subprogram of type T is applied to the operand, see section Dispatching Operations of Tagged Types, using a tag to control which body to execute is called dispatching.
  4. The tag of a specific tagged type identifies the full_type_declaration of the type. If a declaration for a tagged type occurs within a generic_package_declaration, then the corresponding type declarations in distinct instances of the generic package are associated with distinct tags. For a tagged type that is local to a generic package body, the language does not specify whether repeated instantiations of the generic body result in distinct tags.
  5. The following language-defined library package exists:
  6. package Ada.Tags is
        type Tag is private;
    
  7.     function Expanded_Name(T : Tag) return String;
        function External_Tag(T : Tag) return String;
        function Internal_Tag(External : String) return Tag;
    
  8.     Tag_Error : exception;
    
  9. private
       ... -- not specified by the language
    end Ada.Tags;
    
  10. The function Expanded_Name returns the full expanded name of the first subtype of the specific type identified by the tag, in upper case, starting with a root library unit. The result is implementation defined if the type is declared within an unnamed block_statement.
  11. The function External_Tag returns a string to be used in an external representation for the given tag. The call External_Tag(S'Tag) is equivalent to the attribute_reference S'External_Tag, see section Representation Attributes.
  12. The function Internal_Tag returns the tag that corresponds to the given external tag, or raises Tag_Error if the given string is not the external tag for any specific type of the partition.
  13. For every subtype S of a tagged type T (specific or class-wide), the following attributes are defined:
  14. S'Class
    S'Class denotes a subtype of the class-wide type (called
    T'Class in this International Standard) for the class rooted
    at T (or if S already denotes a class-wide subtype, then
    S'Class is the same as S).
    
    1. S'Class is unconstrained. However, if S is constrained, then the values of S'Class are only those that when converted to the type T belong to S.
  1. S'Tag
    S'Tag denotes the tag of the type T (or if T is class-wide,
    the tag of the root type of the corresponding class). The
    value of this attribute is of type Tag.
    
  2. Given a prefix X that is of a class-wide tagged type (after any implicit dereference), the following attribute is defined:
  3. X'Tag
    X'Tag denotes the tag of X. The value of this attribute is of
    type Tag.
    
    Dynamic Semantics
  4. The tag associated with an object of a tagged type is determined as follows:
    1. The tag of a stand-alone object, a component, or an aggregate of a specific tagged type T identifies T.
    2. The tag of an object created by an allocator for an access type with a specific designated tagged type T, identifies T.
    3. The tag of an object of a class-wide tagged type is that of its initialization expression.
    4. The tag of the result returned by a function whose result type is a specific tagged type T identifies T.
    5. The tag of the result returned by a function with a class-wide result type is that of the return expression.
  1. The tag is preserved by type conversion and by parameter passing. The tag of a value is the tag of the associated object, see section Formal Parameter Modes. Implementation Permissions
  2. The implementation of the functions in Ada.Tags may raise Tag_Error if no specific type corresponding to the tag passed as a parameter exists in the partition at the time the function is called. NOTES
  3. (62) A type declared with the reserved word tagged should normally be declared in a package_specification, so that new primitive subprograms can be declared for it.
  4. (63) Once an object has been created, its tag never changes.
  5. (64) Class-wide types are defined to have unknown discriminants, See section Discriminants. This means that objects of a class-wide type have to be explicitly initialized (whether created by an object_declaration or an allocator), and that aggregates have to be explicitly qualified with a specific type when their expected type is class-wide.
  6. (65) If S denotes an untagged private type whose full type is tagged, then S'Class is also allowed before the full type definition, but only in the private part of the package in which the type is declared, See section Private Operations. Similarly, the Class attribute is defined for incomplete types whose full type is tagged, but only within the library unit in which the incomplete type is declared, see section Incomplete Type Declarations. Examples
  7. Examples of tagged record types:
  8. type Point is tagged
      record
        X, Y : Real := 0.0;
      end record;
    
  9. type Expression is tagged null record;
      -- Components will be added by each extension
    

Type Extensions

  1. Every type extension is a tagged type, and is either a record extension or a private extension of some other tagged type. Syntax
  2. record_extension_part ::= with record_definition
    
    Legality Rules
  3. The parent type of a record extension shall not be a class-wide type. If the parent type is nonlimited, then each of the components of the record_extension_part shall be nonlimited. The accessibility level, See section Operations of Access Types, of a record extension shall not be statically deeper than that of its parent type. In addition to the places where Legality Rules normally apply, see section Generic Instantiation, these rules apply also in the private part of an instance of a generic unit.
  4. A type extension shall not be declared in a generic body if the parent type is declared outside that body. Dynamic Semantics
  5. The elaboration of a record_extension_part consists of the elaboration of the record_definition. NOTES
  6. (66) The term "type extension" refers to a type as a whole. The term "extension part" refers to the piece of text that defines the additional components (if any) the type extension has relative to its specified ancestor type.
  7. (67) The accessibility rules imply that a tagged type declared in a library package_specification can be extended only at library level or as a generic formal. When the extension is declared immediately within a package_body, primitive subprograms are inherited and are overridable, but new primitive subprograms cannot be added.
  8. (68) A name that denotes a component (including a discriminant) of the parent type is not allowed within the record_extension_part. Similarly, a name that denotes a component defined within the record_extension_part is not allowed within the record_extension_part. It is permissible to use a name that denotes a discriminant of the record extension, providing there is a new known_discriminant_part in the enclosing type declaration. (The full rule is given in section Record Types.)
  9. (69) Each visible component of a record extension has to have a unique name, whether the component is (visibly) inherited from the parent type or declared in the record_extension_part, see section Visibility. Examples
  10. Examples of record extensions (of types defined above in section Tagged Types and Type Extensions.):
  11. type Painted_Point is new Point with
      record
        Paint : Color := White;
      end record;
        -- Components X and Y are inherited
    
  12. Origin : constant Painted_Point := (X | Y => 0.0, Paint => Black);
    
  13. type Literal is new Expression with
      record                 -- a leaf in an Expression tree
        Value : Real;
      end record;
    
  14. type Expr_Ptr is access all Expression'Class;
    --  see section Access Types
    
  15. type Binary_Operation is new Expression with
      record       -- an internal node in an Expression tree
        Left, Right : Expr_Ptr;
      end record;
    
  16. type Addition is new Binary_Operation with null record;
    type Subtraction is new Binary_Operation with null record;
    -- No additional components needed for these extensions
    
  17. Tree : Expr_Ptr :=  -- A tree representation of ``5.0 + (13.0-7.0)''
       new Addition'(
          Left  => new Literal'(Value => 5.0),
          Right => new Subtraction'(
             Left  => new Literal'(Value => 13.0),
             Right => new Literal'(Value => 7.0)));
    

Dispatching Operations of Tagged Types

  1. The primitive subprograms of a tagged type are called dispatching operations. A dispatching operation can be called using a statically determined controlling tag, in which case the body to be executed is determined at compile time. Alternatively, the controlling tag can be dynamically determined, in which case the call dispatches to a body that is determined at run time; such a call is termed a dispatching call. As explained below, the properties of the operands and the context of a particular call on a dispatching operation determine how the controlling tag is determined, and hence whether or not the call is a dispatching call. Run-time polymorphism is achieved when a dispatching operation is called by a dispatching call. Static Semantics
  2. A call on a dispatching operation is a call whose name or prefix denotes the declaration of a primitive subprogram of a tagged type, that is, a dispatching operation. A controlling operand in a call on a dispatching operation of a tagged type T is one whose corresponding formal parameter is of type T or is of an anonymous access type with designated type T; the corresponding formal parameter is called a controlling formal parameter. If the controlling formal parameter is an access parameter, the controlling operand is the object designated by the actual parameter, rather than the actual parameter itself. If the call is to a (primitive) function with result type T, then the call has a controlling result -- the context of the call can control the dispatching.
  3. A name or expression of a tagged type is either statically tagged, dynamically tagged, or tag indeterminate, according to whether, when used as a controlling operand, the tag that controls dispatching is determined statically by the operand's (specific) type, dynamically by its tag at run time, or from context. A qualified_expression or parenthesized expression is statically, dynamically, or indeterminately tagged according to its operand. For other kinds of names and expressions, this is determined as follows:
    1. The name or expression is statically tagged if it is of a specific tagged type and, if it is a call with a controlling result, it has at least one statically tagged controlling operand;
    2. The name or expression is dynamically tagged if it is of a class-wide type, or it is a call with a controlling result and at least one dynamically tagged controlling operand;
    3. The name or expression is tag indeterminate if it is a call with a controlling result, all of whose controlling operands (if any) are tag indeterminate.
  1. A type_conversion is statically or dynamically tagged according to whether the type determined by the subtype_mark is specific or class-wide, respectively. For a controlling operand that is designated by an actual parameter, the controlling operand is statically or dynamically tagged according to whether the designated type of the actual parameter is specific or class-wide, respectively. Legality Rules
  2. A call on a dispatching operation shall not have both dynamically tagged and statically tagged controlling operands.
  3. If the expected type for an expression or name is some specific tagged type, then the expression or name shall not be dynamically tagged unless it is a controlling operand in a call on a dispatching operation. Similarly, if the expected type for an expression is an anonymous access-to-specific tagged type, then the expression shall not be of an access-to-class-wide type unless it designates a controlling operand in a call on a dispatching operation.
  4. In the declaration of a dispatching operation of a tagged type, everywhere a subtype of the tagged type appears as a subtype of the profile, see section Subprogram Declarations, it shall statically match the first subtype of the tagged type. If the dispatching operation overrides an inherited subprogram, it shall be subtype conformant with the inherited subprogram. A dispatching operation shall not be of convention Intrinsic. If a dispatching operation overrides the predefined equals operator, then it shall be of convention Ada (either explicitly or by default -- see section Conformance Rules.).
  5. The default_expression for a controlling formal parameter of a dispatching operation shall be tag indeterminate. A controlling formal parameter that is an access parameter shall not have a default_expression.
  6. A given subprogram shall not be a dispatching operation of two or more distinct tagged types.
  7. The explicit declaration of a primitive subprogram of a tagged type shall occur before the type is frozen, see section Freezing Rules. For example, new dispatching operations cannot be added after objects or values of the type exist, nor after deriving a record extension from it, nor after a body. Dynamic Semantics
  8. For the execution of a call on a dispatching operation of a type T, the controlling tag value determines which subprogram body is executed. The controlling tag value is defined as follows:
    1. If one or more controlling operands are statically tagged, then the controlling tag value is statically determined to be the tag of T.
    2. If one or more controlling operands are dynamically tagged, then the controlling tag value is not statically determined, but is rather determined by the tags of the controlling operands. If there is more than one dynamically tagged controlling operand, a check is made that they all have the same tag. If this check fails, Constraint_Error is raised unless the call is a function_call whose name denotes the declaration of an equality operator (predefined or user defined) that returns Boolean, in which case the result of the call is defined to indicate inequality, and no subprogram_body is executed. This check is performed prior to evaluating any tag-indeterminate controlling operands.
    3. If all of the controlling operands are tag-indeterminate, then:
      1. If the call has a controlling result and is itself a (possibly parenthesized or qualified) controlling operand of an enclosing call on a dispatching operation of type T, then its controlling tag value is determined by the controlling tag value of this enclosing call;
      2. Otherwise, the controlling tag value is statically determined to be the tag of type T.
  1. For the execution of a call on a dispatching operation, the body executed is the one for the corresponding primitive subprogram of the specific type identified by the controlling tag value. The body for an explicitly declared dispatching operation is the corresponding explicit body for the subprogram. The body for an implicitly declared dispatching operation that is overridden is the body for the overriding subprogram, even if the overriding occurs in a private part. The body for an inherited dispatching operation that is not overridden is the body of the corresponding subprogram of the parent or ancestor type. NOTES
  2. (70) The body to be executed for a call on a dispatching operation is determined by the tag; it does not matter whether that tag is determined statically or dynamically, and it does not matter whether the subprogram's declaration is visible at the place of the call.
  3. (71) This subclause covers calls on primitive subprograms of a tagged type. Rules for tagged type membership tests are described in 4.5.2. Controlling tag determination for an assignment_statement is described in section Assignment Statements.
  4. (72) A dispatching call can dispatch to a body whose declaration is not visible at the place of the call.
  5. (73) A call through an access-to-subprogram value is never a dispatching call, even if the access value designates a dispatching operation. Similarly a call whose prefix denotes a subprogram_renaming_declaration cannot be a dispatching call unless the renaming itself is the declaration of a primitive subprogram.

Abstract Types and Subprograms

  1. An abstract type is a tagged type intended for use as a parent type for type extensions, but which is not allowed to have objects of its own. An abstract subprogram is a subprogram that has no body, but is intended to be overridden at some point when inherited. Because objects of an abstract type cannot be created, a dispatching call to an abstract subprogram always dispatches to some overriding body. Legality Rules
  2. An abstract type is a specific type that has the reserved word abstract in its declaration. Only a tagged type is allowed to be declared abstract.
  3. A subprogram declared by an abstract_subprogram_declaration, see section Subprogram Declarations, is an abstract subprogram. If it is a primitive subprogram of a tagged type, then the tagged type shall be abstract.
  4. For a derived type, if the parent or ancestor type has an abstract primitive subprogram, or a primitive function with a controlling result, then:
    1. If the derived type is abstract or untagged, the inherited subprogram is abstract.
    2. Otherwise, the subprogram shall be overridden with a nonabstract subprogram; for a type declared in the visible part of a package, the overriding may be either in the visible or the private part. However, if the type is a generic formal type, the subprogram need not be overridden for the formal type itself; a nonabstract version will necessarily be provided by the actual type.
  1. A call on an abstract subprogram shall be a dispatching call; nondispatching calls to an abstract subprogram are not allowed.
  2. The type of an aggregate, or of an object created by an object_declaration or an allocator, or a generic formal object of mode in, shall not be abstract. The type of the target of an assignment operation, see section Assignment Statements, shall not be abstract. The type of a component shall not be abstract. If the result type of a function is abstract, then the function shall be abstract.
  3. If a partial view is not abstract, the corresponding full view shall not be abstract. If a generic formal type is abstract, then for each primitive subprogram of the formal that is not abstract, the corresponding primitive subprogram of the actual shall not be abstract.
  4. For an abstract type declared in a visible part, an abstract primitive subprogram shall not be declared in the private part, unless it is overriding an abstract subprogram implicitly declared in the visible part. For a tagged type declared in a visible part, a primitive function with a controlling result shall not be declared in the private part, unless it is overriding a function implicitly declared in the visible part.
  5. A generic actual subprogram shall not be an abstract subprogram. The prefix of an attribute_reference for the Access, Unchecked_Access, or Address attributes shall not denote an abstract subprogram. NOTES
  6. (74) Abstractness is not inherited; to declare an abstract type, the reserved word abstract has to be used in the declaration of the type extension.
  7. (75) A class-wide type is never abstract. Even if a class is rooted at an abstract type, the class-wide type for the class is not abstract, and an object of the class-wide type can be created; the tag of such an object will identify some nonabstract type in the class. Examples
  8. Example of an abstract type representing a set of natural numbers:
  9. package Sets is
        subtype Element_Type is Natural;
        type Set is abstract tagged null record;
        function Empty return Set is abstract;
        function Union(Left, Right : Set) return Set is abstract;
        function Intersection(Left, Right : Set) return Set is abstract;
        function Unit_Set(Element : Element_Type) return Set is abstract;
        procedure Take
          (Element : out Element_Type;
           From : in out Set) is abstract;
    end Sets;
    
    NOTES
  10. (76) Notes on the example: Given the above abstract type, one could then derive various (nonabstract) extensions of the type, representing alternative implementations of a set. One might use a bit vector, but impose an upper bound on the largest element representable, while another might use a hash table, trading off space for flexibility.

Access Types

  1. A value of an access type (an access value) provides indirect access to the object or subprogram it designates. Depending on its type, an access value can designate either subprograms, objects created by allocators, See section Allocators, or more generally aliased objects of an appropriate type. Syntax
  2. access_type_definition ::=
         access_to_object_definition
       | access_to_subprogram_definition
    
  3. access_to_object_definition ::=
        access [general_access_modifier] subtype_indication
    
  4. general_access_modifier ::= all | constant
    
  5. access_to_subprogram_definition ::=
         access [protected] procedure parameter_profile
       | access [protected] function  parameter_and_result_profile
    
  6. access_definition ::= access subtype_mark
    
    Static Semantics
  7. There are two kinds of access types, access-to-object types, whose values designate objects, and access-to-subprogram types, whose values designate subprograms. Associated with an access-to-object type is a storage pool; several access types may share the same storage pool. A storage pool is an area of storage used to hold dynamically allocated objects (called pool elements) created by allocators; storage pools are described further in section Storage Management.
  8. Access-to-object types are further subdivided into pool-specific access types, whose values can designate only the elements of their associated storage pool, and general access types, whose values can designate the elements of any storage pool, as well as aliased objects created by declarations rather than allocators, and aliased subcomponents of other objects.
  9. A view of an object is defined to be aliased if it is defined by an object_declaration or component_definition with the reserved word aliased, or by a renaming of an aliased view. In addition, the dereference of an access-to-object value denotes an aliased view, as does a view conversion, see section Type Conversions of an aliased view. Finally, the current instance of a limited type, and a formal parameter or generic formal object of a tagged type are defined to be aliased. Aliased views are the ones that can be designated by an access value. If the view defined by an object_declaration is aliased, and the type of the object has discriminants, then the object is constrained; if its nominal subtype is unconstrained, then the object is constrained by its initial value. Similarly, if the object created by an allocator has discriminants, the object is constrained, either by the designated subtype, or by its initial value.
  10. An access_to_object_definition defines an access-to-object type and its first subtype; the subtype_indication defines the designated subtype of the access type. If a general_access_modifier appears, then the access type is a general access type. If the modifier is the reserved word constant, then the type is an access-to-constant type; a designated object cannot be updated through a value of such a type. If the modifier is the reserved word all, then the type is an access-to-variable type; a designated object can be both read and updated through a value of such a type. If no general_access_modifier appears in the access_to_object_definition, the access type is a pool-specific access-to-variable type.
  11. An access_to_subprogram_definition defines an access-to-subprogram type and its first subtype; the parameter_profile or parameter_and_result_profile defines the designated profile of the access type. There is a calling convention associated with the designated profile; only subprograms with this calling convention can be designated by values of the access type. By default, the calling convention is "protected" if the reserved word protected appears, and "Ada" otherwise. See Annex section Interface to Other Languages (normative) for how to override this default.
  12. An access_definition defines an anonymous general access-to-variable type; the subtype_mark denotes its designated subtype. An access_definition is used in the specification of an access discriminant, see section Discriminants, or an access parameter, see section Subprogram Declarations.
  13. For each (named) access type, there is a literal null which has a null access value designating no entity at all. The null value of a named access type is the default initial value of the type. Other values of an access type are obtained by evaluating an attribute_reference for the Access or Unchecked_Access attribute of an aliased view of an object or non-intrinsic subprogram, or, in the case of a named access-to-object type, an allocator, which returns an access value designating a newly created object, see section Operations of Access Types.
  14. All subtypes of an access-to-subprogram type are constrained. The first subtype of a type defined by an access_type_definition or an access_to_object_definition is unconstrained if the designated subtype is an unconstrained array or discriminated type; otherwise it is constrained. Dynamic Semantics
  15. A composite_constraint is compatible with an unconstrained access subtype if it is compatible with the designated subtype. An access value satisfies a composite_constraint of an access subtype if it equals the null value of its type or if it designates an object whose value satisfies the constraint.
  16. The elaboration of an access_type_definition creates the access type and its first subtype. For an access-to-object type, this elaboration includes the elaboration of the subtype_indication, which creates the designated subtype.
  17. The elaboration of an access_definition creates an anonymous general access-to-variable type (this happens as part of the initialization of an access parameter or access discriminant). NOTES
  18. (77) Access values are called "pointers" or "references" in some other languages.
  19. (78) Each access-to-object type has an associated storage pool; several access types can share the same pool. An object can be created in the storage pool of an access type by an allocator, see section Allocators, for the access type. A storage pool (roughly) corresponds to what some other languages call a "heap." See section Storage Management, for a discussion of pools.
  20. (79) Only index_constraints and discriminant_constraints can be applied to access types, see section Index Constraints and Discrete Ranges, and section Discriminant Constraints. Examples
  21. Examples of access-to-object types:
  22. type Peripheral_Ref is access Peripheral;  --  see section Variant Parts and Discrete Choices
    type Binop_Ptr is access all Binary_Operation'Class;
    -- general access-to-class-wide, see section Type Extensions
    
  23. Example of an access subtype:
  24. subtype Drum_Ref is Peripheral_Ref(Drum);  --  see section Variant Parts and Discrete Choices
    
  25. Example of an access-to-subprogram type:
  26. type Message_Procedure is access
      procedure (M : in String := "Error!");
    procedure Default_Message_Procedure(M : in String);
    Give_Message : Message_Procedure := Default_Message_Procedure'Access;
    ...
    procedure Other_Procedure(M : in String);
    ...
    Give_Message := Other_Procedure'Access;
    ...
    Give_Message("File not found.");
    -- call with parameter (.all is optional)
    Give_Message.all;
    -- call with no parameters
    

Incomplete Type Declarations

  1. There are no particular limitations on the designated type of an access type. In particular, the type of a component of the designated type can be another access type, or even the same access type. This permits mutually dependent and recursive access types. An incomplete_type_declaration can be used to introduce a type to be used as a designated type, while deferring its full definition to a subsequent full_type_declaration. Syntax
  2. incomplete_type_declaration ::=
       type defining_identifier [discriminant_part];
    
    Legality Rules
  3. An incomplete_type_declaration requires a completion, which shall be a full_type_declaration. If the incomplete_type_declaration occurs immediately within either the visible part of a package_specification or a declarative_part, then the full_type_declaration shall occur later and immediately within this visible part or declarative_part. If the incomplete_type_declaration occurs immediately within the private part of a given package_specification, then the full_type_declaration shall occur later and immediately within either the private part itself, or the declarative_part of the corresponding package_body.
  4. If an incomplete_type_declaration has a known_discriminant_part, then a full_type_declaration that completes it shall have a fully conforming (explicit) known_discriminant_part, see section Conformance Rules. If an incomplete_type_declaration has no discriminant_part (or an unknown_discriminant_part), then a corresponding full_type_declaration is nevertheless allowed to have discriminants, either explicitly, or inherited via derivation.
  5. The only allowed uses of a name that denotes an incomplete_type_declaration are as follows:
    1. as the subtype_mark in the subtype_indication of an access_to_object_definition; the only form of constraint allowed in this subtype_indication is a discriminant_constraint;
    2. as the subtype_mark defining the subtype of a parameter or result of an access_to_subprogram_definition;
    3. as the subtype_mark in an access_definition;
    4. as the prefix of an attribute_reference whose attribute_designator is Class; such an attribute_reference is similarly restricted to the uses allowed here; when used in this way, the corresponding full_type_declaration shall declare a tagged type, and the attribute_reference shall occur in the same library unit as the incomplete_type_declaration.
  1. A dereference (whether implicit or explicit -- see section Names.) shall not be of an incomplete type. Static Semantics
  2. An incomplete_type_declaration declares an incomplete type and its first subtype; the first subtype is unconstrained if a known_discriminant_part appears. Dynamic Semantics
  3. The elaboration of an incomplete_type_declaration has no effect. NOTES
  4. (80) Within a declarative_part, an incomplete_type_declaration and a corresponding full_type_declaration cannot be separated by an intervening body. This is because a type has to be completely defined before it is frozen, and a body freezes all types declared prior to it in the same declarative_part, see section Freezing Rules. Examples
  5. Example of a recursive type:
  6. type Cell;  --  incomplete type declaration
    type Link is access Cell;
    
  7. type Cell is
       record
          Value  : Integer;
          Succ   : Link;
          Pred   : Link;
       end record;
    
  8. Head   : Link  := new Cell'(0, null, null);
    Next   : Link  := Head.Succ;
    
  9. Examples of mutually dependent access types:
  10. type Person(<>);    -- incomplete type declaration
    type Car;           -- incomplete type declaration
    
  11. type Person_Name is access Person;
    type Car_Name    is access all Car;
    
  12. type Car is
       record
          Number  : Integer;
          Owner   : Person_Name;
       end record;
    
  13. type Person(Sex : Gender) is
       record
          Name     : String(1 .. 20);
          Birth    : Date;
          Age      : Integer range 0 .. 130;
          Vehicle  : Car_Name;
          case Sex is
             when M => Wife    : Person_Name(Sex => F);
             when F => Husband : Person_Name(Sex => M);
          end case;
       end record;
    
  14. My_Car, Your_Car, Next_Car : Car_Name := new Car;
    --  see section Allocators
    George : Person_Name := new Person(M);
       ...
    George.Vehicle := Your_Car;
    

Operations of Access Types

  1. The attribute Access is used to create access values designating aliased objects and non-intrinsic subprograms. The "accessibility" rules prevent dangling references (in the absence of uses of certain unchecked features -- see section Representation Issues.). Name Resolution Rules
  2. For an attribute_reference with attribute_designator Access (or Unchecked_Access -- see section Unchecked Access Value Creation.), the expected type shall be a single access type; the prefix of such an attribute_reference is never interpreted as an implicit_dereference. If the expected type is an access-to-subprogram type, then the expected profile of the prefix is the designated profile of the access type. Static Semantics
  3. The accessibility rules, which prevent dangling references, are written in terms of accessibility levels, which reflect the run-time nesting of masters. As explained in section Completion and Finalization, a master is the execution of a task_body, a block_statement, a subprogram_body, an entry_body, or an accept_statement. An accessibility level is deeper than another if it is more deeply nested at run time. For example, an object declared local to a called subprogram has a deeper accessibility level than an object declared local to the calling subprogram. The accessibility rules for access types require that the accessibility level of an object designated by an access value be no deeper than that of the access type. This ensures that the object will live at least as long as the access type, which in turn ensures that the access value cannot later designate an object that no longer exists. The Unchecked_Access attribute may be used to circumvent the accessibility rules.
  4. A given accessibility level is said to be statically deeper than another if the given level is known at compile time (as defined below) to be deeper than the other for all possible executions. In most cases, accessibility is enforced at compile time by Legality Rules. Run-time accessibility checks are also used, since the Legality Rules do not cover certain cases involving access parameters and generic packages.
  5. Each master, and each entity and view created by it, has an accessibility level:
    1. The accessibility level of a given master is deeper than that of each dynamically enclosing master, and deeper than that of each master upon which the task executing the given master directly depends, see section Task Dependence - Termination of Tasks.
    2. An entity or view created by a declaration has the same accessibility level as the innermost enclosing master, except in the cases of renaming and derived access types described below. A parameter of a master has the same accessibility level as the master.
    3. The accessibility level of a view of an object or subprogram defined by a renaming_declaration is the same as that of the renamed view.
    4. The accessibility level of a view conversion is the same as that of the operand.
    5. For a function whose result type is a return-by-reference type, the accessibility level of the result object is the same as that of the master that elaborated the function body. For any other function, the accessibility level of the result object is that of the execution of the called function.
    6. The accessibility level of a derived access type is the same as that of its ultimate ancestor.
    7. The accessibility level of the anonymous access type of an access discriminant is the same as that of the containing object or associated constrained subtype.
    8. The accessibility level of the anonymous access type of an access parameter is the same as that of the view designated by the actual. If the actual is an allocator, this is the accessibility level of the execution of the called subprogram.
    9. The accessibility level of an object created by an allocator is the same as that of the access type.
    10. The accessibility level of a view of an object or subprogram denoted by a dereference of an access value is the same as that of the access type.
    11. The accessibility level of a component, protected subprogram, or entry of (a view of) a composite object is the same as that of (the view of) the composite object.
  1. One accessibility level is defined to be statically deeper than another in the following cases:
    1. For a master that is statically nested within another master, the accessibility level of the inner master is statically deeper than that of the outer master.
    2. The statically deeper relationship does not apply to the accessibility level of the anonymous type of an access parameter; that is, such an accessibility level is not considered to be statically deeper, nor statically shallower, than any other.
    3. For determining whether one level is statically deeper than another when within a generic package body, the generic package is presumed to be instantiated at the same level as where it was declared; run-time checks are needed in the case of more deeply nested instantiations.
    4. For determining whether one level is statically deeper than another when within the declarative region of a type_declaration, the current instance of the type is presumed to be an object created at a deeper level than that of the type.
  1. The accessibility level of all library units is called the library level; a library-level declaration or entity is one whose accessibility level is the library level.
  2. The following attribute is defined for a prefix X that denotes an aliased view of an object:
  3. X'Access
    X'Access yields an access value that designates the object
    denoted by X. The type of X'Access is an access-to-object
    type, as determined by the expected type. The expected type
    shall be a general access type. X shall denote an aliased
    view of an object, including possibly the current instance,
    See section The Context of Overload Resolution, of a limited type within its definition, or a
    formal parameter or generic formal object of a tagged type.
    The view denoted by the prefix X shall satisfy the following
    additional requirements, presuming the expected type for
    X'Access is the general access type A:
    
      1. If A is an access-to-variable type, then the view shall be a variable; on the other hand, if A is an access-to-constant type, the view may be either a constant or a variable.
      2. The view shall not be a subcomponent that depends on discriminants of a variable whose nominal subtype is unconstrained, unless this subtype is indefinite, or the variable is aliased.
      3. If the designated type of A is tagged, then the type of the view shall be covered by the designated type; if A's designated type is not tagged, then the type of the view shall be the same, and either A's designated subtype shall statically match the nominal subtype of the view, or the designated subtype shall be discriminated and unconstrained;
      4. The accessibility level of the view shall not be statically deeper than that of the access type A. In addition to the places where Legality Rules normally apply, see section Generic Instantiation, this rule applies also in the private part of an instance of a generic unit.
    1. A check is made that the accessibility level of X is not deeper than that of the access type A. If this check fails, Program_Error is raised.
    2. If the nominal subtype of X does not statically match the designated subtype of A, a view conversion of X to the designated subtype is evaluated (which might raise Constraint_Error -- see section Type Conversions.) and the value of X'Access designates that view.
  1. The following attribute is defined for a prefix P that denotes a subprogram:
  2. P'Access
    P'Access yields an access value that designates the
    subprogram denoted by P. The type of P'Access is an
    access-to-subprogram type (S), as determined by the expected
    type. The accessibility level of P shall not be statically
    deeper than that of S. In addition to the places where
    Legality Rules normally apply, see section Generic Instantiation, this rule applies
    also in the private part of an instance of a generic unit.
    The profile of P shall be subtype-conformant with the
    designated profile of S, and shall not be Intrinsic. If
    the subprogram denoted by P is declared within a generic
    body, S shall be declared within the generic body.
    
    NOTES
  3. (81) The Unchecked_Access attribute yields the same result as the Access attribute for objects, but has fewer restrictions, see section Unchecked Access Value Creation. There are other predefined operations that yield access values: an allocator can be used to create an object, and return an access value that designates it, see section Allocators, evaluating the literal null yields a null access value that designates no entity at all, see section Literals.
  4. (82) The predefined operations of an access type also include the assignment operation, qualification, and membership tests. Explicit conversion is allowed between general access types with matching designated subtypes; explicit conversion is allowed between access-to-subprogram types with subtype conformant profiles, see section Type Conversions. Named access types have predefined equality operators; anonymous access types do not, see section Relational Operators and Membership Tests.
  5. (83) The object or subprogram designated by an access value can be named with a dereference, either an explicit_dereference or an implicit_dereference. See section Names.
  6. (84) A call through the dereference of an access-to-subprogram value is never a dispatching call.
  7. (85) The accessibility rules imply that it is not possible to use the Access attribute to implement "downward closures" -- that is, to pass a more-nested subprogram as a parameter to a less-nested subprogram, as might be desired for example for an iterator abstraction. Instead, downward closures can be implemented using generic formal subprograms, See section Formal Subprograms. Note that Unchecked_Access is not allowed for subprograms.
  8. (86) Note that using an access-to-class-wide tagged type with a dispatching operation is a potentially more structured alternative to using an access-to-subprogram type.
  9. (87) An implementation may consider two access-to-subprogram values to be unequal, even though they designate the same subprogram. This might be because one points directly to the subprogram, while the other points to a special prologue that performs an Elaboration_Check and then jumps to the subprogram. See section Relational Operators and Membership Tests. Examples
  10. Example of use of the Access attribute:
  11. Martha : Person_Name := new Person(F);  --  see section Incomplete Type Declarations
    Cars   : array (1..2) of aliased Car;
       ...
    Martha.Vehicle := Cars(1)'Access;
    George.Vehicle := Cars(2)'Access;
    

Declarative Parts

  1. A declarative_part contains declarative_items (possibly none). Syntax
  2. declarative_part ::= {declarative_item}
    
  3. declarative_item ::= basic_declarative_item | body
    
  4. basic_declarative_item ::=
       basic_declaration | representation_clause | use_clause
    
  5. body ::= proper_body | body_stub
    
  6. proper_body ::=
       subprogram_body | package_body | task_body | protected_body
    
    Dynamic Semantics
  7. The elaboration of a declarative_part consists of the elaboration of the declarative_items, if any, in the order in which they are given in the declarative_part.
  8. An elaborable construct is in the elaborated state after the normal completion of its elaboration. Prior to that, it is not yet elaborated.
  9. For a construct that attempts to use a body, a check (Elaboration_Check) is performed, as follows:
    1. For a call to a (non-protected) subprogram that has an explicit body, a check is made that the subprogram_body is already elaborated. This check and the evaluations of any actual parameters of the call are done in an arbitrary order.
    2. For a call to a protected operation of a protected type (that has a body -- no check is performed if a pragma Import applies to the protected type), a check is made that the protected_body is already elaborated. This check and the evaluations of any actual parameters of the call are done in an arbitrary order.
    3. For the activation of a task, a check is made by the activator that the task_body is already elaborated. If two or more tasks are being activated together, see section Task Execution - Task Activation, as the result of the elaboration of a declarative_part or the initialization for the object created by an allocator, this check is done for all of them before activating any of them.
    4. For the instantiation of a generic unit that has a body, a check is made that this body is already elaborated. This check and the evaluation of any explicit_generic_actual_parameters of the instantiation are done in an arbitrary order.
  1. The exception Program_Error is raised if any of these checks fails.

Completions of Declarations

  1. Declarations sometimes come in two parts. A declaration that requires a second part is said to require completion. The second part is called the completion of the declaration (and of the entity declared), and is either another declaration, a body, or a pragma. Name Resolution Rules
  2. A construct that can be a completion is interpreted as the completion of a prior declaration only if:
    1. The declaration and the completion occur immediately within the same declarative region;
    2. The defining name or defining_program_unit_name in the completion is the same as in the declaration, or in the case of a pragma, the pragma applies to the declaration;
    3. If the declaration is overloadable, then the completion either has a type-conformant profile, or is a pragma.

Legality Rules

  1. An implicit declaration shall not have a completion. For any explicit declaration that is specified to require completion, there shall be a corresponding explicit completion.
  2. At most one completion is allowed for a given declaration. Additional requirements on completions appear where each kind of completion is defined.
  3. A type is completely defined at a place that is after its full type definition (if it has one) and after all of its subcomponent types are completely defined. A type shall be completely defined before it is frozen, see section Freezing Rules, and section Private Types and Private Extensions. NOTES
  4. (88) Completions are in principle allowed for any kind of explicit declaration. However, for some kinds of declaration, the only allowed completion is a pragma Import, and implementations are not required to support pragma Import for every kind of entity.
  5. (89) There are rules that prevent premature uses of declarations that have a corresponding completion. The Elaboration_Checks of See section Declarative Parts, prevent such uses at run time for subprograms, protected operations, tasks, and generic units. The rules of See section Freezing Rules, "Freezing Rules" prevent, at compile time, premature uses of other entities such as private types and deferred constants.


Go to the first, previous, next, last section, table of contents.