Version 1.5 of ais/ai-00137.txt
!standard 13.01 (10-11) 00-04-12 AI95-00137/04
!class binding interpretation 96-05-07
!status Corrigendum 2000 99-07-28
!status WG9 approved 96-12-07
!status ARG approved 6-0-2 96-06-17
!status work item 96-05-08
!status received 96-05-07
!priority High
!difficulty Medium
!qualifier Error
!subject Attribute definition clause for Stream Attributes
!summary
13.1(10) says:
10 For an untagged derived type, no type-related representation items are
allowed if the parent type is a by-reference type, or has any user-defined
primitive subprograms.
This rule does not apply to an attribute_definition_clause for one of
the stream-oriented attributes Read, Write, Input, and Output.
!question
13.1(10) seems to forbid the following example:
with Ada.Streams; use Ada.Streams;
generic
type T is private;
package Attr_Rep is
type NT is new T;
procedure Attribute_Write(
Stream : access Root_Stream_Type'Class;
Item : in NT);
for NT'Write use Attribute_Write; --
end Attr_Rep;
!recommendation
(See summary.)
!wording
(See corrigendum.)
!discussion
The intent of 13.1(10) is to forbid two types from having different
representation in certain cases. However, the stream-oriented
attributes, although they are formally defined to be "representation
attributes", do not actually affect the representation of the type.
Therefore, there is no need for 13.1(10) to apply to these attributes.
Furthermore, as the example illustrates, applying the rule to these
attributes would seriously hinder their usefulness.
The definition of stream attributes as "representation attributes" has
proven to be a continuing problem. Several issues have made it necessary
to except stream attributes from the rules for representation attributes,
enough that it is clear that they are not representation attributes. Therefore,
we have taken the major step of defining a new kind of attribute, the
"operational attributes", and redefining stream attributes to be of this kind.
!corrigendum 3.08(05)
Replace the paragraph:
component_item ::= component_declaration | representation_clause
by:
component_item ::= component_declaration | aspect_clause
!corrigendum 3.11(04)
Replace the paragraph:
basic_declarative_item ::=
basic_declaration | representation_clause | use_clause
by:
basic_declarative_item ::=
basic_declaration | aspect_clause | use_clause
!corrigendum 9.01(05)
Replace the paragraph:
task_item ::= entry_declaration | representation_clause
by:
task_item ::= entry_declaration | aspect_clause
!corrigendum 9.04(05)
Replace the paragraph:
protected_operation_declaration ::= subprogram_declaration
| entry_declaration
| representation_clause
by:
protected_operation_declaration ::= subprogram_declaration
| entry_declaration
| aspect_clause
!corrigendum 9.04(08)
Replace the paragraph:
protected_operation_item ::= subprogram_declaration
| subprogram_body
| entry_body
| representation_clause
by:
protected_operation_item ::= subprogram_declaration
| subprogram_body
| entry_body
| aspect_clause
!corrigendum 13.01(00)
Replace the paragraph:
Representation Items
by:
Operational and Representation Items
!corrigendum 13.01(01)
Replace the paragraph:
There are three kinds of representation items: representation_clauses,
component_clauses, and representation pragmas. Representation items
specify how the types and other entities of the language are to be mapped onto
the underlying machine. They can be provided to give more efficient
representation or to interface with features that are outside the domain of
the language (for example, peripheral hardware). Representation items also
specify other specifiable properties of entities. A representation item
applies to an entity identified by a local_name, which denotes an entity
declared local to the current declarative region, or a library unit declared
immediately preceding a representation pragma in a compilation.
by:
There are six kinds of representation items:
attribute_definition_clauses for representation attributes,
enumeration_representation_clauses, record_representation_clauses,
at_clauses, component_clauses, and representation pragmas.
Representation items
specify how the types and other entities of the language are to be mapped onto
the underlying machine. They can be provided to give more efficient
representation or to interface with features that are outside the domain of
the language (for example, peripheral hardware). An
attribute_definition_clause for an operational attribute is an
operational item. Operational items specify other specifiable properties
of entities. An operational item or a representation item applies to an entity
identified by a local_name, which denotes an entity declared local to the
current declarative region, or a library unit declared immediately preceding a
representation pragma in a compilation.
!corrigendum 13.01(02)
Replace the paragraph:
representation_clause ::= attribute_definition_clause
| enumeration_representation_clause
| record_representation_clause
| at_clause
by:
aspect_clause ::= attribute_definition_clause
| enumeration_representation_clause
| record_representation_clause
| at_clause
!corrigendum 13.01(04)
Replace the paragraph:
A representation pragma is allowed only at places where a
representation_clause or compilation_unit is allowed.
by:
A representation pragma is allowed only at places where an
aspect_clause or compilation_unit is allowed.
!corrigendum 13.01(05)
Replace the paragraph:
In a representation item, if the local_name is a direct_name, then it
shall resolve to denote a declaration (or, in the case of a pragma, one or
more declarations) that occurs immediately within the same
declarative_region as the representation item. If the local_name has
an attribute_designator, then it shall resolve to denote an
implementation-defined component (see 13.5.1) or a class-wide type implicitly
declared immediately within the same declarative_region as the
representation item. A local_name that is a
library_unit_name (only permitted in a representation pragma) shall
resolve to denote the library_item that immediately precedes (except for
other pragmas) the representation pragma.
by:
In an operational item or representation item, if the local_name is a
direct_name, then it shall resolve to denote a declaration (or, in the
case of a pragma, one or more declarations) that occurs immediately
within the same declarative_region as the item. If the local_name
has an attribute_designator, then it shall resolve to denote an
implementation-defined component (see 13.5.1) or a class-wide type implicitly
declared immediately within the same declarative_region as the
item. A local_name that is a
library_unit_name (only permitted in a representation pragma) shall
resolve to denote the library_item that immediately precedes (except for
other pragmas) the representation pragma.
!corrigendum 13.01(06)
Replace the paragraph:
The local_name of a representation_clause or representation pragma
shall statically denote an entity (or, in the case of a pragma, one or
more entities) declared immediately preceding it in a compilation, or
within the same declarative_part, package_specification,
task_definition, protected_definition, or record_definition
as the representation item. If a local_name denotes a local callable
entity, it may do so through a local subprogram_renaming_declaration
(as a way to resolve ambiguity in the presence of overloading); otherwise, the
local_name shall not denote a renaming_declaration.
by:
The local_name of an aspect_clause or representation pragma
shall statically denote an entity (or, in the case of a pragma, one or
more entities) declared immediately preceding it in a compilation, or
within the same declarative_part, package_specification,
task_definition, protected_definition, or record_definition
as the representation or operational item. If a local_name denotes a
local callable entity, it may do so through a local
subprogram_renaming_declaration (as a way to resolve ambiguity in the
presence of overloading); otherwise, the local_name shall not denote a
renaming_declaration.
!corrigendum 13.01(08)
Insert after the paragraph:
A representation item directly specifies an aspect of representation of
the entity denoted by the local_name, except in the case of a type-related
representation item, whose local_name shall denote a first subtype, and
which directly specifies an aspect of the subtype's type. A representation
item that names a subtype is either subtype-specific (Size and Alignment
clauses) or type-related (all others). Subtype-specific aspects may differ
for different subtypes of the same type.
the new paragraph:
An operational item directly specifies an operational aspect of the
type of the subtype denoted by the local_name. The local_name of an
operational item shall denote a first subtype. Operational items are
type-related.
!corrigendum 13.01(09)
Insert after the paragraph:
A representation item that directly specifies an aspect of a subtype or
type shall appear after the type is completely defined (see 3.11.1), and
before the subtype or type is frozen (see 13.14). If a representation item
is given that directly specifies an aspect of an entity, then it is illegal
to give another representation item that directly specifies the same aspect
of the entity.
the new paragraph:
An operational item that directly specifies an aspect of a type shall appear
before the type is frozen (see 13.14). If an operational item is given that
directly specifies an aspect of a type, then it is illegal to give another
operational item that directly specifies the same aspect of the type.
!corrigendum 13.01(11)
Replace the paragraph:
Representation aspects of a generic formal parameter are the same as
those of the actual. A type-related representation item is not allowed for a
descendant of a generic formal untagged type.
by:
Operational and representation aspects of a generic formal parameter are the
same as those of the actual. A type-related representation item is not allowed
for a descendant of a generic formal untagged type.
!corrigendum 13.01(19)
Replace the paragraph:
For the elaboration of a representation_clause, any evaluable constructs
within it are evaluated.
by:
For the elaboration of an aspect_clause, any evaluable constructs
within it are evaluated.
!corrigendum 13.03(00)
Replace the paragraph:
Representation Attributes
by:
Operational and Representation Attributes
!corrigendum 13.03(01)
Replace the paragraph:
The values of certain implementation-dependent characteristics can be
obtained by interrogating appropriate representation attributes. Some of
these attributes are specifiable via an attribute_definition_clause.
by:
The values of certain implementation-dependent characteristics can be obtained
by interrogating appropriate operational or representation attributes. Some of
these attributes are specifiable via an attribute_definition_clause.
!corrigendum 13.03(05)
Replace the paragraph:
An attribute_designator is allowed in an attribute_definition_clause
only if this International Standard explicitly allows it, or for an
implementation-defined attribute if the implementation allows it. Each
specifiable attribute constitutes an aspect of representation.
by:
An attribute_designator is allowed in an attribute_definition_clause
only if this International Standard explicitly allows it, or for an
implementation-defined attribute if the implementation allows it. Each
specifiable attribute constitutes an operational aspect or an aspect of
representation.
!corrigendum 13.03(09)
Replace the paragraph:
The following attributes are defined:
by:
The following representation attributes are defined: Address, Alignment, Size,
Storage_Size, and Component_Size.
!corrigendum 13.03(74)
Replace the paragraph:
For every subtype S of a tagged type T (specific or class-wide), the following
attribute is defined:
by:
The following operational attribute is defined: External_Tag.
For every subtype S of a tagged type T (specific or class-wide):
!corrigendum 13.04(11)
Replace the paragraph:
11 Unchecked_Conversion may be used to query the internal codes used
for an enumeration type. The attributes of the type, such as Succ,
Pred, and Pos, are unaffected by the representation_clause. For
example, Pos always returns the position number, not the internal
integer code that might have been specified in a representation_clause.
by:
11 Unchecked_Conversion may be used to query the internal codes used
for an enumeration type. The attributes of the type, such as Succ,
Pred, and Pos, are unaffected by the enumeration_representation_clause. For
example, Pos always returns the position number, not the internal
integer code that might have been specified in a
enumeration_representation_clause.
!corrigendum 13.11(12)
Replace the paragraph:
For every access subtype S, the following attributes are defined:
by:
For every access subtype S, the following representation attributes are defined:
!corrigendum 13.13.2(1)
Replace the paragraph:
The Write, Read, Output, and Input attributes convert values to a
stream of elements and reconstruct values from a stream.
by:
The operational attributes Write, Read, Output, and Input convert values to a
stream of elements and reconstruct values from a stream.
!corrigendum 13.14(19)
Replace the paragraph:
A representation item that directly specifies an aspect of an entity shall
appear before the entity is frozen (see 13.1).
by:
An operational item or a representation item that directly specifies an
aspect of an entity shall appear before the entity is frozen (see 13.1).
!ACATS test
Create a C-Test to verify that Read/Write attributes can be defined
on derived non-tagged types.
!appendix
!section 13.1(10)
!subject Attribute definition clause for Stream Attributes
!reference RM95-13.1(10)
!reference RM95-13.1(11)
!reference RM95-13.13.2(36)
!from Anthony Gargaro 96-04-28
!keywords
!reference 96-5519.a Anthony Gargaro 96-4-28>>
!discussion stream attributes, representation items
A consequence of specifying attribute definition clauses for the stream
attributes is that the restrictions associated with representation items
hamper the use of stream attributes. For example, the following idiom is
illegal by 13.1(11).
with Ada.Streams; use Ada.Streams;
generic
type T is private;
package Attr_Rep is
type NT is new T;
procedure Attribute_Write(
Stream : access Root_Stream_Type'Class;
Item : in NT);
-- Illegal use of attribute definition clause
for NT'Write use Attribute_Write;
end Attr_Rep;
package body Attr_Rep is
procedure Attribute_Write(
Stream : access Root_Stream_Type'Class;
Item : in NT) is
begin
-- Save type information for dispatching Write and then call
T'Write(Stream, T(Item));
end Attribute_Write;
end Attr_Rep;
Since allowing such idioms facilitates reading/writing streams that are
architecture neutral, consideration should be given to relaxing the
application of 13.1(10,11) to representation-independent attributes.
****************************************************************
!section 13.1(10)
!subject Attribute definition clause for Stream Attributes
!reference RM95-13.1(10)
!reference RM95-13.1(11)
!reference RM95-13.13.2(36)
!keywords stream attributes, representation items
!reference 96-5519.a Anthony Gargaro 96-4-28
!keywords stream attributes, representation items
!from Norman Cohen 96-04-29
!reference 96-5521.a Norman H. Cohen 96-4-29>>
!discussion
Interestingly, 13.1(11) does not prohibit the following workaround:
with Ada.Streams; use Ada.Streams;
generic
type T is private;
package Attr_Rep is
type NT is
record
Only_Component: T;
end record;
procedure Attribute_Write(
Stream : access Root_Stream_Type'Class;
Item : in NT);
for NT'Write use Attribute_Write;
end Attr_Rep;
package body Attr_Rep is
procedure Attribute_Write(
Stream : access Root_Stream_Type'Class;
Item : in NT) is
begin
-- Save type information for dispatching Write and then call
T'Write(Stream, Item.Only_Component);
end Attribute_Write;
end Attr_Rep;
Of course this is a nuisance: NT doesn't inherit T's operations, so one
always has to invoke Op(X.Only_Component) instead of Op(X). One can
define corresponding operations for type NT manually, but there is no way
to allow direct conversions between descendents of NT and types that are
truly in the derivation class for T. (One wishes to use NT rather than T
in constructing new types, so that the 'Write for the new type invokes
NT'Write.)
On the one hand, the existence of such a loophole indicates that there is
no fundamental problem with the relaxation Anthony suggests. On the
other hand, the existence of the loophole may make resolution of the
problem a little less of an emergency.
****************************************************************
!section 13.1(10)
!subject Attribute definition clause for Stream Attributes
!reference RM95-13.1(10)
!reference RM95-13.1(11)
!reference RM95-13.13.2(36)
!keywords stream attributes, representation items
!reference 96-5519.a Anthony Gargaro 96-4-28
!keywords stream attributes, representation items
!reference 96-5521.a Norman H. Cohen 96-4-29
!from Bob Duff
!reference 96-5542.a Robert A Duff 96-5-8>>
!discussion
Norm says:
> Interestingly, 13.1(11) does not prohibit the following workaround:
> [workaround involving wrapping the type in a record]
Right. Another workaround is to simply make the thing a tagged type,
since 13.1(11) applies only to untagged types.
- Bob
****************************************************************
!section 13.1(10)
!subject Attribute definition clause for Stream Attributes
!reference RM95-13.1(10)
!reference RM95-13.1(11)
!reference RM95-13.13.2(36)
!reference 96-5519.a Anthony Gargaro 96-4-28
!reference 96-5521.a Norman H. Cohen 96-4-29
!reference 96-5542.a Robert A Duff 96-5-8
!from Anthony Gargaro 96-05-10
!reference 96-5546.a Anthony 96-5-10>>
!discussion
>>Norm says:
>> Interestingly, 13.1(11) does not prohibit the following workaround:
>> [workaround involving wrapping the type in a record]
to which Bob replied:
>Right. Another workaround is to simply make the thing a tagged type,
>since 13.1(11) applies only to untagged types.
In the context of the application where this issue was raised both of these
options were considered. Unfortunately, neither seems satisfactory since the
useability of the abstraction which is presented to the programmer is
compromised. This is because the idiom requires the incremental composition of
types to allow arbitrary user-defined types to be associated with "architecture
neutral" stream attributes.
In the case of wrapping the type (which is used at the moment), there is a
useability penalty. The programmer must be aware of the wrapper name when
referencing subcomponents of the type and this may become onerous if the
composite type contains other composite types.
****************************************************************
Notes from Pascal Leroy on the changes to define operational attributes,
dated 2000-02-23:
While there are many changes, the overall scheme is quite simple: not all
attribute_definition_clauses are representation items, some are operational
items. Operational items are legal in places where representation items are
not (e.g. before a type is complete) but by and large they follow the same
rules. One notable difference is that an implementation may decide to reject a
representation item that it doesn't like, but not an operational item (with the
current wording of the RM, the support of stream attributes is entirely
optional, even if you support annex C). Then, for each attribute we have to
say whether it's a representation attribute or an operational attribute.
****************************************************************
Notes from the editor, dated 2000-03-08
Discussions with Pascal added the following points:
It is quite unclear what is the scope of the sentence "The following
representation attributes are defined:" in 13.3(9) (which was originally
"The following attributes are defined"). Obviously it doesn't cover
13.3(61-65), which is a pragma, not an attribute. But then it seems to cover
13.3(68-73) because of the sentence that start with "For ..." in 13.3(68). At
any rate, whoever wrote this part decided that there was enough confusion when
reaching 13.3(74) that they specified again that "the following attribute is
defined". We have changed 13.3(68) to be consistent with the idea that the
scope of that statement stops at 13.3(59). But it might be clearer to change
each of the attribute definitions consistently with 13.3(68) and 13.3(74),
deleting 13.3(9) completely.
The syntax changes are scattered about, but should not change the actual
syntax of the language in any way. The reason for the syntax changes is not
clear, so I'll explain it here.
Ada 95 uses reference to syntax constructs wherever possible. There are several
dozen uses of "Representation_Clause", many of which should not apply to
operational items. In order to fix this, operational items have to be split
out of Representation_Clause, which requires a syntax change.
Representation_Clause is used in five places in the Ada 95 grammar (3.8, 3.11,
9.1, and 9.4 (twice). We need to consider the impact of changes in all five
places.
The most appealing fix is to define the syntax as follows:
representation_clause ::= attribute_definition_clause
| enumeration_representation_clause
| record_representation_clause
| at_clause
operational_clause ::= attribute_definition_clause
and then add operational_clause to 3.11(4) [operational attributes definition
clauses only make sense in declarative parts.]
However, this grammar is ambiguous, in that there is no way to tell when an
attribute definition clause is operational or representational syntactically.
Pascal proposed removing attribute_definition_clause from representation_clause,
then adding it back where needed. He suggested only adding it to 3.11(4), as
that is the primary usage. However, that would prevent the use of attribute
definition clauses in protected types (both specification and body), task
specifications, and component clauses. While not all of these have useful
clauses today, eliminating their use in those places would be a substantial
change.
Randy (the editor) proposed the following:
representation_clause ::= attribute_definition_clause
| representation_item_clause
representation_item_clause ::= enumeration_representation_clause
| record_representation_clause
| at_clause
This has the advantage of not requiring changes at the uses of
representation_clause. However, Pascal though it to be too confusing (that
a representation_clause wasn't necessarily a representation clause), and I
agreed with him.
Therefore, I've changed the grammar to:
aspect_clause ::= attribute_definition_clause
| representation_clause
representation_clause ::= enumeration_representation_clause
| record_representation_clause
| at_clause
and modified all 5 uses. This version allows use to use "aspect_clause" rather
than "representation_clause and attribute_definition_clause" wherever some
rule applies to both representation and operational aspects.
One alternative would be to avoid the syntax changes altogether by saying
"representation_clauses except operational items" at the appropriate points.
But that seems to confuse the issue.
Note that the changes listed here don't include the corresponding changes
in the (non-normative) syntax summary. I'll do this in the integrated
reference manual, of course, but doing it here just bulks this up further.
****************************************************************
Notes from the editor, dated 2000-04-12
AT the Phoenix ARG meeting, it was decided to minimize the syntax changes
(by only changing Representation_Clause to Aspect_Clause), and make all other
changes in the text. The current wording reflects that.
****************************************************************
Questions? Ask the ACAA Technical Agent