!standard 3.3(11.1/3) 18-06-10 AI12-0226-1/03
!standard 3.3(21.1/3)
!standard 3.3(23.8/5)
!standard 4.6(58.1/4)
!standard 4.6(58.3/4)
!class Amendment 17-04-18
!status Amendment 1-2012 18-07-10
!status ARG Approved 7-1-2 18-06-23
!status work item 17-04-18
!status received 17-03-23
!priority Low
!difficulty Easy
!subject Make objects more consistent
!summary
A value conversion of an object is an object in order to be consistent with
a qualified expression.
!problem
Ada 2012 made a qualified expression a "name", and a qualified expression of
an object is an object. This created an unusual situation where a single
character makes a difference between constructs usually considered equivalent:
Max : constant Natural := 10;
Ren1 : Natural renames Max; -- Legal.
Ren2 : Natural renames Natural'(Max);-- Legal, object.
Ren3 : Natural renames Natural(Max); -- Illegal, not object. (A value
-- conversion is not an object.)
We can make qualified expression and value conversion be more regular.
!proposal
(See Summary.)
!wording
[The definition of object:]
Modify 3.3(11.1/3):
* a {value conversion or }qualified_expression whose operand denotes an object;
[The definition of constants:]
Modify 3.3(21.1/3):
* the result of evaluating a {value conversion or }qualified_expression;
[The definition of known to be constrained:]
Modify 3.3(23.8/5):
* it is a {value conversion or }qualified_expression where the operand denotes
a view of a composite object that is known to be constrained; or
Modify 4.6(58.1/4):
Evaluation of a value conversion [of a composite type]{of an object} either
creates a new anonymous object Redundant[(similar to the object
created by the evaluation of an aggregate or a function call)] or
yields a new view of the operand object without creating a new object:
Add after 4.6(58.3/4):
If the target type is an elementary type, then a new object is created;
Add after AARM 4.6(58.b.1/4):
AARM Implementation Note: The new temporary object need not be materialized
in most cases; it should be handled like the return object of a predefined
operator. Generally, whether the object exists can only be detected if it
is renamed (unless the type is controlled).
AARM Discussion: This set of rules does not apply in those cases where the
operand is not an object (such as a value conversion of a named
number); in such cases, the result isn't an object, so it isn't necessary
to describe what that means. The rules cover all value conversions of
composite types (since there aren't any separate values of composite types).
!discussion
A value conversion looks much like a function call and similar to a qualified
expression, both of which represent objects (the latter only if the expression
is already an object). Therefore, we treat it consistently and make it an
object as well. Note that most of the needed wording was already added by
AI12-0027-1. We expect that compilers will materialize this temporary object
only when it is required, as is typically done for the result object of
predefined operators.
We made value conversions consistent with qualified expressions in the wording
above, but we could have made them consistent with function calls instead.
The wording differences are minimal (drop "new value," and the associated
AARM discussion from 4.6(58.1/4), and put "value conversion" with function
call rather than qualified expression in 3.3 [two places]). The difference can
be seen when renaming uses of named numbers:
Limit : constant := 12;
function Func (A : Natural) return Natural ...
RenA : Natural renames Natural'(Limit); -- Illegal, not object.
RenB : Natural renames Natural(Limit); -- (A)
RenC : Natural renames Func(Limit); -- OK, object by Ada 95.
(A) is illegal with the wording as suggested, and would be legal with the more
general wording mentioned here. With either wording in this AI, all three
would be legal if Limit had been a constant object (if a subtype had been
given in the declaration).
We also considered making the result of a parenthesized object an object,
so that parenthesized expressions and qualified expressions have the same
static semantics. However, since a parenthesized object should be considered
a constant and is not syntactically a name, there does not appear to be any
places where such a construct could be used.
A more general fix would be to eliminate the distinctions between "name" and
"expression" as well as "object" and "value", but that would require extensive
surgery to the Standard, so it is is not simple and is covered in a separate
AI - AI12-0270-1.
!corrigendum 3.3(11/3)
@drepl
@xbullet whose operand denotes an object;>
@dby
@xbullet whose operand
denotes an object;>
!corrigendum 3.3(21/3)
@drepl
@xbullet;>
@dby
@xbullet;>
!corrigendum 3.3(23.7/3)
@dinsa
@xbullet or
@fa; or>
@dinst
@xbullet where the
operand denotes a view of a composite object that is known to be constrained; or>
!corrigendum 4.6(58.1/4)
@drepl
Evaluation of a value conversion of a composite type either
creates a new anonymous object (similar to the object
created by the evaluation of an @fa or a function call) or
yields a new view of the operand object without creating
a new object:
@dby
Evaluation of a value conversion of an object either
creates a new anonymous object (similar to the object
created by the evaluation of an @fa or a function call) or
yields a new view of the operand object without creating
a new object:
!corrigendum 4.6(58.3/4)
@dinsa
@xbullet
@dinst
@xbullet
!ASIS
[Probably not, but not certain - Editor.]
!ACATS test
An ACATS C-Test is needed to check that the new capabilities are supported.
!appendix
[The following thread is forked from the discussion filed in AI12-0225-1.]
From: Randy Brukardt
Sent: Thursday, March 23, 2017 7:46 PM
> I just think the distinction between objects and values is lost on
> many users, and we allow 'Last, 'First, etc., on names that denote
> array values, so why not allow 'Image on names that denote scalar
> values.
I tend to agree with this sentiment. Particularly the first part, because given
the various changes in Ada 95 and Ada 2012, that distinction is lost on many Ada
language lawyers as well. I for one can detect no reason for what is an object
and what is a value in Ada 2012. More in a moment.
...
> X'Image is meant to be equivalent to
> 'Image(X), and clearly in this latter form, X can denote a
> value rather than an object. If we restrict a name in some context to
> denote an "object," it really ought to be something that relies on a
> memory cell of some sort to exist, such as 'Address, 'Size, or
> 'Alignment.
But in Ada 2012, almost everything is an object. The only expressions that are
never objects in Ada 2012 + TC1 are numeric and access literals, named numbers,
value conversions of elementary types, membership tests, short circuit control
forms, some attributes, and parenthized expressions. Why those particular things
are values, but things like logical operators, qualifications of objects, and
even the discrete Pos attribute deliver objects is beyond my understanding.
Consider object renaming, which like the name says, requires an object.
Ren1 : Natural renames Natural'(1); -- Illegal, not object.
Ren2 : Natural renames Natural'(+1); -- Legal, "+1" is equivalent to a function call "+"(1), and the
-- result object of a function call is clearly an object [3.3(13)].
Ren3 : Natural renames Natural(+1); -- Illegal, not object (value conversion isn't an object).
Ren4 : Natural renames Natural'First;-- Illegal, not object.
Ren5 : Natural renames Natural'Val(1); -- Legal, object. (Val denotes a function.)
Ren6 : Boolean renames Boolean'(A and B); -- Legal, object. ("and" is a function.)
Ren7 : Boolean renames Boolean'(A and then B); -- Illegal, not object ("and then" is an operation, not a function.)
I have to wonder if it would make more sense to clean up this mess rather than
bothering to change any attributes. After all, the fact that function calls
return objects don't suddenly make compilers stick every scalar intermediate
value into memory -- a compiler only materializes the return object if it
matters (as in the legal renamings above).
In particular, value conversion of composite types now (optionally in some
cases) creates an anonymous object, that was to fix a problem someone reported
caused by the accessibility of components of by-reference types when the actual
is a value conversion. (One guess as to which someone would care about that
case.) A tiny bit of additional wording and we could have an object for all
value conversions. (Doing that alone would get rid of the Image case that I was
most concerned about - the bizarre difference between Ren2 and Ren above.)
...
****************************************************************
From: Jeff Cousins
Sent: Tuesday, March 28, 2017 8:21 AM
> Consider object renaming, which like the name says, requires an object.
>
> Ren1 : Natural := Natural'(1); -- Illegal, not object.
> Ren2 : Natural := Natural'(+1); -- Legal, "+1" is equivalent to a function call "+"(1), and the
> -- result object of a function call is clearly an object [3.3(13)].
This is probably worth a new thread. It's certainly the kind of thing that gets
new Ada programmers tearing their hair out.
****************************************************************