Version 1.1 of ai05s/ai05-0053-1.txt
!standard G.3.1 07-05-15 AI05-0053-1/01
!class binding interpretation 07-05-15
!status work item 07-05-15
!status received 07-05-07
!subject Aliased views of unaliased objects
An extended return statement can be used to obtain an aliased view
of an unaliased object.
This introduces a number of problems.
How are these problems to be resolved?
Not clear. Ban aliased return objects? See discussion for ideas.
Consider the case where an extended return statement
includes the reserved word "aliased" and the function is
called to initialize an unaliased object in place,
either as required by 7.5(8.1/2) or as allowed by 7.6(21/2).
If an implementation wants to treat aliased objects differently
than unaliased objects in some way, then an aliased view of
an unaliased object can be problematic.
An optimizer might wish to assume that an assignment through an
access value does not "kill" any information that is known about
the value of an unaliased object.
If this were the only problem, then this might be resolved via a
"clarification" stating that if an aliased view of an unaliased
object is used as the prefix of an Unchecked_Access attribute,
then the resulting access value is valid only for the lifetime of
the aliased view (which will typically be shorter than the lifetime
of the designated object).
This "clarification" seems like a good idea, but unfortunately
it does not solve all of the problems in this area.
For example, the IBM/Rational Ada compiler implements an aliased
object X whose nominal subtype is an unconstrained array subtype
by storing a contiguous dope vector. This is needed in order to
support the evaluation of X'Access in the case where the designated
type of the access type is unconstrained.
In the case of an unaliased object, no storage is allocated for a
contiguous dope vector.
This implementation model worked for Ada95 and it was not
the intention of the Ada05 designers to invalidate this approach.
If it is possible to construct an aliased view of an object which
lacks a contiguous dope vector, then things can go downhill rapidly.
The following example illustrates the situation:
procedure Aliased_Return_Object is
type Inner (Ref : access Outer) is limited null record;
type Outer is limited
Self : Inner (Outer'access);
Data : Integer := 0;
type Vector is array (Positive range <>) of Outer;
subtype S is Vector (1 .. 10);
function F return Vector is
return X : aliased Vector := S'(others => <>) do
type Vector_Ref is access all Vector;
for Vector_Ref'Storage_Size use 0;
Ptr : Vector_Ref := X'access; --
Xx : Vector renames Ptr.all;
for I in Xx'range loop
Xx (I).Data := I;
Y : S := F; --
There is also a considerably more obscure problem involving object identity.
In this example,
subtype Zero_Sized is String (1 .. Report.Ident_Int (0));
X1, Y1 : Zero_Sized := Some_Function;
X2, Y2 : aliased Zero_Sized;
, it is ok if X1'Address = Y1'Address but it is not ok
if X2'Access = Y2'Access. If we can somehow construct X1'Access and Y1'Access,
and if they must be distinct, then some implementations might have a problem.
This particular problem is not very important (and it would be solved by
the Unchecked_Access "clarification" described above), but it does suggest
that there may be other issues that have not been discovered yet.
How should these problems be addressed?
One could simply change the syntax to disallow aliased extended return
objects, but that's a fairly major incompatibility.
It would probably be better to explicitly state the Unchecked_Access
"clarification" described above and then add a runtime check which
raises Program_Error when X'Access is evaluated during the execution
of the preceding example.
How precise should the condition of that runtime check be?
Perhaps the check fails during the evaluation of Some_Object'Access
(or Some_Object'Unchecked_Access) if Some_Object is an aliased extended
return object whose nominal subtype is an unconstrained array subtype
and the designated subtype of the access type is unconstrained.
Or perhaps for the check to fail it must also be the case that the function
is called to initialize an object other than an aliased array object with
an unconstrained nominal subtype (in implementation terms, an object
which lacks a contiguous dope vector).
Or perhaps (if portability is not a concern) it must also be the case
that the initialization of this dopeless object must be in place.
The first predicate, although the least precise, seems to be the best.
The more precise alternatives would probably incur distributed overhead
because a caller would have to pass in additional information (albeit
only a boolean) on the off chance that a function's body might
contain this problematic construct.
From: Randy Brukardt
Sent: Never, authored May 15, 2007 8:30 PM
>If this were the only problem, then this might be resolved via a
>"clarification" stating that if an aliased view of an unaliased
>object is used as the prefix of an Unchecked_Access attribute,
>then the resulting access value is valid only for the lifetime of
>the aliased view (which will typically be shorter than the lifetime
>of the designated object).
This "clarification" makes no sense. Are you saying that a program
that has such a 'Access and saves it somewhere is erroneous? That's
completely unacceptable to me - the error should be detected somehow;
it would make more sense to ban the 'Access or (better) define the
accessibility of such a 'Access to be limited to the extended return statement.
Is there any actual value to aliased return objects in the first place?
The best solution I can think of would be to have "aliased" as part of the function
spec. We actually talked about that at one time but eventually dropped that.
> For example, the IBM/Rational Ada compiler implements an aliased
> object X whose nominal subtype is an unconstrained array subtype
> by storing a contiguous dope vector. This is needed in order to
> support the evaluation of X'Access in the case where the designated
> type of the access type is unconstrained.
I have little sympathy for trying to support a contiguous dope vector; this is
an idea that I concluded wouldn't work (in all cases) back in 1983. It was the
original reason that we support/use non-contiguous objects. The struggle to
allow contiguous dope vectors reminds me of the struggle to support generic code
sharing. Arguably, implementers should get over it. ;-) In both cases, we add
rules to allow it, but those rules are both harmful to users and also don't
help that much. For instance, 3.10.2(27.1/2) requires static matching, while there
is no problem supporting *any* 'Access for an access-to-unconstrained array as long
as you don't require continguous array descriptors. Even slices would work fine.
(I vaguely recall that this rules helped in some generic code sharing case, so I'm
not being that serious about trying to repeal it...)
So, while I agree with
> This implementation model worked for Ada95 and it was not
> the intention of the Ada05 designers to invalidate this approach.
there are lots of other unintended consequences (like the incomparability of accessibility
in some cases) that are a lot harder to implement and have a lot more impact.
Questions? Ask the ACAA Technical Agent