From: msimonides on
I have experienced problems upon using an access to tagged type object
converted to an access to ancestor type - Storage_Error is raised when
calling its operations.

After some investigation I found out that address of object (obtained
like this: Object_Ptr.all'Address) is different after conversion.
Using Unchecked_Deallocation for converting the access value solved
the problem.

The situation is analogous to that in program below:

with System.Address_Image; use System;
with Ada.Text_IO; use Ada.Text_IO;

procedure IFace_Cast_Bug is

type Root_Type is interface;
type Root_Access is access all Root_Type'Class;

type Additional_Operations_Type is interface and Root_Type;
type Additional_Operations_Access is access all
Additional_Operations_Type'Class;

type Root_Implementation_Type is new Root_Type with null record;
type Root_Implementation_Access is access all
Root_Implementation_Type'Class;

type Final_Implementation_Type is new Root_Implementation_Type and
Additional_Operations_Type with null record;
type Final_Implementation_Access is access all
Final_Implementation_Type'Class;


function To_Additional_Operations (Object_Ptr :
Final_Implementation_Access)
return Additional_Operations_Access
is
begin
return Additional_Operations_Access (Object_Ptr);
end To_Additional_Operations;


Object_Ptr : constant Final_Implementation_Access :=
new Final_Implementation_Type;

Iface_Ptr : constant Additional_Operations_Access :=
To_Additional_Operations (Object_Ptr);
begin
Put (Address_Image (Object_Ptr.all'Address));
Put (" /= ");
Put_Line (Address_Image (IFace_Ptr.all'Address));
end IFace_Cast_Bug;

The output of this program is two addresses, the first one 4 less than
the second one (in my original program the difference is 12).
Removing the Root_Implementation_Type tagged type from inheritance
hierarchy results in identical addresses.

The question is:
Am I doing something wrong with the conversion? I believe that
upcasting should be perfectly safe and operations defined for the
target type should work on the access (and even incorrect downcast
should raise Constraint_Error instead of a Storage_Error postponed to
the first use).

To me this looks like a compiler bug.

I am using GNAT GPL 3.4.6 on Linux.
--
Marcin Simonides

From: Robert A Duff on
msimonides(a)power.com.pl writes:

> The output of this program is two addresses, the first one 4 less than
> the second one (in my original program the difference is 12).
> Removing the Root_Implementation_Type tagged type from inheritance
> hierarchy results in identical addresses.
>
> The question is:
> Am I doing something wrong with the conversion?

I don't know (I didn't read your code carefully), but it is normal for
access values pointing at the same object to be represented by different
addresses, depending on which interface you are viewing the object as.
This is because C++ works that way, and GNAT mimics the C++ conventions
in order to make interfacing Ada with C++ easier.

C++ has a more powerful form of multiple inheritance than Ada does.
If we didn't care about interfacing, we could implement Ada without
this somewhat-strange offsetting of the addresses.

> To me this looks like a compiler bug.

Could be.

- Bob
From: Adam Beneschan on
On Mar 13, 9:06 am, Robert A Duff <bobd...(a)shell01.TheWorld.com>
wrote:
> msimoni...(a)power.com.pl writes:
> > The output of this program is two addresses, the first one 4 less than
> > the second one (in my original program the difference is 12).
> > Removing the Root_Implementation_Type tagged type from inheritance
> > hierarchy results in identical addresses.
>
> > The question is:
> > Am I doing something wrong with the conversion?
>
> I don't know (I didn't read your code carefully), but it is normal for
> access values pointing at the same object to be represented by different
> addresses, depending on which interface you are viewing the object as.
> This is because C++ works that way, and GNAT mimics the C++ conventions
> in order to make interfacing Ada with C++ easier.

I still think 'Address should be the same, though. The definition of
X'Address for an object X is that it is "the address of the first of
the storage elements allocated to X"; and here, after IFace_Ptr has
been converted from Object_Ptr by a legal type conversion,
IFace_Ptr.all and Object_Ptr.all are the same object, so their
'Address should be the same. It may be the case that IFace_Ptr and
Object_Ptr are represented as different addresses in memory, and that
if you used an Unchecked_Conversion on the access objects themselves,
you might see different values. But Marcin's code didn't use
Unchecked_Conversion; the 'Addresses should be the same, and if the
addresses stored in memory are different, the compiler needs to adjust
for this when computing 'Address.

This definitely seems like a compiler bug.

-- Adam


From: Robert A Duff on
"Adam Beneschan" <adam(a)irvine.com> writes:

> I still think 'Address should be the same, though. The definition of
> X'Address for an object X is that it is "the address of the first of
> the storage elements allocated to X";...

Good point.

- Bob
From: Simon Wright on
Judging by the result of compiling with -gnatdg (output intermediate
form) and -gnata (assertions), the compiler seems to be complaining
that Root_Implementation_Type isn't an interface. So I guess it's
confused (which would explain the strange (lack of) error messages).

Is this conversion of access values legal in Ada 95? if so -- live and
learn!
 |  Next  |  Last
Pages: 1 2
Prev: Design help
Next: FYI - Lead Designer of Ada Dies