Version 1.7 of ai12s/ai12-0427-1.txt
!standard 3.5(56.4/3) 21-06-03 AI12-0427-1/06
!standard 3.6(22.2/3)
!standard 4.1.3(13.1/5)
!standard 4.2.1(0/5)
!standard 4.3.5(0/5)
!standard 4.5.10(0/5)
!standard 4.9.1(2/3)
!standard 4.10(0/5)
!standard 5.6.1(0/5)
!standard 8.5(5)
!standard 8.6(17.1/5)
!standard 9.10.1(26/5)
!standard 13.1(10/5)
!standard 13.1(13.1/3)
!standard 13.1.1(11/5)
!standard 13.1.1(21/3)
!standard 13.1.1(22/3)
!standard 13.3(6)
!standard 13.13.2(51/3)
!standard B.3(65.1/5)
!class Amendment 21-05-07
!status Amendment 1-2012 21-05-07
!status ARG Approved 14-0-1 21-06-03
!status work item 21-05-07
!status received 21-05-07
!priority Low
!difficulty Easy
!subject Fixups from WG 9 review
!summary
(1) Add rules about the propagation of exceptions from implicit calls to
Put_Image.
(2) Delete 8.5(5); it is not true in Ada 202x (and part of it was not true
in Ada 2005 or Ada 2012, either).
(3) Add "unless otherwise specified" to the second sentence of 8.6(17.1/5).
(4) Add a case for "aggregates" to 13.1.1(19-22/3).
(5) Generalize 13.3(6) (moving it after 13.1(13.1/3)) and 13.13.2(51/3) to
apply to aspect_specifications as well as attribute_definition clauses.
(6) Remove "no primitive subprograms" from 3.5(56.4/3) and 3.6(22.2/3).
(7) Drop the text added by AI12-0411-1 to B3.(65.1/5).
(8) Clarify the second sentence of 4.5.10(34/5).
(9) Replace the original 13.1(10) in the case of primitive subprogram
parameters that are passed by reference and thus cannot be converted to a
different representation.
(10) Add a special case to 3.5(56.4/3) to prevent problems with the
inheritance of routines that would be illegal if called explicitly.
(11) In 4.3.5(6/5), change the matching to require "exactly one" and
allow any signed integer type for the parameter if any.
(12) Clarify that the Implementation Permission in 9.10.1 also applies to
All_xxx_Checks policies.
(13) Clarify what is passed to xxx_Literal functions.
(14) Add an aspect_specification to parallel blocks.
(15) Restrict the deferred resolution of aspect_specifications to those
appearing on a declaration.
(16) 4.1.3(13.1/5) needs to define the context of the Access attribute
so that resolution is well-defined.
(17) Extend 4.9.1(1.5/5) to properly account for global aspects that
contain global_names. Also, change "statically denotes" to "statically
names" in 6.1.1(9/5) to allow as many names as possible to be used in a
global aspect.
!problem
(1) Stream-oriented attributes define the subtype of the parameter of the
associated subprograms with 13.13.2(51/3). We don't have any similar rule
for Put_Image in 4.10. The definition of Put_Image seems to suggest that
the parameter is of type T, but types do not have names in Ada -- one always
has to specify a subtype.
Additionally, the RM doesn't mention that the implicit calls of Put_Image
propagate any exceptions (including those caused by a subtype check
failure).
(2) 8.5(5) says that an object of an anonymous access type cannot be renamed.
However, it seems to me that the second alternative in 8.5.1(1/5), the
"access_definition" case, does allow such a renaming. Similarly, 8.5(5) says
that a single task or protected object cannot be renamed since the
corresponding type is anonymous, but as we can now omit the subtype_mark
from the object_renaming_declaration, it seems that such entities can be
renamed. Either I am wrong, or the statements in 8.5(5) are wrong.
(3) The nominal (sub)type specified in 8.6(17.1/5) for the "current instance"
value seems to be overridden in 7.3.2(5/4) for the aspect
Type_Invariant'Class, and in 7.3.3(4/5) for the aspect
Default_Initial_Condition, where different types ("NT") are specified for the
current instance. This apparent contradiction should be addressed in some way.
(4) In RM 13.1.1(19/3-22/3) we have:
Depending on which aspect is identified by the aspect_mark, an
aspect_definition specifies:
* a name that denotes a subprogram, object, or other kind of entity;
* an expression, which is either evaluated to produce a single value, or
which (as in a precondition) is to be evaluated at particular points during
later execution; or
* an identifier specific to the aspect.
This is relatively old wording, and doesn't mention "aggregate" which is of
course a kind of expression, but in newer wording is called out separately,
and it is certainly misleading to talk about it being evaluated to produce a
"single value."
(5) Paragraphs 13.3(6) and 13.13.2(51/3) give requirements on subprograms
specified for attributes (aspects) via an attribute_definition_clause. There
is no rule that does that for aspects specified via aspect_specifications.
(6) 3.5(56.4/3) says:
If a derived type with no primitive subprograms inherits a boolean
Default_Value aspect, the aspect may be specified to have any value for the
derived type.
It is likely that the "with no primitive subprograms" was included to ensure
that we didn't unintentionally override 13.1(10) with this rule. However,
Ada 202x removes the bulk of 13.1(10) (which mostly was intended to avoid
expensive implicit conversions -- but the effect was to prevent programmers
from writing derived types that they needed even if the expensive conversion
was not a problem). This means this rule as written is a wart, as it seems to
prevent non-confirming Default_Value aspects in the case of a type with
primitive subprograms.
3.6(22.2/3) has similar wording.
(7) We have added C_bool to Interfaces.C, which is defined to be equivalent to
C's "bool" (or "_Bool"). It now seems misleading to say that Ada's
Standard.Boolean type "corresponds" to the C bool type. The point of
introducing C_bool was so that you could be certain that you had a type
compatible with C, and there was no guarantee that, for example, a record
component of type Standard.Boolean would match a C struct component of type
"bool."
The current state of RM B.3(65.1/5) is
An Ada enumeration type corresponds to a C enumeration type with
corresponding enumeration literals having the same internal codes, provided
the internal codes fall within the range of the C int type. The Ada Boolean
type corresponds to the C bool type.
That last sentence was not present when this paragraph was added, which
originated from AI12-0135-1. The last sentence came from AI12-0411-1, which
defined Interfaces.C.C_bool. That last sentence seems to miss the whole point
of the addition of C_bool, namely, that there is no requirement that the Ada
Boolean type itself corresponds to the C bool type.
(8) 4.5.10 (34/5) says:
For a parallel reduction expression, it is a bounded error if the reducer
subprogram is not associative. That is, for any arbitrary values of subtype
Value_Type A, B, C and a reducer function R, the result of R (A, R(B, C))
should produce a result equal to R (R (A, B), C)). The possible consequences
are Program_Error, or a result that does not match the equivalent sequential
reduction expression due to the order of calls on the reducer subprogram
being unspecified in the overall reduction. Analogous rules apply in the
case of a reduction procedure.
The second sentence is misleading in that it is explaining what associative
means while the first sentence talks about being not associative.
(9) We have relaxed the rules relating to specifying type-related representation
aspects when there are primitives that might be inherited by derived types
with a different representation. However, we did not take into account that
some parameters are necessarily passed by reference, even if the type itself
is not a by-reference type. Such parameters cannot easily be converted
automatically when calling an inherited subprogram.
(10) Paragraphs 6.4.1(5.1/5) through 6.4.1(5.4/4) define a Legality check for
some scalar view conversions passed to OUT mode parameters.
When a type is derived, any inherited subprograms are called with the actual
parameters of the new type view converted to the parent type. This can cause
an anomaly, in that an explicit call would be illegal while calling an
inherited routine (which makes the same call implicitly) is legal.
Tucker notes that 6.4.1(15.1/5) says that this view conversion raises
Program_Error. Therefore, there is no language bug because code that does
not follow the principles cannot be executed. OTOH, the rule Tucker refers
to was only intended to be used in generic bodies (and there is an AARM note
to that effect). So implementers and users alike are likely to be confused.
Moreover, we have a Language Design Principle (admittedly, not always
followed) that a construct which will always raise an exception should be
detected at compile-time. So it seems that a Legality Rule is missing here.
(11) The optional parameter of the Empty function is required in 4.3.5(6/5)
to be of type (Standard.) Integer. However, the language-defined containers
use Empty functions that have an Ada.Containers.Count_Type parameter, and
that does not match this specification.
(12) Are these permissions granted also when the (stronger) policies
All_Parallel_Conflict_Checks or All_Tasking_Conflict_Checks apply? It is
said earlier in this subclause that these stronger policies "include" the
restrictions imposed by the weaker (Known_...) policies, but it is not clear
that specifying the stronger policies implies that the weaker policies also
"apply", which is the condition now given for these permissions.
(13) 4.2.1(7/5) says:
... The actual parameter of this notional call is a string_literal having
the textual representation of the original (numeric or string) literal.
Does the textual representation of a string literal include the quotes on
either end? And what about doubled quotation marks occurring in the middle?
Based on the example of Roman_Number, I would guess the answer is the
enclosing quotes are removed, and a doubled quotation mark becomes a single
quotation mark, but that is not clear from this rule.
Additionally, how can a string literal have the same textual representation
as a numeric literal? At a minimum it needs enclosing quotation marks. This
needs to be better specified.
(14) AI12-0355-2 adds aspect_specifications to "all constructs that use the
reserved word parallel". But that was not done for a parallel block, which
uses the reserved work parallel.
(15) AI12-0355-2, as well as the previous issue, adds aspect_specifications to
certain statements and expressions. 13.1.1(11/5) says:
The usage names in an aspect_definition are not resolved at the point of the
associated declaration, but rather are resolved at the end of the
immediately enclosing declaration list, or in the case of the declaration of
a library unit, at the end of the visible part of the entity.
This doesn't make sense when an aspect_specification is associated with
something other than a declaration -- we might not even directly be in a
declaration list (and the declaration list containing a body is way too late).
(16) 4.1.3(13.1/5) says:
For a prefixed view of a subprogram whose first parameter is an access
parameter, the prefix shall be legal as the prefix of an Access attribute
reference.
There are two problems with this. First, an Access
attribute reference normally occurs in some specific context
that, for example, defines its expected type. That is not the case here,
and given that the resolution of the prefix of an Access attribute depends
on the expected type, it is not completely clear what this wording means.
Second, Ada doesn't define an "attribute reference". There is an implicit
definition as an "attribute_reference", but that doesn't explain how the
identifier is associated. Other uses use the longer but clearly correct
"an attribute_reference with attribute_designator Blah". We should either
define "attribute reference" properly, or use the longer wording.
(17) The statically matching rule for Global aspects (4.9.1(1.5/5) says
... or each is of the form “global_mode global_designator” with
the same sequence of reserved words.
But a global_designator can be a global_name, so it seems like we need
a requirement that corresponding global_names have to statically denote
the same entity.
Additionally, we now have "statically names" for objects, which allows
selected and indexed names when those are known at compile-time. We should
use that in 6.1.2(9/5) and in 4.9.1(1.5/5) to allow as much as possible in
global aspects.
!proposal
(1) Add appropriate wording.
(2) Delete 8.5(5).
(3) Add "unless otherwise specified" to the second sentence of 8.6(17.1/5).
(4) Add an extra bullet for "aggregates".
(5) (See summary.)
(6) (See summary.)
(7) (See summary.)
(8) Add clarifying text at the end of the second sentence of 4.5.10(34/5).
(9) Add a definition of a "by-reference primitive", and disallow nonconfirming
representation clauses if any of those are present.
(10) Add a special case to 3.5(56.4/3) preventing specification of
Default_Value if this problem can happen.
(11) Allow the optional parameter to be of any integer type. Also, require
exactly one function to match this, to avoid issues if there are multiple
routines that match these profiles.
(12) Add All_Parallel_Conflict_Checks or All_Tasking_Conflict_Checks to
the permission of 9.10.1(26/5).
(13) Clarify what is passed to xxxx_Literal functions.
(14) Add an aspect_specification to a parallel block, and update the semantics
to include it.
(15) (See summary.)
(16) (See summary.)
(17) (See summary.)
!wording
[Editor's note: These changes have been applied to Draft 30 of the RM, even
though they are not yet approved, in order that the draft reflect as much of
the accepted WG 9 comments as possible.]
(1) A version of the first problem also occurs in AI12-0435-1, and we
chose to fix it there as that AI also includes other fixes.
Add to the end of each of 4.10(28.2/5), 4.10(31/5), 4.10(34/5):
Redundant[Any exception propagated by the call of S'Put_Image is
propagated.]
[Editor's note: There is no attempt to have such wording for the
default implementations of the stream-oriented attributes, so we make no
attempt to do that here, either. All such wording is redundant, since it
follows directly from the definition of exception propagation in 11.4.]
(2) Delete 8.5(5).
(3) Modify 8.6(17.1/5):
Within an aspect_specification for a type or subtype, the current instance
represents a value of the type; it is not an object. {Unless otherwise
specified, the}[The] nominal subtype of this value is given by the subtype
itself (the first subtype in the case of a type_declaration), prior to
applying any predicate specified directly on the type or subtype. If the
type or subtype is by-reference, the associated object of the value is the
object associated (see 6.2) with the evaluation of the usage name.
(4) Modify 13.1.1(21/3):
* an expression{ (other than an aggregate)}, which is either evaluated to
produce a single value, or which (as in a precondition) is to be evaluated
at particular points during later execution;[ or]
Modify 13.1.1(22/3):
* an identifier specific to the aspect{; or
* an aggregate, which is positional or named, and is composed of elements of
any of these four kinds of constructs}.
(5) Add after 13.1(13.1/3):
When specifying an aspect that denotes a subprogram, the profile of the
subprogram shall be mode conformant with the one required for the aspect,
and the convention shall be Ada. Additional requirements are defined for
particular aspects.
AARM Ramification: As well as applying to aspect_specifications, this rule
applies to attribute_definition_clauses for those aspects that have associated
attributes.
This rule implies, for example, that if one writes:
type T is ...
with Read => R;
R has to be a procedure with two parameters with the appropriate subtypes and
modes as shown in 13.13.2.
End AARM Ramification.
[Editor's note: The latter half of this AARM Ramification is from the existing
text, modified to use an aspect_specification.]
Delete 13.3(6) and the associated notes (the rule above replaces it).
Modify 13.13.2(51/3):
For an attribute_definition_clause {or aspect_specification} specifying one of
these attributes, the subtype of the Item parameter shall be the first subtype
or the base subtype if scalar, and the first subtype if not scalar. The same
rule applies to the result of the Input function.
Modify AARM 13.13.2(51.b/3):
The view of the type at the point of the attribute_definition_clause determines
whether the base subtype is allowed. Thus, for a scalar type with a partial view
(which is never scalar), whether the base subtype is allowed is determined by
whether the attribute_definition_clause occurs before or after the full
definition of the scalar type.{ For the same reason, the base subtype is never
allowed for an attribute specified via an aspect_specification on the partial
view.}
(6) Modify 3.5(56.4/3):
If a derived type [with no primitive subprograms] inherits a boolean
Default_Value aspect, the aspect may be specified to have any value for the
derived type.
[Editor's note: This wording is modified further by (10), below.]
Modify 3.6(22.2/3):
If a derived type [with no primitive subprograms] inherits a boolean
Default_Component_Value aspect, the aspect may be specified to have any value
for the derived type.
(7) Modify B.3(65.1/5):
An Ada enumeration type corresponds to a C enumeration type with corresponding
enumeration literals having the same internal codes, provided the internal
codes fall within the range of the C int type. [The Ada Boolean type
corresponds to the C bool type.]
(8) Modify 4.5.10(34/5):
For a parallel reduction expression, it is a bounded error if the reducer
subprogram is not associative. That is, for any arbitrary values of subtype
Value_Type A, B, C and a reducer function R, the result of R (A, R (B, C))
should produce a result equal to R (R (A, B), C)){; it is a bounded error if
R does not}. The possible consequences are Program_Error, or a result that
does not match the equivalent sequential reduction expression due to the
order of calls on the reducer subprogram being unspecified in the overall
reduction. Analogous rules apply in the case of a reduction procedure.
(9) Modify 13.1(10/5):
{A by-reference primitive is a user-defined primitive subprogram for a
type T that has an access result designating type T, or that has a formal
parameter that is an access parameter designating type T or is aliased and
of type T.} It is illegal to specify a nonconfirming type-related
representation aspect for an untagged [by-reference] type T if it is
derived from a by-reference type {or inherits one or more by-reference
primitives}, or if one or more types have been derived from T prior to
the specification of the aspect {and type T is a by-reference type or
defines one or more by-reference primitives that are inherited by these
descendants}.
Modify AARM 13.1(10.b/5):
The reason for forbidding specification of type-related representation aspects
on untagged by-reference types is because a change of representation is
impossible when passing by reference (to an inherited subprogram). (A
by-reference object cannot be copied to change its representation.) {The reason
for forbidding specification of type-related representation aspects on untagged
types with by-reference primitives is that access parameters, access results,
and aliased parameters cannot be converted as part of invoking an inherited
subprogram if the representation of the designated types might be different.}
This rule is not needed for tagged types, because other rules prevent a
type-related representation aspect from changing the representation of the
parent part; we want to allow specifying a type-related representation aspect
on a type extension to specify aspects of the extension part. For example,
specifying aspect Pack will cause packing of the extension part, but not of
the parent part.
(10) Modify 3.5(56.4/3): [including the change from (6), above]
If a derived type [with no primitive subprograms] inherits a boolean
Default_Value aspect, the aspect may be specified to have any value for the
derived type.{ If a derived type T does not inherit a Default_Value aspect,
it shall not specify such an aspect if it inherits a primitive subprogram
that has a parameter of type T of mode OUT.
AARM Reason: The second sentence is to avoid violating the rules specified
in 6.4.1 about view conversions of OUT parameters with a specified
Default_Value aspect.}
(11) Modify 4.3.5(6/5):
The name specified for Empty for an Aggregate aspect shall denote a constant
of the container type, or denote [a]{exactly one} function with a result type
of the container type that has no parameters, or that has one in parameter of
[type Integer]{a signed integer type}.
(12) Modify 9.10.1(26/5):
When the conflict check policy Known_Parallel_Conflict_Checks {or
All_Parallel_Conflict_Checks} applies, the implementation may disallow two
concurrent actions appearing within parallel constructs if the implementation
can prove they will at run-time denote the same object with uses that
conflict. Similarly, when the conflict check policy
Known_Tasking_Conflict_Checks {or All_Tasking_Conflict_Checks} applies, the
implementation may disallow two concurrent actions, at least one of which
appears within a task body but not within a parallel construct, if the
implementation can prove they will at run-time denote the same object with
uses that conflict.
(13) Modify the last portion of 4.2.1(7/5):
... The actual parameter of this notional call is a string_literal
{representing a sequence of characters that is the same as the sequence
of characters in the original numeric literal, or the sequence represented
by the original string} [having the textual representation of the original
(numeric or string)] literal.
(14) Replace 5.6.1(2/5) with:
parallel_block_statement ::=
parallel [(chunk_specification)] [aspect_specification] do
handled_sequence_of_statements
and
handled_sequence_of_statements
{and
handled_sequence_of_statements}
end do;
The chunk_specification, if any, of a parallel_block_statement shall be an
/integer_/simple_expression.
Replace 5.6.1(3/5) with:
For the execution of a parallel_block_statement, the chunk_specification
and the aspect_specification, if any, are elaborated in an arbitrary order.
After elaborating the chunk_specification, if any, a check is made that the
determined maximum number of chunks is greater than zero. If this check
fails, Program_Error is raised.
Then, the various handled_sequence_of_statements are grouped into one or
more /chunks/, each with its own logical thread of control (see clause 9),
up to the maximum number of chunks specified by the chunk_specification, if
any. Within each chunk every handled_sequence_of_statements of the chunk is
executed in turn, in an arbitrary order. The parallel_block_statement is
complete once every one of the handled_sequence_of_statements has completed,
either by reaching the end of its execution, or due to a transfer of control
out of the construct by one of the handled_sequence_of_statements (see 5.1).
(15) Modify 13.1(11/5):
The usage names in an aspect_definition {associated with a declaration}
[Redundant: are not resolved at the point of the associated declaration,
but rather] are resolved at the end of the immediately enclosing declaration
list, or in the case of the declaration of a library unit, at the end of
the visible part of the entity.
(16) Modify 4.1.3(13.1/5):
For a prefixed view of a subprogram whose first {formal} parameter is an
access parameter, the prefix shall be legal as the prefix of an
{an attribute_reference with attribute_designator} Access
[attribute reference] {appearing as the first actual parameter in a call on
the unprefixed view of the subprogram}.
(17) Modify 4.9.1(1.5/5):
The Global or Global'Class aspects (see 6.1.2) of two entities statically
match if both consist of a single global_aspect_definition where each is
the reserved word null, or each is of the form
"global_mode global_designator" with {each global_mode being} the same
sequence of reserved words {and each global_designator being the same
reserved word, or each being a global_name that statically names the
same entity}.
Modify 6.1.2(9/5):
A global_name shall resolve to statically {name}[denote] an object or
a package (including a limited view of a package).
!discussion
(1) The added sentences are modeled on 13.11(21.5/3) for calls to Allocate.
Note that we don't consistently mention exception propagation in the RM;
such wording is not needed since the definition of exception propagation in
11.4 clearly covers that (it's not limited to particular constructs). For
example, we have exception propagation wording for calls to Allocator in
allocators, but we have no such wording for calls to Deallocation from
Unchecked_Deallocation. As such, we only added it in a few cases where it
was easy and did not disrupt the flow of the text.
(2) We could try to rewrite the note to make it True. However, this note is
in the introductory material for renaming, so it should not be very detailed.
Moreover, the original purpose clearly is to note that not all objects can be
renamed -- but all objects (and many values as well) CAN be renamed in
Ada 202x, so any revised note is not longer serving that purpose. The notion
that not all constructs can be used in all possible ways seems fundamental to
a programming language, and the RM does not need notes to give out random
facts (especially in the general overview material). Thus we recommend
deleting this note.
If there is felt to be value in a revised note, the Editor would suggest that
such a note would be more appropriate in 8.5.1 (details of object renaming)
rather than in the overview material of 8.5.
(3) As noted in the !problem, 7.3.2(5/4) and 7.3.3(4/5) specify a different
subtype, so we should make it clear that this rule can be overridden by a
more specific rule.
(4) An aggregate is composed of all of the other kinds of things, and might
be evaluated piece-meal. As such, it is best to handle them separately.
(5) While there can be no doubt of the intent of an equivalence between
specification via an aspect_specification and an attribute_definition_clause,
we have been trying to eliminate semantic rules that specifically
mention how some aspect/attribute is specified, since those can be misread
easily and are always confusing.
The rule of 13.3(6) (which is associated with the description of
attribute_definition_clauses) should be moved to 13.1 (which contains rules
that apply to all aspects). There are no other rules that apply to all aspects
in 13.3; this is an unusual place that even Ada experts have difficulty
finding.
The author checked the entire AARM for uses of attribute_definition_clause,
and did not find any other rules that needed generalization.
(6) As noted, 13.1(10) does not apply anymore to most derived types, so we
do not want these rules enforcing an obsolete restriction.
(7) We don't need to say that C_Bool corresponds to Bool, as that is required
by B.3(43/5) - and a requirement is stronger than Implementation Advice.
(8) The least change possible is just to make it clear that the bounded error
occurs when the second sentence's requirement is False.
(9) We define the term "by-reference primitives" (meaning those that have
anonymous access parameters or results, or aliased parameters) to simplify
whatever wording is chosen.
One option is that by-reference primitives "become" abstract when
inherited by a derived type with some different representation aspect. However,
that is incompatible with generics, since currently all operations are
available on a formal derived type inside a generic, even though all operations
are effectively inherited.
We also could have required such by-reference primitives to "require
overriding". However, the language currently does not require overriding for
any untagged type inheritance (meaning additional implementation burden), and
this also doesn't solve the problem for generics, since the original operations
"re-emerge" in a generic (overriding is purely a visibility effect for
untagged types).
Thus, the only reasonable solution is to be to go back to disallowing the
specification of a nonconfirming representation aspect if there are any
by-reference primitives. We considered folding the by-reference type rules
into this rule for a further simplification, but 4.6 (especially 4.6(58.2/4))
assumes that any related by-reference types can be converted without any
representation change. Perhaps we could change that, but doing so would cancel
out any simplification to 13.1.
(10) We want a Legality Rule as raising Program_Error is likely to have a
greater implementation burden than enforcing a Legality Rule, and it could
cause a hidden problem in a program that only occurs in unusual cases.
We choose to prevent declaring a problematic type. Other rules (such as
making calls on such inherited operations illegal or requiring overriding
of the operations) would have a much higher implementation burden, as we're
already enforcing similar rules (both this one and 13.1(10/5)).
We only need to disallow adding a Default_Value aspect. The rules in
6.4.1(5.1/5) through 6.4.1(5.4/4) only disallow cases where one type has
a Default_Value and the other doesn't, or where they both have it
but don't have a common ancestor. Clearly a derived type and its parent have
a common ancestor, and clearly you can't get rid of a Default_Value aspect
when you have it, so the only issue is adding a Default_Value aspect.
The choosen rule has the advantage that it could be compatibly relaxed in the
future (perhaps to "require overriding" of problematic operations), if it
proves to be a problem in practice. Other rules would probably require an
incompatible change to be made more friendly.
(11) We already have a minor issue if there is a parameterless function and
one with a single Integer parameter -- which one is used for Empty? This
change thus fixes that bug as well as the one mentioned in the !problem.
(12) It's likely easier for implementers if this permission applies to the
All_xxx_Checks as well as Known_xxx_Checks, as the former is then a more
pure superset of the latter.
[Editor's note: It is my contention that (assuming the All_xxx_Checks is
defined as intended), that this permission can never have an effect for an
All_xxx_Checks policy. Any case where later detection (such as in an instance)
could happen should have been illegal initially, as All_xxx_Checks is an
assume-the-worst rule -- it only allows things that are certain to not
conflict. So I don't see how the permission could possibly matter, since
anything that the permission could detect was already illegal. What might
help here would be the reverse permission -- that is, allowing not rejecting
code that can be proven safe in the All_xxx_Checks policies. But that clearly
is a bridge too far at this late date - whether the effect on portability is
acceptable would need lots of community input.]
(13) Indeed, the intent is that no enclosing quotes are passed to these
routines. That needed to be made explicit.
(14) All of the reasons that it is useful to have an aspect_specification on a
parallel loop (the ability to specify properties to an underlying scheduler
in particular) certainly apply to a parallel block.
(15) The reason for deferring names in a declaration is so that subprograms
and objects declared after a subprogram or type can be used in aspects
like preconditions and stream attributes. This is necessary for types as
one cannot declare a subprogram with a parameter of a type or an object of
a type before the type is declared (and is convenient in other declaration
cases). This need does not apply to statements and expressions, so we resolve
the aspect_definitions immediately.
(16) The term "attribute reference" is not defined, and as the !problem
states, it is not just an alternative for the syntax term
"attribute_reference". Defining a term for this probably would be preferable
for readability, but given the possibility of the definition introducing
new bugs, it is just too late in the definition of Ada 202x to do that.
So we use the more pedantic wording.
(17) Since "statically names" is defined to be equivalent to "statically
denotes" for entities that are not objects, we can use it without
qualification in 6.1.1(9/5).
Since 6.1.1(9/5) requires a global_name to statically name something,
we can require the same for static matching.
!corrigendum 3.5(56.4/3)
Replace the paragraph:
If a derived type with no primitive subprograms inherits a boolean Default_Value
aspect, the aspect may be specified to have any value for the derived type.
by:
If a derived type inherits a boolean Default_Value
aspect, the aspect may be specified to have any value for the derived type.
If a derived type T does not inherit a Default_Value aspect,
it shall not specify such an aspect if it inherits a primitive subprogram
that has a parameter of type T of mode out.
!corrigendum 3.6(22.2/3)
Replace the paragraph:
If a derived type with no primitive subprograms inherits a boolean
Default_Component_Value aspect, the aspect may be specified to have any value
for the derived type.
by:
If a derived type inherits a boolean Default_Component_Value
aspect, the aspect may be specified to have any value for the derived type.
!corrigendum 4.1.3(13.1/5)
Replace the paragraph:
For a prefixed view of a subprogram whose first parameter is an access parameter,
the prefix shall be legal as the prefix of an Access attribute reference.
by:
For a prefixed view of a subprogram whose first formal parameter is an access
parameter, the prefix shall be legal as the prefix an
attribute_reference with attribute_designator Access appearing as
the first actual parameter in a call on the unprefixed view of the subprogram.
!corrigendum 4.2.1(0)
Insert new clause:
See the conflict file for the changes.
!corrigendum 4.3.5(0)
Insert new clause:
See the conflict file for the changes.
!corrigendum 4.5.10(0)
Insert new clause:
See the conflict file for the changes.
!corrigendum 4.9.1(2/3)
Replace the paragraph:
A subtype statically matches another subtype of the same type if they have
statically matching constraints, all predicate specifications that apply to
them come from the same declarations, and, for access subtypes, either both or
neither exclude null. Two anonymous access-to-object subtypes statically match
if their designated subtypes statically match, and either both or neither
exclude null, and either both or neither are access-to-constant. Two anonymous
access-to-subprogram subtypes statically match if their designated profiles are
subtype conformant, and either both or neither exclude null.
by:
The Global or Global'Class aspects (see 6.1.2) of two entities statically
match if both consist of a single global_aspect_definition
where each is the reserved word null, or each is of the form
"global_mode global_designator" with each global_mode being the
same sequence of reserved words and each global_designator being the same
reserved word, or each being a global_name that statically names the
same entity.
A subtype statically matches another subtype of the same type if they have
statically matching constraints, all predicate specifications that apply to
them come from the same declarations, Nonblocking aspects have the same value,
global aspects statically match, Object_Size (see 13.3) has been specified
to have a nonconfirming value for either both or neither, and the nonconfirming
values, if any, are the same, and, for access subtypes, either both or
neither exclude null. Two anonymous access-to-object subtypes statically match
if their designated subtypes statically match, and either both or neither
exclude null, and either both or neither are access-to-constant. Two anonymous
access-to-subprogram subtypes statically match if their designated profiles are
subtype conformant, and either both or neither exclude null.
!corrigendum 4.10(0)
Insert new clause:
See the conflict file for the changes.
!corrigendum 5.6.1(0)
Insert new clause:
See the conflict file for the changes.
!corrigendum 6.1.2(0)
Insert new clause:
See the conflict file for the changes.
!corrigendum 8.5(5)
Delete the paragraph:
10 A task or protected object that is declared by an explicit
object_declaration can be renamed as an object. However, a single task
or protected object cannot be renamed since the corresponding type is
anonymous (meaning it has no nameable subtypes). For similar reasons, an
object of an anonymous array or access type cannot be renamed.
!corrigendum 8.6(17.1/5)
Replace the paragraph:
Within an aspect_specification for a type or subtype, the
current instance represents a value of the type; it is not an object. The
nominal subtype of this value is given by the subtype
itself (the first subtype in the case of a type_declaration), prior to
applying any predicate specified directly on the type or subtype. If the type
or subtype is by-reference, the associated object of the value is the
object associated (see 6.2) with the evaluation of the usage name.
by:
Within an aspect_specification for a type or subtype, the
current instance represents a value of the type; it is not an object. Unless
otherwise specified, the nominal subtype of this value is given by the subtype
itself (the first subtype in the case of a type_declaration), prior to
applying any predicate specified directly on the type or subtype. If the type
or subtype is by-reference, the associated object of the value is the
object associated (see 6.2) with the evaluation of the usage name.
!corrigendum 9.10.1(0)
Insert new clause:
See the conflict file for the changes.
!corrigendum 13.1(10/4)
Replace the paragraph:
For an untagged derived type, it is illegal to specify a type-related
representation aspect if the parent type is a by-reference type, or has any
user-defined primitive subprograms. Similarly, it is illegal to specify a
nonconfirming type-related representation aspect for an untagged
by-reference type after one or more types have been derived from it.
by:
A by-reference primitive is a user-defined primitive subprogram for a
type T that has an access result designating type T, or that has a
formal parameter that is an access parameter designating type T or is
aliased and of type T. It is illegal to specify a nonconfirming
type-related representation aspect for an untagged type T if it is
derived from a by-reference type or inherits one or more by-reference
primitives, or if one or more types have been derived from T prior to
the specification of the aspect and type T is a by-reference type or
defines one or more by-reference primitives that are inherited by these
descendants.
!corrigendum 13.1(13.1/3)
Insert after the paragraph:
A type_declaration is illegal if it has one or more progenitors, and a
nonconfirming value was specified for a representation aspect of an ancestor,
and this conflicts with the representation of some other ancestor. The cases
that cause conflicts are implementation defined.
the new paragraph:
When specifying an aspect that denotes a subprogram, the profile of the
subprogram shall be mode conformant with the one required for the aspect,
and the convention shall be Ada. Additional requirements are defined for
particular aspects.
!corrigendum 13.1.1(11/5)
Replace the paragraph:
The usage names in an aspect_definition are not resolved at the
point of the associated declaration, but rather are resolved at the
end of the immediately enclosing declaration list, or in the
case of the declaration of a library unit, at the end of the visible
part of the entity.
by:
The usage names in an aspect_definition associated with a declaration
are not resolved at the point of the associated declaration, but rather
are resolved at the end of the immediately enclosing declaration list,
or in the case of the declaration of a library unit, at the end of the visible
part of the entity.
!corrigendum 13.1.1(21/3)
Replace the paragraph:
- an expression, which is either evaluated to produce a single
value, or which (as in a precondition) is to be evaluated at
particular points during later execution; or
by:
- an expression (other than an aggregate), which is
either evaluated to produce a single value, or which (as in a precondition)
is to be evaluated at particular points during later execution;
!corrigendum 13.1.1(22/3)
Replace the paragraph:
- an identifier specific to the aspect.
by:
- an identifier specific to the aspect; or
- an aggregate, which is positional or named, and is composed
of elements of any of these four kinds of constructs.
!corrigendum 13.3(6)
Delete the paragraph:
For an attribute_definition_clause that specifies an attribute that
denotes a subprogram, the profile shall be mode conformant with the one
required for the attribute, and the convention shall be Ada. Additional
requirements are defined for particular attributes.
!corrigendum 13.13.2(51/3)
Replace the paragraph:
For an attribute_definition_clause specifying one of these attributes,
the subtype of the Item parameter shall be the first subtype or the base
subtype if scalar, and the first subtype if not scalar. The same rule applies
to the result of the Input function.
by:
For an attribute_definition_clause or aspect_specification
specifying one of these attributes, the subtype of the Item parameter
shall be the first subtype or the base subtype if scalar, and the first
subtype if not scalar. The same rule applies to the result of the Input
function.
!corrigendum B.3(65.1/5)
Replace the paragraph:
- An Ada enumeration type corresponds to a C enumeration type with
corresponding enumeration literals having the same internal codes,
provided the internal codes fall within the range of the C int type.
The Ada Boolean type corresponds to the C bool type.
by:
- An Ada enumeration type corresponds to a C enumeration type with
corresponding enumeration literals having the same internal codes,
provided the internal codes fall within the range of the C int type.
!ASIS
No ASIS effect.
!ACATS test
No ACATS Tests needed.
!appendix
From: Tucker Taft
Sent: Thursday, March 18, 2021 11:07 AM
Here is a comment that might best be considered as a "WG9-stage" comment
on the latest draft (#29.3) of the Ada 202X RM: [It was WG 9 issue #8, see
below - Editor.]
In RM 13.1.1(19/3-22/3) we have:
Depending on which aspect is identified by the aspect_mark, an
aspect_definition specifies:
* a name that denotes a subprogram, object, or other kind of entity;
* an expression, which is either evaluated to produce a single value, or
which (as in a precondition) is to be evaluated at particular points
during later execution; or
* an identifier specific to the aspect.
This is relatively old wording, and doesn't mention "aggregate" which is of
course a kind of expression, but in newer wording is called out separately,
and it is certainly misleading to talk about it being evaluated to produce
a "single value."
I would suggest we augment the above as follows:
Depending on which aspect is identified by the aspect_mark, an
aspect_definition specifies:
* a name that denotes a subprogram, object, or other kind of entity;
* an expression{ (other than an aggregate)}, which is either evaluated to
produce a single value, or which (as in a precondition) is to be evaluated
at particular points during later execution;[ or]
* an identifier specific to the aspect{; or
* an aggregate, which is positional or named, and is composed of elements of
any of these four kinds of constructs}.
****************************************************************
From: Randy Brukardt
Sent: Saturday, March 20, 2021 2:20 AM
I agree this should be fixed as you suggest. It looks like an oversight to me;
we made a similar fix to 13.1.1(5 through 11) and I'd guess we missed that
there was a second place that needed a fix.
****************************************************************
From: Tucker Taft
Sent: Thursday, March 18, 2021 11:31 AM
Randy suggested I bring this comment to the ARG as a WG9-stage comment.
We have added C_bool to Interfaces.C, which is defined to be equivalent to C's
"bool" (or "_Bool"). It now seems misleading to say that Ada's
Standard.Boolean type "corresponds" to the C bool type. The point of
introducing C_bool was so that you could be certain that you had a type
compatible with C, and there was no guarantee that, for example, a record
component of type Standard.Boolean would match a C struct component of type
"bool."
The current state of RM B.3(65.1/5) is
* An Ada enumeration type corresponds to a C enumeration type with
corresponding enumeration literals having the same internal codes,
provided the internal codes fall within the range of the C int type.
The Ada Boolean type corresponds to the C bool type.
That last sentence was not present when this paragraph was added, which
originated from AI12-0135-1. The last sentence came from AI12-0411-1, which
defined Interfaces.C.C_bool. I admit I wrote the original version of
AI12-041101, but now that last sentence seems to miss the whole point of the
addition of C_bool, namely, that there is no requirement that the Ada Boolean
type itself corresponds to the C bool type. It would make more sense to say
something like the following, I believe:
* An Ada enumeration type corresponds to a C enumeration type with
corresponding enumeration literals having the same internal codes,
provided the internal codes fall within the range of the C int type.
Interfaces.C.C_bool, a boolean type derived from the Standard.Boolean
type, corresponds to the C bool type.
We could also mark this new last sentence as "redundant" (i.e., inside [ ... ]
in the AARM) as it is implied by other wording now in the draft RM that says
that C_bool corresponds to C's bool, plus the declaration of C_bool to be
derived from Standard.Boolean.
****************************************************************
From: Jean-Pierre Rosen
Sent: Thursday, March 18, 2021 11:43 AM
> * An Ada enumeration type corresponds to a C enumeration type with
> corresponding enumeration literals having the same internal codes,
> provided the internal codes fall within the range of the C int type.
> Interfaces.C.C_bool, a boolean type derived from the
> Standard.Boolean type, corresponds to the C bool type.
>
Does it correspond to this sea bull?
https://www.alamy.com/stock-photo-greenland-sea-norway-svalbard-archipelago-spitsbergen-walrus-odobenus-55591858.html
****************************************************************
From: Tucker Taft
Sent: Thursday, March 18, 2021 12:15 PM
Of course the Sea Bull Walrus would let us know that...
The time has come,' the Walrus said,
To talk of many things:
Of shoes — and ships — and sealing-wax —
Of cabbages — and kings —
And why the sea is boiling hot —
And whether pigs have wings.'
And whether bool is C_Bool,
Or Standard dot Booling!
****************************************************************
From: Randy Brukardt
Sent: Saturday, March 20, 2021 2:18 AM
...
> I admit I wrote the original version of AI12-041101, but now that last
> sentence seems to miss the whole point of the addition of C_bool,
> namely, that there is no requirement that the Ada Boolean type itself
> corresponds to the C bool type.
I certainly agree with this, but I thought that we had that discussion at the
time and I lost (and the sentence remained). I certainly thought the intent
was as written -- this is Implementation Advice anyway, no one has to follow
it.
>It would make more sense to say something like the following, I believe:
>* An Ada enumeration type corresponds to a C enumeration type with
> corresponding enumeration literals having the same internal codes,
> provided the internal codes fall within the range of the C int type.
> Interfaces.C.C_bool, a boolean type derived from the Standard.Boolean
> type, corresponds to the C bool type.
I don't see any reason to mention Interfaces.C.C_bool here. We don't mention
any of the other Interfaces.C types in this Implementation Advice, because
they are already *normatively* corresponding (in B.3(43/5)). It makes no sense
to repeat that in IA - IA is weaker, after all.
>We could also mark this new last sentence as "redundant" (i.e., inside
>[ ... ] in the AARM) as it is implied by other wording now in the draft
>RM that says that C_bool corresponds to C's bool, plus the declaration
>of C_bool to be derived from Standard.Boolean.
I see no reason to mention it at all, as stated above. I thought people wanted
to encourage a correspondence between Boolean and the C bool type, otherwise
it should never have been there in the first place.
****************************************************************
From: Tucker Taft
Sent: Saturday, March 20, 2021 5:21 PM
I am happy to drop the problematic sentence completely. I had the sense that
Randy or someone else thought the sentence should be preserved, but if so, it
should not imply a direct correspondence between Ada Boolean and C bool, but
rather indicate the C_bool type, derived from Boolean, is required to
correspond. But that is definitely redundant with the update made to
B.3(43/5), so happy to leave it out completely.
****************************************************************
From the WG 9 review, issue #2.
Stream attributes define the subtype of the parameter of the associated
subprograms with 13.13.2(51/3). We don't have any similar rule for Put_Image
in 4.10. The definition of Put_Image seems to suggest that the parameter is
of type T, but types do not have names in Ada -- one always has to specify a
subtype.
Tucker also notes that we don't mention that the implicit calls of Put_Image
propagate any exceptions (including those caused by a subtype check
failure); we doubt anyone would expect anything else, but it usually is
explicitly mentioned in the RM.
****************************************************************
From the WG 9 review, issue #151.
8.5(5): This note says that an object of an anonymous access type cannot be
renamed. However, it seems to me that the second alternative in RM 8.5.1 (1/5),
the "access_definition" case, does allow such a renaming. Similarly, RM 8.5 (5)
says that a single task or protected object cannot be renamed since the
corresponding type is anonymous, but as we can now omit the subtype_mark from
the object_renaming_declaration, it seems that such entities can be renamed.
Either I am wrong, or the statements in RM 8.5 (5) are wrong.
Tucker Taft replied:
Another good catch! I would suggest we change the note to say:
10 A task or protected object that is declared by an explicit
object_declaration can be renamed as an object. However, a single task
or protected object [cannot]{can} be renamed {only using the form of
renaming that omits specifying the subtype} [since the corresponding type
is anonymous (meaning it has no nameable subtypes). For similar reasons,
an object of an anonymous array or access type cannot be renamed].
This is a bit informal (i.e. "specifying the subtype" is not a defined
technical notion) but that is generally fine for a "Note".
Your editor replied:
I wonder if this note retains enough value to bother with it at all. The
original purpose was to say that not all objects can be renamed, but that is
False with Ada 202x, and indeed one now can rename most values as well. Saying
that something can only be renamed with the most simple (and likely common)
form of renaming is hardly interesting. We don't need notes to tell people
random facts about the language.
I'll write up deleting the note in AI12-0427-1 (the fixup AI), and we can
decide if that is acceptable or not in the ARG.
****************************************************************
From the WG 9 review, issue #152.
The nominal (sub)type specified in 8.6(17.1/5) for the "current instance"
value seems to be overridden in RM 7.3.2 (5/4) for the aspect
Type_Invariant'Class, and in RM 7.3.3 (4/5) for the aspect
Default_Initial_Condition, where different types ("NT") are specified for
the current instance. Perhaps this apparent contradiction should be addressed
in some way, by a note or by an exception phrase in the general rule.
Tucker Taft replied:
Might want to add simply "Unless otherwise specified in this document, ...".
****************************************************************
From the WG 9 review, issue #8.
In RM 13.1.1(19/3-22/3) we have:
Depending on which aspect is identified by the aspect_mark, an
aspect_definition specifies:
* a name that denotes a subprogram, object, or other kind of entity;
* an expression, which is either evaluated to produce a single value, or
which (as in a precondition) is to be evaluated at particular points during
later execution; or
* an identifier specific to the aspect.
This is relatively old wording, and doesn't mention "aggregate" which is of
course a kind of expression, but in newer wording is called out separately,
and it is certainly misleading to talk about it being evaluated to produce a
"single value."
Suggested fix:
We should augment the above as follows:
Depending on which aspect is identified by the aspect_mark, an
aspect_definition specifies:
* a name that denotes a subprogram, object, or other kind of entity;
* an expression{ (other than an aggregate)}, which is either evaluated to
produce a single value, or which (as in a precondition) is to be evaluated
at particular points during later execution;[ or]
* an identifier specific to the aspect{; or
* an aggregate, which is positional or named, and is composed of elements of
any of these four kinds of constructs}.
****************************************************************
From the WG 9 review, issue #3.
The listed paragraphs give requirements on subprograms specified for
attributes (aspects) via an attribute_definition_clause. There is no rule
that does that for aspects specified via aspect_specifications.
There is a usual equivalence of aspects that can be specified via
aspect_specifications, and the Dewar rule applies here -- it would be highly
unusual for these rules to act differently than many others.
However, we have been trying to eliminate semantic rules that specifically
mention how some aspect/attribute is specified, since those can be misread
easily and are always confusing. So we believe these paragraphs should be
rewritten.
Note that if we do that for 13.3(6), it should be moved somewhere more
general (probably 13.1) as it currently is part of rules that only apply to
attribute_definition_clauses. (A reason this change should be made, IMHO -
RLB) Even language lawyers (for example, Steve Baird) have had difficulty
locating this rule when wondering what rules apply to a particular aspect.
****************************************************************
From the WG 9 review, issue #4.
3.5(56.4/3) says:
If a derived type with no primitive subprograms inherits a boolean
Default_Value aspect, the aspect may be specified to have any value for the
derived type.
Tucker tells me that the "with no primitive subprograms" was included to
ensure that we didn't override 13.1(10) with this rule. However, Ada 202x
removes the bulk of 13.1(10) (which mostly was intended to avoid expensive
implicit conversions -- but the effect was to prevent programmers from
writing derived types that they needed even if the expensive conversion was
not a problem). This means this rule as written is a wart, as it seems to
prevent non-confirming Default_Value aspects in the case of a type with
primitive subprograms.
3.6(22.2/3) has similar wording.
Suggested fix: drop the words "with no primitive subprograms" from both of
these rules.
****************************************************************
From the WG 9 review, issue #9.
[This is just a repeat of the ARG thread saved above, starting with a
message from Tucker Taft, Thursday, March 18, 2021 11:31 AM - Editor.]
****************************************************************
From the WG 9 review, issue #16.
In 4.5.10 (34/5) we have
"For a parallel reduction expression, it is a bounded error if the reducer
subprogram is not associative. That is, for any arbitrary values of subtype
Value_Type A, B, C and a reducer function R, the result of R (A, R(B, C))
should produce a result equal to R (R (A, B), C)). The possible consequences
are Program_Error, or a result that does not match the equivalent sequential
reduction expression due to the order of calls on the reducer subprogram
being unspecified in the overall reduction. Analogous rules apply in the
case of a reduction procedure."
The second sentence is misleading in that it is explaining what associative
means while the first sentence talks about being not associative. Maybe
better: "For any arbitrary values of subtype Value_Type A, B, C, an
associative reducer function R should guarantee that the result
of R (A, R(B, C)) is equal to R (R (A, B), C))."
In addition, it could be mentioned that addition and multiplication of
floating point numbers are prominent examples of not associative operations.
A fact that many programmers are not aware of.
****************************************************************
Editor's reply to the previous item:
We had a very hard time agreeing on wording for this one, so I would want to
change it as little as possible. As such, I suggest adding "; it is a bounded
error if R does not" to the end of the second sentence to provide the
clarification you are asking for, This was added to the fixups AI
(AI12-0427-1).
As far as the second suggestion is concerned, we don't want "fun facts" in the
normative rules of the Standard. I suppose it could be mentioned in the AARM
or a user note, but that seems to be of less value since it would be separated
from the reason it matters. So I'm not going to do anything with this second
point.
****************************************************************
From the WG 9 review, issue #114.
We have relaxed the rules relating to specifying type-related representation
aspects when there are primitives that might be inherited by derived types
with a different representation. However, we did not take into account that
some parameters are necessarily passed by reference, even if the type itself
is not a by-reference type. Such parameters cannot easily be converted
automatically when calling an inherited subprogram. One option is for such
"by-reference primitives" to "become" abstract when inherited by a derived
type with some different representation aspect. However, that is incompatible
with generics, since currently all operations are available on a formal
derived type inside a generic, even though all operations are effectively
inherited. After discussion, the simplest solution seems to be to go back to
disallowing the specification of a nonconfirming representation aspect if
there are any "by-reference primitives." Hence, I would suggest we modify
13.1(10/5) as follows:
Modify RM 13.1(10/5):
{A by-reference primitive is a user-defined primitive subprogram for a
type T that has an access result designating type T, or that has a formal
parameter that is an access parameter designating type T or is aliased and
of type T.} It is illegal to specify a nonconfirming type-related
representation aspect for an untagged [by-reference] type T if it is
derived from a by-reference type {or inherits one or more by-reference
primitives}, or if one or more types have been derived from T prior to
the specification of the aspect {and type T is a by-reference type or
defines one or more by-reference primitives that are inherited by these
descendants}.
{AARM Reason: Access parameters, access results, and aliased parameters
cannot be converted as part of invoking an inherited subprogram if the
representation of the designated types might be different.}
We could simplify this further, which would effectively relax the existing
rules for a by-reference type that has no primitives, to the following:
{A by-reference primitive is a user-defined primitive subprogram for a
type T, if T is a by-reference type, or if the primitive has an access
result designating type T, or has a formal parameter that is an access
parameter designating type T or is aliased and of type T.} It is illegal
to specify a nonconfirming type-related representation aspect for an
untagged [by-reference] type T if it [is derived from a by-reference
type] {inherits one or more by-reference primitives}, or if one or more
types have been derived from T prior to the specification of the aspect
{and type T defines one or more by-reference primitives that are
inherited by these descendants}.
In the spirit of removing unnecessary restrictions, this simpler rule might be
preferred.
[Later message]
Randy noted that we should probably not change the rules on by-reference
types, since in 4.6(58.2/4) we assume all by-reference types can be converted
without representation change. So that implies we should retain the
distinction as suggested in the first alternative proposed above.
****************************************************************
From the WG 9 review, issue #5.
[From Randy Brukardt:]
Paragraphs 6.4.1(5.1/5) through 6.4.1(5.4/4) define a Legality check for
some scalar view conversions passed to OUT mode parameters.
When a type is derived, any inherited subprograms are called with the actual
parameters of the new type view converted to the parent type. This can cause
an anomaly, in that an explicit call would be illegal while calling an
inherited routine (which makes the same call implicitly) is legal.
Tucker notes that 6.4.1(15.1/5) says that this view conversion raises
Program_Error. Therefore, there is no language bug in that code that does
not follow the principles cannot be executed. OTOH, the rule Tucker refers
to was only intended to be used in generic bodies (and there is an AARM note
to that effect). So implementers and users alike are likely to be confused.
Moreover, we have a Language Design Principle (admittedly, not always
followed) that a construct which will always raise an exception should be
detected at compile-time. So it seems that a Legality Rule is missing here.
Suggested fix: Add a Legality Rule to reject any call on an inherited
routine with an out parameter where the implied view conversion would be
illegal.
Example: Here is an example of this situation:
package P1 is
type Moddy is mod 2**16;
procedure Convert (Ival : in Integer; Mval : out Moddy);
end P1;
with P1;
package P2 is
type IModdy is new P1.Moddy
with Default_Value => 65535; -- [A]
-- Convert inherited here.
end P2;
with P1, P2;
procedure Tester is
V : P2.IModdy;
begin
P1.Convert (10, P1.Moddy(V)); -- [B]
P2.Convert (10, V); -- [C]
end Tester;
[C] is implemented as [B] -- 3.4(27/2).
But [B] is illegal by 6.4.1(5.1-4/5) -- the operand type has a Default_Value
and the target type does not.
The equivalence is only for Dynamic Semantics, so the Legality Rule does not
apply. But 6.4.1(15.1/5) does apply, so [C] is required to raise Program_Error.
[From Tucker Taft:]
It would perhaps be better to require such primitives to be overridden, since
having a primitive that is illegal to call might have cascading weird effects.
On the other hand, this only comes up with non-tagged types, so there is no
dispatching to worry about, and ancestor primitives re-emerge in a generic, so
perhaps I am merely sowing Fear, Uncertainty, and Doubt.
It still seems friendlier, though, to require overriding. You could of course
override with a subprogram that always raised Program_Error if so desired, but
at least you are being explicit about it.
[From Randy Brukardt:]
I didn't suggest requiring overriding, as that is something that currently
happens only for tagged types. As such, adding it for an unlikely case for
untagged types could be a substantial implementation burden. (If tagged
derivation is separately implemented from untagged derivation, then one would
need to implement a new mechanism for untagged types.) I do agree it would be
friendlier to a user, but only in unusual circumstances (and it would be
incompatible with Ada 2012 in those circumstances).
I don't think there would be any "cascading weird effects", as you note that
there isn't any effect in generics.
[From Tucker Taft:]
An alternative would be to add yet another restriction on applying a
representation clause to a type with primitives. It used to be completely
illegal, and now we are beginning to find out why... ;-) But at least we are
certain we are keeping all of the "hair" in the same place, namely, in
limiting how far we loosen this rule. I'll see if I can come up with wording
for the two different approaches -- disallowing the call, or disallowing the
representation change -- and I'll add it as another comment.
[From Randy Brukardt:]
It would seem weird to add something to 13.1(10/5) about a specific aspect
used with a specific kind of parameter - it doesn't seem general enough. But
I suppose we could have a wart rule in 3.5 specifically to disallow such
Default_Values. That seems less friendly than just disallowing uses of such
inherited routines, but it's probably not a huge issue either way.
[From Steve Baird:]
Given our recent discussion about inherited subprograms with
aliased untagged parameters, it sounds like we are already planning
on adding new cases to 13.1(10) for other reasons. So I would prefer
to address this problem there.
[From Tucker Taft:]
We are simplifying the current rule in 3.5, so perhaps we could make it more
complex again:
If a derived type [with no primitive subprograms] inherits a boolean
Default_Value aspect, the aspect may be specified to have any value for
the derived type. {If a derived type T does not inherit a Default_Value
aspect, it shall not specify such an aspect if it inherits a primitive
subprogram that has a parameter of type T of mode OUT.
AARM Reason: This is to avoid violating the rules specified in 6.4.1 about
view conversions of OUT parameters with a specified Default_Value aspect.}
The rules in 6.4.1(5.1/5) through 6.4.1(5.4/4) only disallow cases where one
type has the Default_Value and the other doesn't, or where they both have it
but don't have a common ancestor. Clearly a derived type and its parent have
a common ancestor, and clearly you can't get rid of a Default_Value aspect
when you have it, so the only issue is adding a Default_Value aspect.
[From Randy Brukardt:]
This rule has the advantage that it could be compatibly relaxed in the future
(perhaps to "require overriding"), if it proves to be a problem. Other rules
would probably require an incompatible change to be made more friendly.
****************************************************************
From the WG 9 review, issue #116.
4.2.1(7/5) says:
... The actual parameter of this notional call is a string_literal having
the textual representation of the original (numeric or string) literal.
Does the textual representation of a string literal include the quotes on
either end? And what about doubled quotation marks occurring in the middle?
Based on the example of Roman_Number, I would guess the answer is the
enclosing quotes are removed, and a doubled quotation mark becomes a single
quotation mark, but that is not clear from this rule. I would suggest the
following:
... The actual parameter of this notional call is a string_literal having
the textual representation of the original (numeric or string) literal{;
in the case of a string literal, the enclosing quotation marks from the
original textual representation are not included, and doubled quotation
marks in the textual representation are represented by a single quotation
mark in the actual parameter}.
---
On further thought, the string literal case to some extent makes more sense
than the numeric literal case. How can a string literal have the same textual
representation as a numeric literal? At a minimum it needs enclosing quotation
marks. I think part of the confusion here is that we are swinging between a
syntactic view and a semantic view, while not always being clear which one we
mean at any given time. So perhaps this should be changed as follows:
... The actual parameter of this notional call is a string_literal
{representing a sequence of characters that is the same as the sequence
of characters in the original numeric literal, or the sequence represented
by the original string} [having the textual representation of the original
(numeric or string)] literal.
****************************************************************
From the WG 9 review, issue #176.
AI12-0355-2 starts as follows:
All constructs that include the word "parallel" now permit an
aspect_specification as part of their syntax.
!problem
We need a mechanism to pass information through to a lightweight
parallelism scheduler. Something like an aspect specification might be a
good way to specify such options.
!proposal
We propose to add an aspect_specification to every place the PARALLEL
keyword is envisioned currently ...
In fact, we somehow missed the parallel block feature. All of the above logic
applies to a parallel block, so it makes sense to allow an aspect clause
there. Hence, 5.6.1(2/5) should probably be replaced with
parallel_block_statement ::=
parallel [aspect_specification] do
handled_sequence_of_statements
and
handled_sequence_of_statements
{and
handled_sequence_of_statements}
end do;
The "static semantics" section is mislabeled, and should be labeled "dynamic
semantics" (also mentioned by Issue #169). RM 5.6.1(3/5) should be updated as
follows:
{For the execution of a parallel_block_statement, the aspect_specification,
if any, is elaborated. Then every}[Each] handled_sequence_of_statements{,
each of which} represents a separate logical thread of control{,
executes}[ that proceeds] independently and concurrently. The
parallel_block_statement is complete once every one of the
handled_sequence_of_statements has completed, either by reaching the end
of its execution, or due to a transfer of control out of the construct by
one of the handled_sequence_of_statements (see 5.1).
****************************************************************
Inspired by the above:
All of this (incorrect) talk about visibility and resolution of aspect
specifications along with thinking about adding aspect_specifications to
parallel blocks (and other statements and expressions) caused me to wonder
about resolution in those aspect_specifications.
Specifically, 13.1.1(11/5) says:
The usage names in an aspect_definition are not resolved at the point of
the associated declaration, but rather are resolved at the end of the
immediately enclosing declaration list, or in the case of the declaration
of a library unit, at the end of the visible part of the entity.
What if this aspect_definition is part of an aspect_specification that's
in a loop or block or if statement etc??? What the heck declaration list
are we talking about -- the one enclosing the body is way too late and there
isn't one in the sequence_of_statements. (It's better for an
aspect_specification in an expression, such as an aggregate or quantified
expression, if that expression is part of some declaration, but it still
means resolution is mighty late. Of course, we have a rule - 13.1.1(13/3) -
that the resolution has to match at the freezing point of the declaration,
but how that applies to an expression that is only loosely tied to a
declaration isn't clear.)
I think we patched up the freezing rules for this statement/expression case
(yes, we did, see 13.14(7.2/5)), but not the resolution rules. Yikes!!
Am I right? Do we have a significant last minute issue here??
[Tucker Taft replied:]
I agree that we should limit the notion of "deferred" name resolution to cases
where we are talking about an aspect specification on a declaration. Hence:
Modify 13.1(11/5):
The usage names in an aspect_definition {associated with a declaration}
[Redundant: are not resolved at the point of the associated declaration, but
rather] are resolved at the end of the immediately enclosing declaration list,
or in the case of the declaration of a library unit, at the end of the visible
part of the entity.
****************************************************************
From the WG 9 review, issue #132 - Steve Baird.
We could quibble over 13.1/5 wording regarding "shall be legal as
the prefix of an Access attribute reference", since an Access
attribute reference normally occurs in some specific context
that, for example, defines its expected type. So it is, arguably at
least, not completely clear what this wording means.
[Randy suggests that this does indeed warrant some action, and that
the fix is easy.]
===
This also illustrates an RM consistency issue that should be
cleaned up at some point (but not now). Here we use the (good
& desirable) terminology "an Access attribute reference". At other places
in the RM (e.g., 6.1.1(8)), we use pedantic, contorted wording
like "an attribute_reference with attribute_designator Old".
That sort of thing should be replaced with "an Old attribute reference".
If it seems appropriate, we could add a definition saying that
an " attribute reference" is an attribute_reference
having the given attribute name as its attribute_designator. Or we
could decide that this is sufficiently obvious that it does not need
to be stated explicitly.
[Randy suggests either we should explicitly define this new term or
we should avoid the shorter terminology that I prefer. He doesn't like
using this shorter terminology without properly defining it. I'm
inclined to agree.]
[Tucker Taft responds:]
For the first part, I would suggest:
Modify 4.1.3(13.1/5):
For a prefixed view of a subprogram whose first {formal} parameter is an
access parameter, the prefix shall be legal as the prefix of an Access
attribute reference {appearing as the first actual parameter in a call on
the unprefixed view of the subprogram}.
[The Editor responds:]
The second part is easy to fix in this rule, just use the defined terminology:
Modify 4.1.3(13.1/5):
For a prefixed view of a subprogram whose first {formal} parameter is an
access parameter, the prefix shall be legal as the prefix of an
{an attribute_reference with attribute_designator} Access
[attribute reference] {appearing as the first actual parameter in a call on
the unprefixed view of the subprogram}.
No one is interested in spelunking the RM for other places where we use
inprecise terminology, and adding a term is too much at this point.
****************************************************************
From the WG 9 review, issue #142 - Steve Baird.
The statically matching rule for Global aspects (4.9.1(1.5/5) says
... or each is of the form “global_mode global_designator” with
the same sequence of reserved words.
But a global_designator can be a global_name, so it seems like we need
a requirement that corresponding global_names have to statically denote
the same entity, or something like that.
[Tucker Taft responds:]
I would suggest:
Modify 4.9.1(1.5/5)
The Global or Global'Class aspects (see 6.1.2) of two entities statically
match if both consist of a single global_aspect_definition where each is
the reserved word null, or each is of the form
“global_mode global_designator” with {each global_mode being} the same
sequence of reserved words {and each global_designator being the same
reserved word, or each being a global_name that statically denotes the
same entity}.
****************************************************************
From: Tucker Taft
Sent: Monday, May 31, 2021 11:14 AM
Item (14) of this AI proposes the wording change to parallel blocks given
below, to include an aspect_specification, as with all other parallel
constructs. I realized as I have been putting together a tutorial on the
various Ada 2022 parallel constructs for Ada-Europe, that we should also
include a chunk count for a parallel block, as we have for essentially all
other parallel constructs. This is because a typical recursive divide and
conquer parallel algorithm will want to use a parallel block, but will also
want to control the number of logical threads spawned to handle the parallel
block, as the nesting of recursion increases. The easiest way to do this
programmatically is to have the chunk count go to one once sufficient
parallelism has been produced, or the problem has gotten sufficiently small.
Note that in OpenMP there is always an ability to turn off further parallelism
under similar circumstances, by having such a limit on the number of threads
devoted to the construct. As part of adding the aspect_specification to a
parallel_block_statement, it makes sense to include a chunk_specification,
but with the same restriction as is present for a parallel reduction, namely
that the chunk_specificaiton is required to be an integer simple_expression
(i.e. no named chunk parameter).
Below I first give the wording change as initially proposed by AI12-0427-1,
and then an alternative, which includes the chunk_specification.
=====================
Here is the proposal from AI12-0427-1:
(14) Replace 5.6.1(2/5) with:
parallel_block_statement ::=
parallel [aspect_specification] do
handled_sequence_of_statements
and
handled_sequence_of_statements
{and
handled_sequence_of_statements}
end do;
Modify 5.6.1(3/5):
{For the execution of a parallel_block_statement, the aspect_specification,
if any, is elaborated. Then every}[Each] handled_sequence_of_statements{,
each of which} represents a separate logical thread of control{,
executes}[ that proceeds] independently and concurrently. The
parallel_block_statement is complete once every one of the
handled_sequence_of_statements has completed, either by reaching the end
of its execution, or due to a transfer of control out of the construct by
one of the handled_sequence_of_statements (see 5.1).
====
And here is what I would now recommend:
(14) Replace 5.6.1(2/5) with:
parallel_block_statement ::=
parallel [(chunk_specification)] [aspect_specification] do
handled_sequence_of_statements
and
handled_sequence_of_statements
{and
handled_sequence_of_statements}
end do;
The chunk_specification, if any, of a parallel_block_statement shall be an
/integer_/simple_expression.
Modify 5.6.1(3/5):
{For the execution of a parallel_block_statement, the chunk_specification
and the aspect_specification, if any, are elaborated in an arbitrary order.
Then every}[Each] handled_sequence_of_statements{, each of which can}
represent[s] a separate logical thread of control{ (up to the maximum
specified by the value of the chunk_specification, if any), executes}[ that
proceeds] independently and concurrently{, again, up to the maximum if
specified}. The parallel_block_statement is complete once every one of the
handled_sequence_of_statements has completed, either by reaching the end
of its execution, or due to a transfer of control out of the construct by
one of the handled_sequence_of_statements (see 5.1).
****************************************************************
From: Randy Brukardt
Sent: Friday, June 4, 2021 11:47 PM
I noticed some minor problems with the rewording of 5.6.1(3/5) in AI12-0427-1.
A summary of a private thread between Tucker and I is given below.
We intend to process this rewording of the rewording as an Editorial Review
change. It is a bit of a stretch for that (the missing check represents added
semantics, even if obviously missing semantics). Therefore, if anyone wants to
request a Letter Ballot on this change (essentially, objecting to handling
this as an Editorial Review change), please speak up ASAP.
Summary of private thread:
From Randy Brukardt:
We have in 5.6.1(3/5):
{For the execution of a parallel_block_statement, the chunk_specification
and the aspect_specification, if any, are elaborated in an arbitrary order.
Then every}[Each] handled_sequence_of_statements{, each of which can}
represent[s] a separate logical thread of control{ (up to the maximum
specified by the value of the chunk_specification, if any), executes}[ that
proceeds] independently and concurrently{, again, up to the maximum if
specified}. The parallel_block_statement is complete once every one of the
handled_sequence_of_statements has completed, either by reaching the end
of its execution, or due to a transfer of control out of the construct by
one of the handled_sequence_of_statements (see 5.1).
I won't mention the department of redundancy department repeat of the maximum
(there's nothing like it in the loop wording).
But two things seem to be missing here:
First, how do the limbs of a parallel block execute if there aren't enough
logical threads of control for all of them? Previously, there always were
enough logical threads, and they could be mapped to physical threads
however the implementation wished. But now we seem to have a limit on the
number of logical threads, and we never say anything about how a limb
executes if it doesn't have a thread.
Second, for loops have a check to ensure that the number of chunks is
positive (see 5.5(8.1/5)). This is implied (very weakly!!) for reduction
expressions via the references to 5.5 in 4.5.10(20-21/5). But we have no
such check here, nor even a way to hand-wave a check via a reference to
the check in 5.5.
So, what happens with
parallel (-2) do
...
end do;
One would hope this raised Program_Error like a loop would. But why??
From Tucker Taft:
> First, how do the limbs of a parallel block execute if there aren't
> enough logical threads of control for all of them?
My intent was that they execute independently and concurrently only if we
stay within the maximum. Otherwise, they execute sequentially. But I agree
that my attempt to avoid complete rewrite was doomed.
...
>One would hope this raised Program_Error like a loop would. But why??
Agreed, we should be consistent here.
Here is my attempt. I have given up on using {} and [] to indicate what is
new and what is pre-existing. I have dropped the "handled_" part ;-)
Replace 5.6.1(3/5) with:
For the execution of a parallel_block_statement, the chunk_specification
and the aspect_specification, if any, are elaborated in an arbitrary order.
The various
sequence_of_statements are grouped into one or more /chunks/, each with
its own logical thread of control (see clause 9), up to the maximum number
of chunks specified by the chunk_specification, if any. Within each chunk
every sequence_of_statements of the chunk is executed in turn, in an
arbitrary order. The parallel_block_statement is complete once every one
of the sequence_of_statements has completed, either by reaching the end of
its execution, or due to a transfer of control out of the construct by one
of the sequence_of_statements (see 5.1). After elaborating the
chunk_specification, if any, a check is made that the determined maximum
number of chunks is greater than zero. If this check fails, Program_Error
is raised.
****************************************************************
From: Jeff Cousins
Sent: Saturday, June 5, 2021 2:29 AM
Shouldn't last two sentences of the new wording come after the first sentence?
****************************************************************
From: Randy Brukardt
Sent: Sunday, June 6, 2021 12:53 AM
I wondered that, too. I eventually concluded it didn't matter that much, but
the loop wording uses two separate paragraphs. Here, that would look something
like:
Replace 5.6.1(3/5) with:
For the execution of a parallel_block_statement, the chunk_specification
and the aspect_specification, if any, are elaborated in an arbitrary order.
After elaborating the chunk_specification, if any, a check is made that the
determined maximum number of chunks is greater than zero. If this check
fails, Program_Error is raised.
Then, the various sequence_of_statements are grouped into one or more
/chunks/, each with its own logical thread of control (see clause 9), up to
the maximum number of chunks specified by the chunk_specification, if any.
Within each chunk every sequence_of_statements of the chunk is executed in
turn, in an arbitrary order. The parallel_block_statement is complete once
every one of the sequence_of_statements has completed, either by reaching
the end of its execution, or due to a transfer of control out of the
construct by one of the sequence_of_statements (see 5.1).
Not certain if this is better, but it's more consistent with the wording for
the parallel loops. Agree? Disagree? Don't care? ;-)
****************************************************************
From: Jeff Cousins
Sent: Sunday, June 6, 2021 2:38 AM
That seems much better to me. Otherwise we might need another AI later to
clarify the order in which things happen (as with 343).
****************************************************************
From: Tullio Vardanega
Sent: Sunday, June 6, 2021 7:52 AM
I agree this way is more consistent with the related wording.
****************************************************************
From: Tucker Taft
Sent: Sunday, June 6, 2021 8:15 AM
Fine with me.
****************************************************************
Questions? Ask the ACAA Technical Agent