Version 1.2 of ai05s/ai05-0054-2.txt
!standard 3.3(13) 07-10-24 AI05-0054-2/02
!standard 13.9.1(13)
!class binding interpretation 07-10-24
!status work item 07-10-24
!status received 07-10-24
!priority Low
!difficulty Hard
!qualifier Omission
!subject Variable views of constant objects
!summary
Remove erroneousness associated with using access-to-variable
values designating constants, so long as they originate at a
point where the language provides a variable view of the constant.
Revise the definition of constant objects and views to make it clear
that there always is a possibility of a variable view existing.
!question
The current instance of a limited type can be used to obtain
a variable aliased view of a (limited) constant object.
Are runtime checks needed in order to prevent the
modification of a constant?
!recommendation
No, the practice of obtaining such a variable aliased view during
initialization is an existing idiom, and should be allowed to continue
even if the object is declared constant. (See the discussion section
for more rationale.)
!wording
Modify 3.3(13) as follows:
An object is either a constant object or a variable
object. [The value of a constant object cannot be changed
between its initialization and its finalization, whereas
the value of a variable object can be changed.] Similarly,
a view of an object is either a constant or a variable.
[All views of a constant object are constant.] {A name
that statically denotes a constant object is a constant
view. A name that statically denotes a variable object
is a variable view.} A constant view of [a variable]
{an} object cannot be used to modify [the value of the
variable] {its value}. The terms constant and variable
by themselves refer to constant and variable views of objects.
Modify 13.9.1(13) as follows:
The dereference of an access value is erroneous if it does not
designate an object of an appropriate type or a subprogram with
an appropriate profile, if it designates a nonexistent object,
or if it is an access-to-variable value that designates a
constant object{ and it did not originate from an attribute_
reference applied to a variable view of the object}.
[Redundant: [Such an]{An} access value {whose dereference is
erroneous} can exist, for example, because of Unchecked_Deallocation,
Unchecked_Access, or Unchecked_Conversion.]
AARM NOTE: We permit the use of access-to-variable values
that designate constant objects so long as they originate
from a variable view, such as during the
initialization of a limited or controlled constant, when
there exists a variable view of the object.
!discussion
It is always possible for an object that is declared constant to internally
contain an access-to-variable component that designates a separate
heap resident object, meaning that operations on the constant object
can still change the state of the "overall" object.
If we were to outlaw the idiom of squirreling away an access-to-variable
value during the initialization of a constant (the so-called
"Rosen" trick), then the programmer would be forced to allocate
a separate object in the heap to hold data that needs to be updatable.
This would not provide obvious benefit to anyone, since the code
would be slower, take more space, and still have exactly the same
external interface, namely that an operation can change the state of a
"constant."
One could argue this would be confusing for non-private types,
since potentially visible components of a constant might be
updatable, but if the type is non-private, then the semantics of its
initialization should certainly be considered open to inspection
as well, and the squirreling away of the access-to-variable value
should be available for all to see.
We use the phrase "originate from an attribute_reference applied to
a variable view" to allow for possible type conversions after
the initial '[Unchecked_]Access that created the access-to-variable
value. Hopefully that is clear enough. The key thing is that
you have to have a variable view at some point, or else somebody
cheated.
!ACATS test
There should be C-Tests that an access-to-variable view of a constant object
works properly.
!appendix
From: Tucker Taft
Sent: Wednesday, October 24, 2007 11:26 AM
I have attached variant 2 of AI-54 [this is version /01 of the AI - ED.],
the AI dealing with the erroneousness of using an access-to-variable
value designating a constant object. This variant
proposes to eliminate the erroneousness, so long
as the value originated from an attribute_reference
applied to a variable view of the constant.
Such a variable view is provided during initialization
for limited and controlled objects.
The basic point is that this is an existing idiom,
and that disallowing it would just force programmers
to allocate a separate heap object to hold data
that needs to be updatable, which doesn't do anybody
any favors, since you still have the same external
interface, namely that an operation can apparently change
the "state" of a constant.
****************************************************************
From: Randy Brukardt
Sent: Wednesday, October 24, 2007 8:26 PM
Thanks for doing this.
I'm concerned that your AI doesn't cover tasks. Obviously, tasks in constants is a
new concept, and it seems that we don't have an allowance for that.
task type T is
entry Set (A : in Integer);
entry Get (A : out Integer);
end T;
task body T is
Val : Integer := 0;
begin
loop
select
accept Set (A : in Integer) do
Val := A;
end Set;
or
accept Get (A : out Integer) do
A := Val;
end Get;
end select;
end loop;
end T;
type Lim is limited record
Tsk : T;
end record;
procedure Do_It (Obj : in Lim) is
begin
Obj.Tsk.Set (10);
end Do_It;
procedure Check_It (Obj : in Lim) is
V : Integer;
begin
Obj.Tsk.Get (V);
if V /= 10 then raise Program_Error; end if;
end Check_It;
declare
Obj : constant Lim := (Tsk => <>);
begin
Do_It (Obj);
Check_It (Obj);
end;
The call to Do_It causes a modification to the local data of the task Obj.Tsk, which is
a part of a constant. This surely seems to violate 3.3(13/2) "The value of a constant
object cannot be changed." (one presumes that the local values of a task are part of
the value of an object containing that task).
There doesn't seem to be any penalty for this violation, so maybe it is safe to ignore it,
but it seems odd at best.
****************************************************************
From: Tucker Taft
Sent: Wednesday, October 24, 2007 9:24 PM
> I'm concerned that your AI doesn't cover tasks. Obviously, tasks in
> constants is a new concept, and it seems that we don't have an allowance for
> that.
I'm pretty surprised you are worried about this.
It has been possible to call entries of task "IN"
parameters since Ada 83, so I presumed we never
considered the local variables of a task body
as part of the "value" of a task object.
> ...
>
> The call to Do_It causes a modification to the local data of the task
> Obj.Tsk, which is a part of a constant. This surely seems to violate
> 3.3(13/2) "The value of a constant object cannot be changed."
Well that isn't quite what 3.3 says, it says you can't
change the value between its initialization and its
finalization. In any case, I think this is clearly
violated by the "Rosen" trick applied to a constant.
I think this AI needs to fix this paragraph as well.
Perhaps as follows:
An object is either a constant object or a variable
object. [The value of a constant object cannot be changed
between its initialization and its finalization, whereas
the value of a variable object can be changed.] Similarly,
a view of an object is either a constant or a variable.
[All views of a constant object are constant.] {A name
that statically denotes a constant object is a constant
view. A name that statically denotes a variable object
is a variable view.} A constant view of [a variable]
{an} object cannot be used to modify [the value of the
variable] {its value}. The terms constant and variable
by themselves refer to constant and variable views of objects.
The net effect is that "constant object" isn't a very
interesting term. It basically means that its name
denotes a constant view, but that there might be other
views that provide a variable view of the same object.
> ... (one presumes
> that the local values of a task are part of the value of an object
> containing that task).
I don't make that presumption, and haven't since Ada 83.
Perhaps a NOTE to that effect might be friendly.
****************************************************************
From: Randy Brukardt
Sent: Wednesday, October 24, 2007 9:26 PM
> > I'm concerned that your AI doesn't cover tasks. Obviously, tasks in
> > constants is a new concept, and it seems that we don't have an allowance for
> > that.
>
> I'm pretty surprised you are worried about this.
> It has been possible to call entries of task "IN"
> parameters since Ada 83, so I presumed we never
> considered the local variables of a task body
> as part of the "value" of a task object.
An "in" parameter is a constant view of a variable object. I'm thinking about
constant objects; recall that 3.3(13/2) says that all views of a constant object
are constant. There's no variable view existing anywhere, and that's what's
different. Maybe it's hair-splitting.
> > ...
> >
> > The call to Do_It causes a modification to the local data of the task
> > Obj.Tsk, which is a part of a constant. This surely seems to violate
> > 3.3(13/2) "The value of a constant object cannot be changed."
>
> Well that isn't quite what 3.3 says, it says you can't
> change the value between its initialization and its
> finalization. In any case, I think this is clearly
> violated by the "Rosen" trick applied to a constant.
> I think this AI needs to fix this paragraph as well.
> Perhaps as follows:
>
> An object is either a constant object or a variable
> object. [The value of a constant object cannot be changed
> between its initialization and its finalization, whereas
> the value of a variable object can be changed.] Similarly,
> a view of an object is either a constant or a variable.
> [All views of a constant object are constant.] {A name
> that statically denotes a constant object is a constant
> view. A name that statically denotes a variable object
> is a variable view.} A constant view of [a variable]
> {an} object cannot be used to modify [the value of the
> variable] {its value}. The terms constant and variable
> by themselves refer to constant and variable views of objects.
>
> The net effect is that "constant object" isn't a very
> interesting term. It basically means that its name
> denotes a constant view, but that there might be other
> views that provide a variable view of the same object.
That would satisfy my concern.
> > ... (one presumes
> > that the local values of a task are part of the value of an object
> > containing that task).
>
> I don't make that presumption, and haven't since Ada 83.
> Perhaps a NOTE to that effect might be friendly.
Well, they certainly aren't part of the enclosing object in our implementation.
But I can't find anything in the language semantics that says that. Just
because we all think something is true does not make it true!
But I do prefer your rewording of 3.3(13/2), because it will help avoid
misconceptions.
****************************************************************
From: Tucker Taft
Sent: Wednesday, October 24, 2007 11:08 PM
>> I'm pretty surprised you are worried about this.
>> It has been possible to call entries of task "IN"
>> parameters since Ada 83, so I presumed we never
>> considered the local variables of a task body
>> as part of the "value" of a task object.
>
> An "in" parameter is a constant view of a variable object. I'm thinking
> about constant objects; recall that 3.3(13/2) says that all views of a
> constant object are constant. There's no variable view existing anywhere,
> and that's what's different. Maybe it's hair-splitting.
But the more fundamental part of 3.3 is the part that
says you can't use a constant view to modify an object.
But you *can* call an entry on a constant view of a task
object (even in Ada 83), so clearly calling an entry is
*not* considered "modifying" a task object. Hence the
local variables of a task body must clearly not be
considered part of the "value" of a task object. I don't
think we need any hand waving to prove that, based on
semantics that have existed since Ada 83.
>>> ...
>>>
>>> The call to Do_It causes a modification to the local data of the task
>>> Obj.Tsk, which is a part of a constant. This surely seems to violate
>>> 3.3(13/2) "The value of a constant object cannot be changed."
>> Well that isn't quite what 3.3 says, it says you can't
>> change the value between its initialization and its
>> finalization. In any case, I think this is clearly
>> violated by the "Rosen" trick applied to a constant.
>> I think this AI needs to fix this paragraph as well.
>> Perhaps as follows:
>>
>> An object is either a constant object or a variable
>> object. [The value of a constant object cannot be changed
>> between its initialization and its finalization, whereas
>> the value of a variable object can be changed.] Similarly,
>> a view of an object is either a constant or a variable.
>> [All views of a constant object are constant.] {A name
>> that statically denotes a constant object is a constant
>> view. A name that statically denotes a variable object
>> is a variable view.} A constant view of [a variable]
>> {an} object cannot be used to modify [the value of the
>> variable] {its value}. The terms constant and variable
>> by themselves refer to constant and variable views of objects.
>>
>> The net effect is that "constant object" isn't a very
>> interesting term. It basically means that its name
>> denotes a constant view, but that there might be other
>> views that provide a variable view of the same object.
>
> That would satisfy my concern.
Glad to hear it.
>
>>> ... (one presumes
>>> that the local values of a task are part of the value of an object
>>> containing that task).
>> I don't make that presumption, and haven't since Ada 83.
>> Perhaps a NOTE to that effect might be friendly.
>
> Well, they certainly aren't part of the enclosing object in our
> implementation. But I can't find anything in the language semantics that
> says that. Just because we all think something is true does not make it
> true!
No, but see my rationale given above.
****************************************************************
From: Jean-Pierre Rosen
Sent: Thursday, October 25, 2007 7:27 AM
> The call to Do_It causes a modification to the local data of the task
> Obj.Tsk, which is a part of a constant. This surely seems to violate
> 3.3(13/2) "The value of a constant object cannot be changed." (one presumes
> that the local values of a task are part of the value of an object
> containing that task).
>
> There doesn't seem to be any penalty for this violation, so maybe it is safe
> to ignore it, but it seems odd at best.
Well, a constant can include a pointer to a variable, whose value can
also be changed. Not exactly the same thing, but I think close enough
that we don't have to care about it.
****************************************************************
Questions? Ask the ACAA Technical Agent