Version 1.5 of ais/ai-00108.txt
!standard 13.13.02 (09) 00-03-07 AI95-00108/05
!standard 13.13.02 (27)
!standard 13.13.02 (36)
!class binding interpretation 96-04-04
!status Corrigendum 2000 99-06-02
!status WG9 approved 96-12-07
!status ARG approved 7-0-2 96-06-17
!status work item 96-04-13
!status received 96-04-04
!priority High
!difficulty Hard
!qualifier Error
!subject Inheritance of Stream Attributes for Type Extensions
!summary
For a type extension, the predefined Read attribute is defined to call
the Read of the parent type, followed by the Read of the non-inherited
components, if any, in canonical order. The analogous rule applies to
the Write attribute.
The Input and Output attributes are not inherited by a type extension.
The stream attributes must work properly for every language defined
nonlimited type. For language defined private types, the output
generated by the Write attribute is not specified, but it must be
readable by the Read attribute.
!question
13.1(15) says:
15 A derived type inherits each type-related aspect of its parent type that
was directly specified before the declaration of the derived type, or (in the
case where the parent is derived) that was inherited by the parent type from
the grandparent type. A derived subtype inherits each subtype-specific
aspect of its parent subtype that was directly specified before the
declaration of the derived type, or (in the case where the parent is derived)
that was inherited by the parent subtype from the grandparent subtype, but
only if the parent subtype statically matches the first subtype of the parent
type. An inherited aspect of representation is overridden by a subsequent
representation item that specifies the same aspect of the type or subtype.
Do these rules apply to the stream-oriented attributes Read, Write,
Input, and Output? (No.)
Are the stream-oriented attributes intended to work properly for
language defined types such as Unbounded_String? (Yes.)
!recommendation
(See summary.)
!wording
(See corrigendum.)
!discussion
The general rule for inheritance of type-related representation aspects
should not apply to the stream attributes of type extensions. For 'Read
and 'Write, a rule analogous to the rule for tagged equality makes the
most sense. For 'Input and 'Output, no inheritance makes sense;
instead, they should regain their predefined meaning in terms of 'Read
and 'Write.
There are several problems associated with applying the normal 13.1(15)
inheritance rules to the stream attributes of tagged types:
1) Inheriting a 'Read or 'Write of the parent type as-is for
the 'Read or 'Write of a type extension will ignore any new
components added in the extension part. A rule analogous
to the one for the equality operator makes more sense.
In particular, the default 'Read or 'Write for a type extension
should be defined to do the 'Read or 'Write of the parent type
followed by the 'Read or 'Write for each component of the
type extension, in canonical order.
2) Inheriting a 'Input or 'Output of the parent type as-is for
'Input or 'Output of a type extension makes no sense, since
the inherited 'Input is a function returning the parent type,
and the inherited 'Output puts out the discriminants of the
parent type. For these two, the only meaningful approach seems
to be for the default 'Input and 'Output for a tagged type to
always be defined in terms of the 'Read and 'Write for the
tagged type, preceded with the discriminants, if any.
For untagged derived types, there is no problem for the derived
type inheriting the stream attributes. Even for tagged derived
types, if the extension part is null, the 'Read and 'Write will
effectively be inherited.
For language defined nonlimited private types, the RM does not say
whether the stream-oriented attributes must work properly. It seems
that they ought to. For many such types, the default version will work
properly. However, for a type like Unbounded_String, which is almost
certainly implemented as a data structure involving pointers, the
default versions will not work. Therefore, for these types, the
implementer must provide an explicit version of the Read and Write
attributes.
!corrigendum 13.1(15)
Replace the paragraph:
A derived type inherits each type-related aspect of its parent type that
was directly specified before the declaration of the derived type, or (in the
case where the parent is derived) that was inherited by the parent type from
the grandparent type. A derived subtype inherits each subtype-specific
aspect of its parent subtype that was directly specified before the
declaration of the derived type, or (in the case where the parent is derived)
that was inherited by the parent subtype from the grandparent subtype, but
only if the parent subtype statically matches the first subtype of the parent
type. An inherited aspect of representation is overridden by a subsequent
representation item that specifies the same aspect of the type or subtype.
by:
A derived type inherits each type-related aspect of representation of its
parent type that was directly specified before the declaration of the derived
type, or (in the case where the parent is derived) that was inherited by the
parent type from the grandparent type. A derived subtype inherits each
subtype-specific aspect of representation of its parent subtype that was
directly specified before the declaration of the derived type, or (in the case
where the parent is derived) that was inherited by the parent subtype from the
grandparent subtype, but only if the parent subtype statically matches the
first subtype of the parent type. An inherited aspect of representation is
overridden by a subsequent representation item that specifies the same aspect
of the type or subtype.
In contrast, operational aspects are not inherited for derived types; rather,
the predefined value of each aspect is used. A predefined operational aspect
can be overridden by a subsequent operational item that specifies the same
aspect of the type.
!corrigendum 13.13.02(9)
Replace the paragraph:
For elementary types, the representation in terms of stream elements is
implementation defined. For composite types, the Write or Read attribute for
each component is called in a canonical order. The canonical order of
components is last dimension varying fastest for an array, and positional
aggregate order for a record. Bounds are not included in the stream if T is
an array type. If T is a discriminated type, discriminants are included only
if they have defaults. If T is a tagged type, the tag is not included.
by:
For elementary types, the representation in terms of stream elements is
implementation defined. For composite types, the Write or Read attribute for
each component is called in a canonical order. The canonical order of
components is last dimension varying fastest for an array, and positional
aggregate order for a record. Bounds are not included in the stream if T is
an array type. If T is a discriminated type, discriminants are included only
if they have defaults. If T is a tagged type, the tag is not included.
For nonlimited type extensions, the Write or Read attribute for the parent type
is called, followed by the Write or Read attribute of each non-inherited
component, in canonical order. For other derived types, the Write or Read
attribute of the parent type is inherited.
!corrigendum 13.13.02(27)
Insert after the paragraph:
- S'Output then calls S'Write to write the value of Item to the
stream. S'Input then creates an object (with the bounds or
discriminants, if any, taken from the stream), initializes it
with S'Read, and returns the value of the object.
the new paragraph:
If T is a type extension, S'Output and S'Input are not inherited from the
parent type; they are defined in terms of S'Read and S'Write, notwithstanding
the inheritance rule stated in 13.1.
!corrigendum 13.13.02(36)
Insert after the paragraph:
The stream-oriented attributes may be specified for any type via an
attribute_definition_clause. All nonlimited types have default
implementations for these operations. An attribute_reference for one of
these attributes is illegal if the type is limited, unless the attribute
has been specified by an attribute_definition_clause. For an
attribute_definition_clause specifying one of these attributes, the
subtype of the Item parameter shall be the base subtype if scalar, and the
first subtype otherwise. The same rule applies to the result of the Input
function.
the new paragraphs:
For every subtype S of a language-defined nonlimited specific type T, the
output generated by S'Output or S'Write shall be readable by S'Input or
S'Read, respectively. The object read by S'Input or S'Read shall behave as
the original object for the operations declared in the language-defined
descendants of the unit that declares T. This rule applies across
partitions if the implementation conforms to the Distributed Systems Annex.
For every subtype S'Class of a language-defined class-wide type T'Class, the
attributes S'Class'Write, S'Class'Read, S'Class'Input, and S'Class'Output
have their predefined definition.
!ACATS test
A C-Test to check that the Read and Write attributes of an extension are
defined as in this issue should be created. It should also check that the
Input and Output attributes revert to the predefined versions for an extension.
Tests to check that language defined nonlimited private types properly support
'Read and 'Write should also be created.
!appendix
!section 13.13.2(09)
!subject Missing AI: 'Input/'Output inheritance
!reference RM95-13.13.2(9,36)
!reference RM95-13.1(15)
!from Tucker Taft 95-10-30
!reference 95-5373.a Tucker Taft 95-10-30>>
!discussion
The general rule for inheritance of type-related representation aspects
should not apply to the stream attributes of type extensions.
For 'Read and 'Write, a rule analogous to the rule for tagged equality
would make the most sense. For 'Input and 'Output, no inheritance makes
sense; instead, they should regain their predefined meaning in terms
of 'Read and 'Write.
This issue was discussed at length in some Ada 95 forum or other
(perhaps the GNAT team mailing list?). There are several problems
associated with applying the normal 13.1(15) inheritance rules to
the stream attributes of tagged types:
1) Inheriting a 'Read or 'Write of the parent type as-is for
the 'Read or 'Write of a type extension will ignore any new
components added in the extension part. A rule analogous
to the one for the equality operator would make more sense.
In particular, the default 'Read or 'Write for a type extension
should be defined to do the 'Read or 'Write of the parent type
followed by the 'Read or 'Write for each component of the
type extension, in canonical order.
2) Inheriting a 'Input or 'Output of the parent type as-is for
'Input or 'Output of a type extension makes no sense, since
the inherited 'Input is a function returning the parent type,
and the inherited 'Output puts out the discriminants of the
parent type. For these two, the only meaningful approach seems
to be for the default 'Input and 'Output for a tagged type to
always be defined in terms of the 'Read and 'Write for the
tagged type, preceded with the discriminants, if any.
For untagged derived types, there is no problem for the derived
type inheriting the stream attributes. Even for tagged derived
types, if the extension part is null, the 'Read and 'Write will
effectively be inherited, given the rule suggested above.
****************************************************************
!section 13.3.2(00)
!subject stream attributes for unbounded string, bounded string etc.
!reference RM95-13.3.2(00)
!from Bob Duff
!reference 96-5480.a Robert A Duff 96-4-12>>
!discussion
Robert Dewar pointed out this issue to me.
It would seem that the stream attributes should work properly for all
the language-defined non-limited types. For example, types
Strings.Unbounded.Unbounded_String, Strings.Bounded.Bounded_String, etc.
- Bob
****************************************************************
!section 13.13.2(00)
!subject Stream-Oriented attributes for language-defined private types
!reference RM95-13.13.2
!from Laurent Guerby 96-07-15
!reference 96-5621.a Laurent Guerby 96-7-15>>
!discussion
The behaviour of the stream oriented attributes is not clearly
defined for most of private (or implementation-defined) types. This
can lead to erroneous execution (but nothing is said about it in the
RM95) if type type has a component of an access type when some object
of this type is exchanged between two partitions. An example of
interest is Unbounded_String.
--
Laurent Guerby <guerby@gnat.com>, Team Ada.
"Use the Source, Luke. The Source will be with you, always (GPL)."
****************************************************************
From Randy Brukardt 3-7-2000
Paragraph 13.1(15.1) is not normative (it follows from other rules), and
could be omitted.
****************************************************************
Questions? Ask the ACAA Technical Agent