Version 1.10 of ais/ai-00171.txt
!standard 03.08 (18) 00-07-13 AI95-00171/09
!standard 03.03.01 (18)
!standard 03.06 (22)
!standard 04.03.01 (19)
!standard 04.08 (10)
!standard 09.04 (14)
!standard 09.05.02 (22)
!class binding interpretation 98-03-19
!status Corrigendum 2000 99-08-17
!status WG9 approved 98-06-12
!status ARG Approved 11-0-1 98-04-01
!status received 96-11-16
!priority Low
!difficulty Hard
!qualifier Omission
!subject Elaboration of subtype_indications with per-object constraints
!summary
The elaboration of a subtype indication with a per-object constraint
occurs when an object of the enclosing type is created. This elaboration
consists of the evaluation of each per-object expression of the constraint,
followed by the usual actions associated with such elaboration, but using
the values for any expressions that are not part of a per-object expression
that were determined earlier when the type definition was elaborated.
For evaluating a named association applying to multiple components in a
per-object discriminant constraint, if the expression of the association
is not part of a per-object expression, then it must be evaluated once
for each associated component.
!question
When does the elaboration of a subtype indication with a per-object
constraint occur? What are the actions of such an elaboration?
When a component has a subtype_indication with a per-object constraint
and an object of the type containing the component is declared, the
subtype_indication containing the per-object constraint is apparently
never elaborated.
3.8(18) explains that subtype_indications with per-object constraints
are not elaborated, but that any expressions that are not part of a
per-object expression are evaluated. However, what to do with the
results of those evaluations never seems to be explained.
3.3.1(15-20) describes the process of elaborating an object_declaration.
In step 3, per-object expressions are evaluated, but there is no mention
of elaborating anything, although later paragraph 20 does seem to imply
that some sort of elaborations were supposed to have taken place in step 3.
The elaboration of per-object constraints is mentioned in (at least)
the following other places where objects are created:
4.3.1(19) creating record aggregates
4.8(10) creating heap objects via uninitialized allocators
9.4(14) creating a protected object (This one is supposed to be redundant
with 3.3.1, but in fact the two appear to be inconsistent.)
According to a strict reading, elaborating the per-object constraint would
appear to involve reevaluating the non-per-object expressions (since there
doesn't seem to be any separate definition of what happens when a per-object
constraint is elaborated), but not include any subtype compatibility checks
that would normally occur as part of subtype elaboration (since elaboration
of the subtype_indication containing the constraint isn't mentioned in these
paragraphs). What are the intended semantics?
!recommendation 98-03-19
Notwithstanding the rules given in 3.3.1(18), 4.3.1(19), and 4.8(10),
the elaboration of the subtype indication of a component definition with
a per-object constraint occurs when an object of the enclosing type is
created. This elaboration takes place on elaboration of an object
declaration, evaluation of an uninitialized allocator, and when
evaluating an aggregate of the type.
The elaboration consists of the evaluation of each per-object expression
of the component's constraint, followed by the conversion of the value
of each expression of the constraint to its appropriate expected type
and the performance of the compatibility check defined for the elaboration
of the subtype indication (see 3.2.2(11)). The values used for any
expressions that are not part of per-object expressions of the subtype's
constraint are those determined during the original elaboration of the
component definition as defined in 3.8(18). Such expressions are not
reevaluated during elaboration of the per-object constraint that occurs
as part of object creation, despite any rules that state when a
per-object constraint is elaborated (e.g., as part of evaluating an
allocator or aggregate).
Note further that the evaluation of expressions in a per-object constraint
defined in 3.8(18) was intended to take into account the case of named
associations for multiple components in a discriminant constraint. For
such an association, the expression must be evaluated once for each
associated component, as prescribed by 3.7.1(12).
!wording
Changes are required in 3.3.1(18), 4.3.1(19), 4.8(10), and 9.4(14)
to state that any subtype indications for components with a per-object
constraint are elaborated. The specific actions of elaborating such
subtype indications and their associated constraints, as described in the
recommendation, should be defined (perhaps in 3.8(18)). Also, 3.8(18)
needs to account for multiple evaluations of non-per-object expressions
in the case of named associations in a per-object discriminant constraint.
!discussion
There are two basic problems with the current wording of the standard regarding
the elaboration of components with a per-object constraint. The
first is that the rules don't explain what is done with the values
obtained from expressions that are not part of per-object expressions
(as defined in 3.8(18)) or whether such expression are reevaluated when
a per-object constraint is later elaborated during object creation.
The other problem is that the mention of elaboration of per-object
constraints in rules such as 4.3.1(19) and 4.8(10) fails to cover
the need for the subtype compatibility check that is normally performed
when elaborating a subtype indication.
The intent was clearly that the values of the expressions evaluated as
part of elaborating a component definition with a per-object constraint
(3.8(18)) should be used later when creating an object of the containing
type. It would not make sense to discard the values already determined
and to reevaluate the expressions (especially if they have side effects).
The description in the rules for allocator and aggregate evaluation
that states that a per-object constraint is elaborated should mention
that only the per-object expressions are evaluated at that point and
that the values for other expressions are those determined earlier
when the type was elaborated. (The description of the semantics
of elaborating per-object constraints should really be centralized
in a single place, such as 3.8(18).)
The rules for object declarations, allocator evaluation, and aggregate
evaluation all fail to require the subtype compatibility check that
occurs when a subtype indication is elaborated (and for object declarations
even the constraint elaboration is omitted). This check is certainly
needed in these cases as well. The fix for this oversight is to define
each of these rules to include the elaboration of the subtype indications
for components with per-object constraints (which also subsumes the
elaboration of the constraint itself).
One other minor gap is that the case of elaborating a named discriminant
association within a per-object constraint is not covered by that rule
in 3.8(18). The rule as given only describes a single evaluation for
each expression of the constraint, but the intent is that for a named
association the expression should be evaluated for each associated
component.
!corrigendum 3.03.01(18)
Replace the paragraph:
- 3.
- The object is created, and, if there is not an initialization
expression, any per-object expressions (see 3.8) are evaluated
and any implicit initial values for the object or for its
subcomponents are obtained as determined by the nominal subtype.
by:
- 3.
- The object is created, and, if there is not an initialization
expression, any per-object constraints (see 3.8) are elaborated
and any implicit initial values for the object or for its
subcomponents are obtained as determined by the nominal subtype.
!corrigendum 3.06(22)
Replace the paragraph:
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.
by:
The elaboration of a discrete_subtype_definition that does not contain
any per-object expressions creates the discrete
subtype, and consists of the elaboration of the subtype_indication or the
evaluation of the range. The elaboration of a
discrete_subtype_definition that contains one or more per-object
expressions is defined in 3.8. 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.
!corrigendum 3.08(18)
Replace the paragraph:
Within the definition of a composite type, if a component_definition or
discrete_subtype_definition (see 9.5.2) 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.
by:
Within the definition of a composite type, if a component_definition or
discrete_subtype_definition (see 9.5.2) 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 or
range being defined is called a per-object constraint. For the
elaboration of a component_definition of a component_declaration or
the discrete_subtype_definition of an entry_declaration for an entry
family (see 9.5.2), if the constraint or range of the
subtype_indication or discrete_subtype_definition is not a per-object
constraint, then the subtype_indication or discrete_subtype_definition
is elaborated. On the other hand, if the constraint or range 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. Each such
expression is evaluated once unless it is part of a named association in a
discriminant constraint, in which case it is evaluated once for each associated
discriminant.
When a per-object constraint is elaborated (as part of creating an object),
each per-object expression of the constraint is evaluated.
For other expressions, the values determined during the elaboration of the
component_definition or entry_declaration are used. Any checks
associated with the enclosing subtype_indication or
discrete_subtype_definition are performed, including the subtype
compatibility check (see 3.2.2), and the associated subtype is created.
!corrigendum 4.08(10)
Replace the paragraph:
- If the designated type is composite, an object of the designated
type is created with tag, if any, determined by the subtype_mark
of the subtype_indication; any per-object constraints on
subcomponents are elaborated and any implicit initial values for
the subcomponents of the object are obtained as determined by the
subtype_indication and assigned to the corresponding subcomponents.
A check is made that the value of the object belongs to the designated
subtype. Constraint_Error is raised if this check fails. This check and the
initialization of the object are performed in an arbitrary order.
by:
- If the designated type is composite, an object of the designated
type is created with tag, if any, determined by the subtype_mark
of the subtype_indication; any per-object constraints on
subcomponents are elaborated (see 3.8) and any implicit initial values for
the subcomponents of the object are obtained as determined by the
subtype_indication and assigned to the corresponding subcomponents.
A check is made that the value of the object belongs to the designated
subtype. Constraint_Error is raised if this check fails. This check and the
initialization of the object are performed in an arbitrary order.
!corrigendum 9.05.02(22)
Replace the paragraph:
For the elaboration of an entry_declaration for an entry family, if the
discrete_subtype_definition contains no per-object expressions (see 3.8),
then the discrete_subtype_definition is elaborated. Otherwise, the
elaboration of the entry_declaration consists of the evaluation of any
expression of the discrete_subtype_definition that is not a per-object
expression (or part of one). The elaboration of an entry_declaration for a
single entry has no effect.
by:
The elaboration of an entry_declaration for an entry family consists of
the elaboration of the discrete_subtype_definition, as described in 3.8.
The elaboration of an entry_declaration for a single entry has no effect.
!ACATS test
An extensive set of tests check cases where a constraint contains an enclosing
discriminant in component_definitions (C37213x and C37215x).
C-Tests should be constructed to check that these rules are enforced on
per-object constraints in task and protected specifications, and that the
checks are made when the per-object expression contains a attribute whose
prefix denotes the current instance of the type.
!appendix
!section 3.8(18)
!subject Elaboration of subtype_indications with per-object constraints
!reference RM95-3.8(18)
!from Vince Del Vecchio 96-10-30
!reference 1996-5737.a Vince Del Vecchio 1996-10-30>>
!discussion
When a component has a subtype_indication with a per-object constraint
and an object of the type containing the component is declared, the
subtype_indication containing the per-object constraint is apparently
never elaborated.
3.8(18) explains that subtype_indications with per-object constraints
are not elaborated, but that any included expressions are evaluated.
What to do with the results of those evaluations never seems to be
explained.
3.3.1(15-20) describes the process of elaborating an object_declaration.
In step 3, per-object expressions are evaluated, but there is no
mention of elaborating anything, although later paragraph 20
does seem to imply that some sort of elaborations were supposed to
have taken place in step 3.
What should really happen is a partial elaboration of the
subtype_indication should be performed, omitting pretty much any
evaluation, and using instead the already evaluated results (either
from 3.8(18) or from the per-object evaluations just performed).
However important part of the elaboration which do need to happen
include various checks (one due to a conversion in 3.7.1(12), then
the compatibility check of 3.2.2(11)), and actually creating the
subtype.
This is described somewhat in the AARM note 3.3.1(18.a), although that
is not binding.
The elaboration of per-object constraints is mentioned in (at least)
the following other places where objects are created:
4.3.1(19) creating record aggregates
4.8(10) creating heap objects via uninitialized allocators
9.4(14) creating a protected object
(This one is supposed to be redundant with, but in fact
appears to be inconsistent with 3.3.1.)
Strictly read, elaborating the per-object constraint would involve
reevaluating the non-per-object expressions (since there doesn't seem to
be any special definition of what happens when a per-object constraint
is elaborated), and not performing compatibility checks (since
elaboration of the subtype_indication containing the constraint doesn't
seem to be mentioned in these places). What is wanted is the same as in
3.8(18), to finish the elaboration of the subtype_indication containing
the constraint.
-Vince Del Vecchio
vdelvecc@inmet.com
****************************************************************
!from Randy Brukardt 99-08-17
Per-object constraints are mentioned in 3.8(18), 3.3.1(18), 4.3.1(19), 4.8(10),
9.1(12), 9.4(14), 9.5.2(22), 7.6(12), 7.6.1(9), and 13.14(8).
3.8(18 is the defining occurrence. The next six all deal with either the
evaluation or elaboration of per-object constraints. The other three deal with
other issues (Initialize calls, Finalize calls, and freezing, respectively)
and do not need changes.
All of 4.3.1(19), 4.8(10), 9.1(12), and 9.4(14) talk in terms of elaborating
the per-object constraint. If that was properly defined, no changes are
required in any of these clauses.
The primary problem here is with 3.3.1(18), which does not speak in terms of
elaborating the per-object constraint (meaning that needed checks aren't done).
This paragraph was changed to use that terminology.
The secondary problem is no definition of the elaboration of a per-object
constraint. This was added to 3.8(18). It also was changed to
insure that evaluation was done multiple times, if needed.
As part of the repairs, I moved the discussion of per-object constraints for
entries from 9.5.2(22) to 3.8(18), in order to insure that the same semantics
is given to both. Since this case has to be mentioned (both when defining
per-object constraint, and when defining elaboration of a per-object constraint)
leaving it in 9.5.2(22) simply means the same words have to be given a second
time. (Which increases the errors).
I noticed another problem: a discrete_subtype_definition can be a range, which
is *not* a constraint. Therefore, I added "range" to the definition of
per-object constraint (or we'd just have a new hole for the next round to
patch up).
I think that the last phrase of 3.8(18A) ("including the subtype compabilitity
check (see 3.2.2).") is redundant, but the AI recommendation seems insistent
that it be included. I'd be happy to do without it.
****************************************************************
!from Randy Brukardt 99-10-06
My notes from the recent ARG meeting say that the end of the first paragraph
should be changed from:
... then the elaboration consists of the evaluation of any
included expression that is not part of a per-object expression. Each such
expression is evaluated once unless it is part of a named association in a
discriminant constraint, in which case it is evaluated once for each associated
discriminant.
to:
... then the elaboration consists of the evaluation of any
included expression that is not part of a per-object expression, according to
the rules given in 3.7.1.
I did not make this change, because the rules in 3.7.1 are wrong for this use,
unfortunately. During the meeting, I checked the behavior of existing ACATS
tests [C37213B.ADA, C37213D.ADA, and others (the tests in fact are Ada 83 tests)],
and they require that the values be evaluated but not be checked at this point.
Given that the test suite requires this behavior, and has for many years, all
compilers delay the checks, and a change would be gratuitous. However, the rules
in 3.7.1 specifically say that each value is evaluated and converted when a
discriminant is evaluated. So a reference to 3.7.1 would cause incorrect behavior.
****************************************************************
Questions? Ask the ACAA Technical Agent