comp.lang.ada
 help / color / mirror / Atom feed
From: Stephen Leake <stephen_leake@stephe-leake.org>
Subject: Re: Issue with GNAT GPL 2009 and GtkAda
Date: Sat, 27 Jun 2009 07:11:46 -0400
Date: 2009-06-27T07:11:46-04:00	[thread overview]
Message-ID: <uljnej5hp.fsf@stephe-leake.org> (raw)
In-Reply-To: h23fuk$fr5$1@munin.nbi.dk

"Randy Brukardt" <randy@rrsoftware.com> writes:

>>Niklas Holsti" <niklas.holsti@tidorum.invalid> wrote in message 
>>news:4a44ae4e$0$6295$4f793bc4@news.tdc.fi...
>> > Damien Carbonne <damien.carbonne@free.fr> writes:
>> >>
>> >>    type Listener is interface;
>> >>    procedure Process (L : in out Listener) is abstract;
>>  ...
>> >>    type Base is tagged null record;
>>  ...
>> >>    type Derived is new Base and Listener with null record;
>> >>    overriding procedure Process (D : in out Derived);
>> >>
>>
>> Stephen Leake wrote:
>>> The problem is clear here.
>>>
>>> "D : in out Derived" is allowed to create a copy of the actual
>>> parameter.
>>
>> Huh? Do you mean that this "D" parameter may be passed by copy? But 
>> "Derived" is a tagged type, and tagged types are passed by reference, not 
>> by copy. Or so I thought.
>
> I think he means that the accessibility level of a parameter is that of a 
> local object, as it *might* have been passed by copy. 

Well, I had forgotten that tagged types are by reference, so I meant
it might _actually_ be passed by copy. But apparently the compiler
isn't taking advantage of the fact that tagged types are by reference,
and is taking the more conservative view that it might be passed by copy.

> (There are no special rules here for tagged types.) So when you pass
> it to an access parameter, you get local accessibility and any
> attempt to use it with a named access type is going to fail a
> run-time accessibility check (raising Program_Error).

Now I'm confused. Here's the relevant code:

package Bug is

   -- Base interface
   type Listener is interface;
   type Listener_Ref is access all Listener'Class;
   procedure Process (L : in out Listener) is abstract;

   -- Base class
   type Base is tagged null record;
   type Base_Ref is access all Base'Class;
   procedure Foreach (B : access Base; I : Integer);

   -- Derived class
   type Derived is new Base and Listener with null record;
   type Derived_Ref is access all Derived'Class;
   overriding procedure Process (D : in out Derived);

   procedure Main;

end Bug;
--------------------------------------------------------------------------
with Ada.Text_IO;
package body Bug is

   procedure Foreach (B : access Base; I : Integer) is
      BB : Base_Ref;
   begin
      Ada.Text_IO.Put_Line ("Foreach" & Integer'Image (I));
      BB := B.all'Access; -- Line that fails
   end Foreach;

   procedure Process (D : in out Derived) is
   begin
      Ada.Text_IO.Put_Line ("Process");
      D.Foreach (2);
   end Process;

   procedure Main is
      G_Derived : constant Derived_Ref := new Derived;
      G_Listener : constant Listener_Ref := Listener_Ref (G_Derived);
   begin
      Ada.Text_IO.Put_Line ("Main");
      G_Derived.Foreach (1);  -- This one works
      G_Listener.Process; -- This one fails
   end Main;

end Bug;

The problem seems to be that the call in Main:

G_Listener.Process;

is passing a object (of a tagged type) to an "in out" parameter to Process.

Then the body of Process does 'Access on that parameter.

I had thought that part of the reason tagged types were by reference
was to allow this to work.

I gather you are saying that's not true, or at least the actual rules
did not achieve this desire.

> The only way that we could have done better would be to pass an 
> accessibility level with every tagged parameter. That seems like way too 
> much overhead.

I see. So the rules are more conservative than they could be, leading
to programmer surprises like this one.

Except that I'm not clear how accessiblity information is passed now.
Since it's a runtime check, it seems the accessiblity level must be
stored with the access object somehow; what is the extra overhead you
are talking about?

> You can use 'Unchecked_Access to get around the accessibility check, of 
> course, but if it would have failed, there is a chance that you will have 
> done something that would actually create a dangling pointer.

Right. I really appreciate the compiler telling me how to avoid
possible dangling pointers.

So far, I've managed to write code that follows the Ada rules (without
Unchecked_Access), and still does what I want. So the current Ada
rules work for me :).

> The aliased parameters that we're looking to add to Ada will mitigate this 
> problem somewhat, but only a little. 

Which Ada Issue is this in?

I tried searching at http://www.ada-auth.org/search-ai05s.html, but I
with Firefox only get a blank screen in response. MS Internet
Explorer gives a results page. But there are lots of results for
'aliased parameter', and none for '"aliased parameter"'.

Ah; searching the index page for 'aliased' finds AI05-0142, which
seems to be it.

I think that would allow the above code to work, by adding 'aliased'
to Process:

   overriding procedure Process (D : aliased in out Derived);

Hmm, that AI contains this paragraph:

    AARM Ramification: Tagged objects (and tagged aggregates for in
    parameters) do not need to be aliased. This matches the behavior
    of unaliased formal parameters of tagged types, which allow
    'Access to be taken of the formal parameter regardless of the form
    of the actual parameter.

Which says the code above should not raise an accessibility error. It
seems like this paragraph is referening to the Ammendment 1 Ada
behavior. But maybe it's just wrong?

Hmm. Searching thru the AARM, I find:

3.10 9.l/2
          We considered making more kinds of objects aliased by
          default. In particular, any object of a by-reference type
          will pretty much have to be allocated at an addressable
          location, so it can be passed by reference without using
          bit-field pointers. Therefore, one might wish to allow the
          Access and Unchecked_Access attributes for such objects.
          However, private parts are transparent to the definition of
          "by-reference type", so if we made all objects of a
          by-reference type aliased, we would be violating the privacy
          of private parts. Instead, we would have to define a concept
          of "visibly by-reference" and base the rule on that. This
          seemed to complicate the rules more than it was worth,
          especially since there is no way to declare an untagged
          limited private type to be by-reference, since the full type
          might by nonlimited.

which says "aliased" is _not_ the same as "by reference", and gives a
rationale for not allowing 'Access on by reference types.

But then:

3.10.2 26.f
          Note that for objects of a by-reference type, it is not an
          error for a programmer to take advantage of the fact that
          such objects are passed by reference. ...

And finally in the definition of 'Access:

Annex K 4 X'Access

     For a prefix X that denotes an aliased view of an object:

     ...

"aliased" is not the same as "by reference"

I can see why this is complicated :)

Incidently, I first tried getting to the Ada Issues site via AdaIC,
but couldn't find a link. I expected one on the Working Groups or Ada
Standards page.

-- 
-- Stephe



  reply	other threads:[~2009-06-27 11:11 UTC|newest]

Thread overview: 48+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2009-06-23 21:52 Issue with GNAT GPL 2009 and GtkAda Damien Carbonne
2009-06-24  7:40 ` Dmitry A. Kazakov
2009-06-24 10:15 ` Stephen Leake
2009-06-25  9:06   ` Stephen Leake
2009-06-25  9:39     ` Dmitry A. Kazakov
2009-06-25 19:02       ` Damien Carbonne
2009-06-26  9:31         ` Stephen Leake
2009-06-26 11:18           ` Niklas Holsti
2009-06-26 16:29             ` Damien Carbonne
2009-06-26 17:28               ` Dmitry A. Kazakov
2009-06-26 19:27                 ` Damien Carbonne
2009-06-26 19:50                   ` Dmitry A. Kazakov
2009-06-26 21:51             ` Randy Brukardt
2009-06-27 11:11               ` Stephen Leake [this message]
2009-06-27 17:04                 ` Robert A Duff
2009-06-30 11:11                   ` Stephen Leake
2009-06-30 18:10                     ` Robert A Duff
2009-06-29 22:11                 ` Randy Brukardt
2009-06-30 11:13                   ` Stephen Leake
2009-06-30 15:26                     ` Adam Beneschan
2009-06-30 15:59               ` Adam Beneschan
2009-06-30 23:11                 ` Randy Brukardt
2009-06-27  9:56             ` Stephen Leake
2009-06-26 21:03           ` Damien Carbonne
2009-06-27 11:21             ` Stephen Leake
2009-06-27 12:25               ` Damien Carbonne
2009-06-27 12:35                 ` Damien Carbonne
2009-06-29 22:15                   ` Randy Brukardt
2009-07-01 19:22                     ` Damien Carbonne
2009-06-30  0:48             ` Adam Beneschan
2009-06-30 11:18               ` Stephen Leake
2009-06-25 20:49       ` Randy Brukardt
2009-06-26  7:20         ` Dmitry A. Kazakov
2009-06-26  8:17           ` Georg Bauhaus
2009-06-26  8:52             ` Dmitry A. Kazakov
2009-06-26 21:38               ` Randy Brukardt
2009-06-27  7:47                 ` Dmitry A. Kazakov
2009-06-29 21:59                   ` Randy Brukardt
2009-06-30  8:31                     ` Dmitry A. Kazakov
2009-06-26 21:31           ` Randy Brukardt
2009-06-27  7:53             ` Dmitry A. Kazakov
2009-06-26  8:39       ` Alex R. Mosteo
2009-06-26  9:07         ` Dmitry A. Kazakov
2009-06-27  9:53           ` Stephen Leake
2009-06-26 21:40         ` Randy Brukardt
2009-06-29 10:04           ` Alex R. Mosteo
2009-06-26  9:02       ` Stephen Leake
2009-06-26  9:14         ` Dmitry A. Kazakov
replies disabled

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox