comp.lang.ada
 help / color / mirror / Atom feed
* Issue with GNAT GPL 2009 and GtkAda
@ 2009-06-23 21:52 Damien Carbonne
  2009-06-24  7:40 ` Dmitry A. Kazakov
  2009-06-24 10:15 ` Stephen Leake
  0 siblings, 2 replies; 48+ messages in thread
From: Damien Carbonne @ 2009-06-23 21:52 UTC (permalink / raw)
  To: gtkada

Hi,

When compiling a program I had written to GNAT GPL 2009 on Linux and 
Windows, I met a problem with the usage of Gtk.Tree_Model.Foreach.

I wrote a relatively small program (unfortunately, still quite long) 
that reproduces the problem (attached in the end).

I wonder if this is a bug in
    1) my program,
    2) GtkAda or
    3) GNAT GPL 2009.
What surprises me is that it was quite hard to reproduce this problem.
Most other examples I wrote with Foreach worked very well.
I don't know how GNAT handles accessibility rules.
I wonder if the problem is not related to the usage of Interfaces ?
I did not try yet to change the program so that it can work, but other 
examples I wrote were quite similar, except that they did not use 
interfaces. I'll check, but do you have any idea on this issue ?

Thanks for help !

Regards,

Damien Carbonne


--------------------------------------------------------------------------
with Bug;
procedure Main is
begin
    Bug.Main;
end Main;
-- Tested with GNAT GPL 2009 on Linux

-- When this program is run, these messages are printed:
--
-- View.Window.Gtk_New
-- View.Window.Initialize
-- View.Store.Gtk_New
-- View.Store.Initialize
-- Model.Attach_Listener
--
-- Then, when one clicks in "Click here to raise exception" button,
-- those one are printed:
--
-- View.Window.On_Reset_Usage_Clicked
-- Model.Do_Something_And_Notify_Listener
-- View.Store.Process
-- View.Store.Visit_Nodes
-- View.Store.Run Foreach ...
-- Exception raised in View.Store.Visit_Nodes
-- Exception name: PROGRAM_ERROR
-- Message: gtk-tree_model.adb:838 accessibility check failed
--
--
-- raised PROGRAM_ERROR : gtk-tree_model.adb:838 accessibility check failed

--------------------------------------------------------------------------
with Gtk.Tree_Store;      use Gtk.Tree_Store;
with Gtk.Window;          use Gtk.Window;
with Gtk.Box;             use Gtk.Box;
with Gtk.Button;          use Gtk.Button;
with Gtk.Tree_View;       use Gtk.Tree_View;

package Bug is

 
-----------------------------------------------------------------------------
    -- This package is a simplified model representation
    -- It holds an access to 1 listener and calls the attached listener
    -- when Do_Something_And_Notify_Listeneris called
    package Model is

       procedure Do_Something_And_Notify_Listener;

       type Model_Listener is limited interface;
       type Model_Listener_Ref is access all Model_Listener'Class;
       procedure Process (Listener : in out Model_Listener) is abstract;

       procedure Attach_Listener (Listener : Model_Listener_Ref);

    end Model;
 
-----------------------------------------------------------------------------
    -- This package is a simplified view representation
    package View is
 
--------------------------------------------------------------------------
       -- This package is supposed to contain a tree representation of
       -- the above model.
       -- The store is also a listener of the above model.
       -- When process is called, Foreach is called, and the program
       -- terminates with an exception.
       package Store is
          Index_Name : constant := 0;
          -- Index used to store a string (name)

          type View_Store_Record is new Gtk_Tree_Store_Record and
            Model.Model_Listener with private;

          type View_Store is access all View_Store_Record'Class;

          procedure Gtk_New (Store : out View_Store);
          procedure Initialize (Store : access View_Store_Record'Class);

       private
          type View_Store_Record is new Gtk_Tree_Store_Record and
            Model.Model_Listener with null record;
          overriding
          procedure Process (Store : in out View_Store_Record);
       end Store;
 
--------------------------------------------------------------------------
       -- This package is supposed to provide the graphical
       -- representation of the above tree store.
       -- When the user click on the button, a call to
       -- Model.Do_Something_And_Notify_Listener is done.
       -- The attached model listener is then called.
       package Window is
          type View_Window_Record is new Gtk_Window_Record with record
             Vbox      : Gtk_Vbox;
             Button    : Gtk_Button;
             Tree_View : Gtk_Tree_View;
          end record;

          type View_Window_Ref is access all View_Window_Record'Class;

          procedure Gtk_New (Widget : out View_Window_Ref);
          procedure Initialize
            (Widget : access View_Window_Record'Class);
       end Window;
 
--------------------------------------------------------------------------
    end View;
 
-----------------------------------------------------------------------------
    procedure Main;
end Bug;

with System;
with Ada.Text_IO;
with Ada.Exceptions;
with Gtk.Tree_Model;         use Gtk.Tree_Model;
with Glib;
with Gtk.Enums;              use Gtk.Enums;
with Gtk.Tree_View_Column;   use Gtk.Tree_View_Column;
with Gtk.Cell_Renderer_Text; use Gtk.Cell_Renderer_Text;
with Gtk.Widget;             use Gtk.Widget;
with Gtk.Handlers;
with Gtk.Main;

package body Bug is

    -----------
    -- Model --
    -----------

    package body Model is

       G_Listener : Model_Listener_Ref := null;

       --------------------------------------
       -- Do_Something_And_Notify_Listener --
       --------------------------------------

       procedure Do_Something_And_Notify_Listener is
       begin
          Ada.Text_IO.Put_Line
            ("Model.Do_Something_And_Notify_Listener");
          if G_Listener /= null then
             G_Listener.Process;
          end if;
       end Do_Something_And_Notify_Listener;

       ---------------------
       -- Attach_Listener --
       ---------------------

       procedure Attach_Listener (Listener : Model_Listener_Ref) is
       begin
          Ada.Text_IO.Put_Line ("Model.Attach_Listener");
          G_Listener := Listener;
       end Attach_Listener;

    end Model;

    ----------
    -- View --
    ----------

    package body View is

       -----------
       -- Store --
       -----------

       package body Store is

          ----------------
          -- Visit_Node --
          ----------------

          function Visit_Node
            (Model     : access Gtk_Tree_Model_Record'Class;
             Path      : Gtk_Tree_Path;
             Iter      : Gtk_Tree_Iter;
             User_Data : System.Address)
             return      Boolean
          is
             pragma Unreferenced (Model, Iter, User_Data);
          begin
             Ada.Text_IO.Put_Line
               ("View.Store.Visit_Node: [" & To_String (Path) & "]");
             return False;
          end Visit_Node;

          -----------------
          -- Visit_Nodes --
          -----------------

          procedure Visit_Nodes
            (Store : access View_Store_Record'Class)
          is
          begin
             Ada.Text_IO.Put_Line ("View.Store.Visit_Nodes");
             Ada.Text_IO.Put_Line ("View.Store.Run Foreach ...");
             Foreach (Store, Visit_Node'Access, System.Null_Address);
             Ada.Text_IO.Put_Line ("View.Store.Foreach Done");
          exception
             when E : others =>
                Ada.Text_IO.Put_Line
                  ("Exception raised in View.Store.Visit_Nodes");
                Ada.Text_IO.Put_Line
                  (Ada.Exceptions.Exception_Information (E));
                raise;
          end Visit_Nodes;

          -------------
          -- Gtk_New --
          -------------

          procedure Gtk_New (Store : out View_Store) is
          begin
             Ada.Text_IO.Put_Line ("View.Store.Gtk_New");
             Store := new View_Store_Record;
             Initialize (Store);
          end Gtk_New;

          ----------------
          -- Initialize --
          ----------------

          procedure Initialize
            (Store : access View_Store_Record'Class)
          is
             Iter : Gtk_Tree_Iter;
          begin
             Ada.Text_IO.Put_Line ("View.Store.Initialize");
             Gtk.Tree_Store.Initialize
               (Store,
                Glib.GType_Array'(Index_Name => Glib.GType_String));

             -- Create dummy nodes in the store
             Store.Insert (Iter, Null_Iter, 0);
             Store.Set (Iter, Index_Name, "Root");

             -- Attach itself as a listener
             Model.Attach_Listener (Model.Model_Listener_Ref (Store));
          end Initialize;

          -------------
          -- Process --
          -------------

          procedure Process (Store : in out View_Store_Record) is
          begin
             Ada.Text_IO.Put_Line ("View.Store.Process");
             Store.Visit_Nodes;
          end Process;

       end Store;

       ------------
       -- Window --
       ------------

       package body Window is
          package Button_Cb is new
             Gtk.Handlers.Callback (Gtk_Button_Record);
          G_View_Store : Store.View_Store := null;

          ----------------------------
          -- On_Reset_Usage_Clicked --
          ----------------------------

          procedure On_Reset_Usage_Clicked
            (Widget : access Gtk_Button_Record'Class)
          is
             pragma Unreferenced (Widget);
          begin
             Ada.Text_IO.Put_Line ("View.Window.On_Reset_Usage_Clicked");
             Model.Do_Something_And_Notify_Listener;
          end On_Reset_Usage_Clicked;

          -------------
          -- Gtk_New --
          -------------

          procedure Gtk_New (Widget : out View_Window_Ref) is
          begin
             Ada.Text_IO.Put_Line ("View.Window.Gtk_New");
             Widget := new View_Window_Record;
             Initialize (Widget);
          end Gtk_New;

          ----------------
          -- Initialize --
          ----------------

          procedure Initialize
            (Widget : access View_Window_Record'Class)
          is
             Column        : Gtk_Tree_View_Column;
             Text_Renderer : Gtk_Cell_Renderer_Text;
             Foo           : Glib.Gint;
             pragma Unreferenced (Foo);
             use Store;
          begin
             Ada.Text_IO.Put_Line ("View.Window.Initialize");

             -- Window
             Gtk.Window.Initialize (Widget, Window_Toplevel);
             Set_Title (Widget, "Bug with Foreach");
             Set_Default_Size (Widget, 300, 200);

             -- VBox
             Gtk_New_Vbox (Widget.Vbox, False, 0);
             Add (Widget, Widget.Vbox);

             -- Button
             Gtk_New (Widget.Button, "Click here to raise exception");
             Pack_Start
               (Widget.Vbox,
                Widget.Button,
                Expand  => False,
                Fill    => False,
                Padding => 0);

             -- Tree view
             Gtk_New (Widget.Tree_View);
             Set_Headers_Visible (Widget.Tree_View, True);
             Pack_Start
               (Widget.Vbox,
                Widget.Tree_View,
                Expand  => True,
                Fill    => True,
                Padding => 0);

             -- Renderers
             Gtk_New (Column);
             Set_Title (Column, "Title");
             Foo := Append_Column (Widget.Tree_View, Column);

             Gtk_New (Text_Renderer);
             Pack_Start (Column, Text_Renderer, False);
             Add_Attribute (Column, Text_Renderer, "text",
                            Store.Index_Name);

             -- Callbacks
             Button_Cb.Connect
               (Widget.Button,
                "clicked",
                Button_Cb.To_Marshaller (On_Reset_Usage_Clicked'Access));

             -- Create once the same log store shared by all windows
             if G_View_Store = null then
                Gtk_New (G_View_Store);
             end if;

             Set_Model (Widget.Tree_View, G_View_Store.all'Access);
          end Initialize;

       end Window;

    end View;

    ----------
    -- Main --
    ----------

    procedure Main is
       G_Window : View.Window.View_Window_Ref := null;
    begin
       Gtk.Main.Set_Locale;
       Gtk.Main.Init;
       View.Window.Gtk_New (G_Window);
       G_Window.Show_All;
       Gtk.Main.Main;
    end Main;

end Bug;



^ permalink raw reply	[flat|nested] 48+ messages in thread

* Re: Issue with GNAT GPL 2009 and GtkAda
  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
  1 sibling, 0 replies; 48+ messages in thread
From: Dmitry A. Kazakov @ 2009-06-24  7:40 UTC (permalink / raw)


On Tue, 23 Jun 2009 23:52:59 +0200, Damien Carbonne wrote:

> When compiling a program I had written to GNAT GPL 2009 on Linux and 
> Windows, I met a problem with the usage of Gtk.Tree_Model.Foreach.
> 
> I wrote a relatively small program (unfortunately, still quite long) 
> that reproduces the problem (attached in the end).
> 
> I wonder if this is a bug in
>     1) my program,
>     2) GtkAda or
>     3) GNAT GPL 2009.
> What surprises me is that it was quite hard to reproduce this problem.
> Most other examples I wrote with Foreach worked very well.
> I don't know how GNAT handles accessibility rules.
> I wonder if the problem is not related to the usage of Interfaces ?
> I did not try yet to change the program so that it can work, but other 
> examples I wrote were quite similar, except that they did not use 
> interfaces. I'll check, but do you have any idea on this issue ?

Well, it is difficult to say, I never used foreach. I do Gtk_Tree_Iter
instead. I looked briefly at the implementation of Foreach in GtkAda and
found nothing offending.

Interface should not be a problem. Run-time accessibility checks is always
a *huge* problem. If in doubt use Unchecked_Access everywhere. I know it is
disgusting, but so is the propagation of a Constraint_Error at run-time.

Other possible issues:

1. Types extending GtkAda types must be library-level

2. Text_IO shall not be used (may cause exception propagation at least on
some platforms, with a subsequent crash. Ada exceptions propagated through
Gtk almost certainly crash the program. You cannot catch them)

3. In your code there is no "unref" the model after Set_Model. Tree model
is not a widget, it must be explicitly unreferenced.

-- 
Regards,
Dmitry A. Kazakov
http://www.dmitry-kazakov.de



^ permalink raw reply	[flat|nested] 48+ messages in thread

* Re: Issue with GNAT GPL 2009 and GtkAda
  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
  1 sibling, 1 reply; 48+ messages in thread
From: Stephen Leake @ 2009-06-24 10:15 UTC (permalink / raw)


Damien Carbonne <damien.carbonne@free.fr> writes:

> When compiling a program I had written to GNAT GPL 2009 on Linux and
> Windows, I met a problem with the usage of Gtk.Tree_Model.Foreach.
>
> I wrote a relatively small program (unfortunately, still quite long)
> that reproduces the problem (attached in the end).

This looks like a compiler bug to me. However, GNAT 6.2.1 on Windows
reports the same access violation.

> I wonder if this is a bug in
>    1) my program,
>    2) GtkAda or
>    3) GNAT GPL 2009.
> What surprises me is that it was quite hard to reproduce this problem.
> Most other examples I wrote with Foreach worked very well.
> I don't know how GNAT handles accessibility rules.

Since the access object being dereferenced is in a package level
variable, it should not be possible to get an access violation.

> I wonder if the problem is not related to the usage of Interfaces ?
> I did not try yet to change the program so that it can work, but other
> examples I wrote were quite similar, except that they did not use
> interfaces. I'll check, but do you have any idea on this issue ?

I don't see why interfaces should affect accessibility. 

If you post a variant that works with GNAT 2009, I can try it with
6.2.1.

I suggest you report this to AdaCore.

-- 
-- Stephe



^ permalink raw reply	[flat|nested] 48+ messages in thread

* Re: Issue with GNAT GPL 2009 and GtkAda
  2009-06-24 10:15 ` Stephen Leake
@ 2009-06-25  9:06   ` Stephen Leake
  2009-06-25  9:39     ` Dmitry A. Kazakov
  0 siblings, 1 reply; 48+ messages in thread
From: Stephen Leake @ 2009-06-25  9:06 UTC (permalink / raw)


Stephen Leake <stephen_leake@stephe-leake.org> writes:

> Damien Carbonne <damien.carbonne@free.fr> writes:
>
>> When compiling a program I had written to GNAT GPL 2009 on Linux and
>> Windows, I met a problem with the usage of Gtk.Tree_Model.Foreach.
>>
>> I wrote a relatively small program (unfortunately, still quite long)
>> that reproduces the problem (attached in the end).
>
> This looks like a compiler bug to me. However, GNAT 6.2.1 on Windows
> reports the same access violation.
>
>> I wonder if this is a bug in
>>    1) my program,
>>    2) GtkAda or
>>    3) GNAT GPL 2009.
>> What surprises me is that it was quite hard to reproduce this problem.
>> Most other examples I wrote with Foreach worked very well.
>> I don't know how GNAT handles accessibility rules.
>
> Since the access object being dereferenced is in a package level
> variable, it should not be possible to get an access violation.
>
>> I wonder if the problem is not related to the usage of Interfaces ?
>> I did not try yet to change the program so that it can work, but other
>> examples I wrote were quite similar, except that they did not use
>> interfaces. I'll check, but do you have any idea on this issue ?
>
> I don't see why interfaces should affect accessibility. 

Another thought: whenever I have trouble with anonymous access types,
I replace them with the corresponding named access type, and the
problem goes away. That may indicate a conmpiler bug, but I've always
had to much to do to find out.

In this case, that means editing the GtkAda sources, which is less
than ideal.

-- 
-- Stephe



^ permalink raw reply	[flat|nested] 48+ messages in thread

* Re: Issue with GNAT GPL 2009 and GtkAda
  2009-06-25  9:06   ` Stephen Leake
@ 2009-06-25  9:39     ` Dmitry A. Kazakov
  2009-06-25 19:02       ` Damien Carbonne
                         ` (3 more replies)
  0 siblings, 4 replies; 48+ messages in thread
From: Dmitry A. Kazakov @ 2009-06-25  9:39 UTC (permalink / raw)


On Thu, 25 Jun 2009 05:06:08 -0400, Stephen Leake wrote:

> Another thought: whenever I have trouble with anonymous access types,
> I replace them with the corresponding named access type, and the
> problem goes away. That may indicate a conmpiler bug, but I've always
> had to much to do to find out.

Yes, but that is not necessarily a compiler bug. It is quite simple to
create a serious problem to oneself:

declare
   Ptr : access T := new T;
begin
   ...
   External_Ptr := Ptr.all'Uchecked_Access; -- Copy the pointer
   ...
end;  -- Now External_Ptr is dangling, because the object is freed.

-- 
Regards,
Dmitry A. Kazakov
http://www.dmitry-kazakov.de



^ permalink raw reply	[flat|nested] 48+ messages in thread

* Re: Issue with GNAT GPL 2009 and GtkAda
  2009-06-25  9:39     ` Dmitry A. Kazakov
@ 2009-06-25 19:02       ` Damien Carbonne
  2009-06-26  9:31         ` Stephen Leake
  2009-06-25 20:49       ` Randy Brukardt
                         ` (2 subsequent siblings)
  3 siblings, 1 reply; 48+ messages in thread
From: Damien Carbonne @ 2009-06-25 19:02 UTC (permalink / raw)


Thanks to both of you for your answers.

I managed to create a much simpler example (that does not depend on 
GtkAda) that exhibits the same kind of problem. It also shows that 
depending on the way the Foreach is called, the exception is raised or 
not. Disappointing.

Here it is:

--------------------------------------------------------------------------
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;
--------------------------------------------------------------------------
with Bug;
procedure Main is
begin
    Bug.Main;
end Main;
-- Tested with GNAT GPL 2009 on Linux
--
-- Main
-- Foreach 1
-- Process
-- Foreach 2
--
-- raised PROGRAM_ERROR : bug.adb:8 accessibility check failed
--------------------------------------------------------------------------

The workaround is obviously to replace the 'Access with 'Unchecked_Access.
In such case, I don't modify Gtkda iteself but create a special package 
that contains a corrected version of the function. In that case, the 
function is no more a primitive one, but it does not really matter.

I find usage of 'Access quite annoying, because I never really know when 
there is an exception whether it is becauise my code is incorrect or 
because the compiler is incorrect.
The last simple example I wrote seems to indicate that GNAT has a bug, 
but I'm not an Ada expert !
If you also consider that there is a GNAT bug, I'll submit a bug to AdaCore.

Thanks again.

Damien Carbonne



Dmitry A. Kazakov a �crit :
> On Thu, 25 Jun 2009 05:06:08 -0400, Stephen Leake wrote:
> 
>> Another thought: whenever I have trouble with anonymous access types,
>> I replace them with the corresponding named access type, and the
>> problem goes away. That may indicate a conmpiler bug, but I've always
>> had to much to do to find out.
> 
> Yes, but that is not necessarily a compiler bug. It is quite simple to
> create a serious problem to oneself:
> 
> declare
>    Ptr : access T := new T;
> begin
>    ...
>    External_Ptr := Ptr.all'Uchecked_Access; -- Copy the pointer
>    ...
> end;  -- Now External_Ptr is dangling, because the object is freed.
> 



^ permalink raw reply	[flat|nested] 48+ messages in thread

* Re: Issue with GNAT GPL 2009 and GtkAda
  2009-06-25  9:39     ` Dmitry A. Kazakov
  2009-06-25 19:02       ` Damien Carbonne
@ 2009-06-25 20:49       ` Randy Brukardt
  2009-06-26  7:20         ` Dmitry A. Kazakov
  2009-06-26  8:39       ` Alex R. Mosteo
  2009-06-26  9:02       ` Stephen Leake
  3 siblings, 1 reply; 48+ messages in thread
From: Randy Brukardt @ 2009-06-25 20:49 UTC (permalink / raw)


"Dmitry A. Kazakov" <mailbox@dmitry-kazakov.de> wrote in message 
news:1avd65rn49abv$.krcxo2gdzb16$.dlg@40tude.net...
...
> Yes, but that is not necessarily a compiler bug. It is quite simple to
> create a serious problem to oneself:
>
> declare
>   Ptr : access T := new T;
> begin

Allocators of anonymous access types are almost never what you want. This is 
so true, in fact, that we have proposed a Restriction for this 
"No_Anonymous_Allocators", which I recommend is part of every program. (Of 
course, that will have to wait until compilers implement it; it wasn't 
formally proposed until 3 weeks ago, but it was accepted at the Brest 
meeting and thus will appear in the next working draft).

The next version of Janus/Ada will print out a warning for any anonymous 
allocator (the restriction would turn it into an error, of course).

                                     Randy.





^ permalink raw reply	[flat|nested] 48+ messages in thread

* Re: Issue with GNAT GPL 2009 and GtkAda
  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 21:31           ` Randy Brukardt
  0 siblings, 2 replies; 48+ messages in thread
From: Dmitry A. Kazakov @ 2009-06-26  7:20 UTC (permalink / raw)


On Thu, 25 Jun 2009 15:49:58 -0500, Randy Brukardt wrote:

> "Dmitry A. Kazakov" <mailbox@dmitry-kazakov.de> wrote in message 
> news:1avd65rn49abv$.krcxo2gdzb16$.dlg@40tude.net...
> ...
>> Yes, but that is not necessarily a compiler bug. It is quite simple to
>> create a serious problem to oneself:
>>
>> declare
>>   Ptr : access T := new T;
>> begin
> 
> Allocators of anonymous access types are almost never what you want. This is 
> so true, in fact, that we have proposed a Restriction for this 
> "No_Anonymous_Allocators", which I recommend is part of every program. (Of 
> course, that will have to wait until compilers implement it; it wasn't 
> formally proposed until 3 weeks ago, but it was accepted at the Brest 
> meeting and thus will appear in the next working draft).

The only purpose of

   Ptr : access T := new T;

I can guess is allocation of a large scoped object on the heap. It would be
better if there were a syntax for that, which does not involve access
types.

   Object : new T;

or

   Object : T'Pool;

or

   Object : T;
   for Object'Storage_Pool use System.Default_Storage_Pool;

etc.

Access types are much overused in Ada in order to overcome language
problems unrelated to access types.

Just to remember: access discriminants (MI for poor), the Rosen trick (in
out parameters of a function), return by access (a patch where in-place
results should have been) and so on.

-- 
Regards,
Dmitry A. Kazakov
http://www.dmitry-kazakov.de



^ permalink raw reply	[flat|nested] 48+ messages in thread

* Re: Issue with GNAT GPL 2009 and GtkAda
  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:31           ` Randy Brukardt
  1 sibling, 1 reply; 48+ messages in thread
From: Georg Bauhaus @ 2009-06-26  8:17 UTC (permalink / raw)


Dmitry A. Kazakov wrote:

> Access types are much overused in Ada in order to overcome language
> problems unrelated to access types.

Another reason to overuse _anonymous_ access types is
probably outside the language, but is present with language
users:  anonymity provides for a reduction in perceived
programmer typing cost which is a convincing motive
to not use names in practice. I.e.

      type R is record
        C1 : access T;   -- quick & risky
        C2 : Float;
      end record

is thought to bring less work.  Experience apparently shows that
it doesn't, since the anonymity virus becomes activated sooner
or later. (Judging by the number of reports of anonymous access
issues.)

Does "access T :=" really have 80/20 merits?



^ permalink raw reply	[flat|nested] 48+ messages in thread

* Re: Issue with GNAT GPL 2009 and GtkAda
  2009-06-25  9:39     ` Dmitry A. Kazakov
  2009-06-25 19:02       ` Damien Carbonne
  2009-06-25 20:49       ` Randy Brukardt
@ 2009-06-26  8:39       ` Alex R. Mosteo
  2009-06-26  9:07         ` Dmitry A. Kazakov
  2009-06-26 21:40         ` Randy Brukardt
  2009-06-26  9:02       ` Stephen Leake
  3 siblings, 2 replies; 48+ messages in thread
From: Alex R. Mosteo @ 2009-06-26  8:39 UTC (permalink / raw)


Dmitry A. Kazakov wrote:

> On Thu, 25 Jun 2009 05:06:08 -0400, Stephen Leake wrote:
> 
>> Another thought: whenever I have trouble with anonymous access types,
>> I replace them with the corresponding named access type, and the
>> problem goes away. That may indicate a conmpiler bug, but I've always
>> had to much to do to find out.
> 
> Yes, but that is not necessarily a compiler bug. It is quite simple to
> create a serious problem to oneself:
> 
> declare
>    Ptr : access T := new T;
> begin
>    ...
>    External_Ptr := Ptr.all'Uchecked_Access; -- Copy the pointer
>    ...
> end;  -- Now External_Ptr is dangling, because the object is freed.
 
If I understand correctly, this is because the type of Ptr goes out of 
scope?

I strongly suspect that Gnat does not behave this way, but I should test it.



^ permalink raw reply	[flat|nested] 48+ messages in thread

* Re: Issue with GNAT GPL 2009 and GtkAda
  2009-06-26  8:17           ` Georg Bauhaus
@ 2009-06-26  8:52             ` Dmitry A. Kazakov
  2009-06-26 21:38               ` Randy Brukardt
  0 siblings, 1 reply; 48+ messages in thread
From: Dmitry A. Kazakov @ 2009-06-26  8:52 UTC (permalink / raw)


On Fri, 26 Jun 2009 10:17:49 +0200, Georg Bauhaus wrote:

> Dmitry A. Kazakov wrote:
> 
>> Access types are much overused in Ada in order to overcome language
>> problems unrelated to access types.
> 
> Another reason to overuse _anonymous_ access types is
> probably outside the language, but is present with language
> users:  anonymity provides for a reduction in perceived
> programmer typing cost which is a convincing motive
> to not use names in practice. I.e.
> 
>       type R is record
>         C1 : access T;   -- quick & risky
>         C2 : Float;
>       end record
> 
> is thought to bring less work.

One of the language problems is that the container types do not well
compose unconstrained types. Considering this one:

   type R is record
      C1 : T'Class;   -- does not work, considering an access type
      C2 : Float;
   end record

it should be allowed to do without access types, like:

   type R (Constraint : T'Range) is record
      C1 : T'Class (Constraint); -- Still class-wide, but constrained
      C2 : Float;
   end record

T'Range is a subtype of Ada.Tags.Tag:

   subtype T'Range is T'Tag...<the last tag of types derived from T>;

> Experience apparently shows that
> it doesn't, since the anonymity virus becomes activated sooner
> or later. (Judging by the number of reports of anonymous access
> issues.)

Yes. I think it is related to a more general issue of structural vs.
nominal type equivalence. I suspect that structural equivalence never pays
off. Ada, initially designed with nominal equivalence, swayed to the
structural one. Anonymous access types is the most prominent example of.
 
> Does "access T :=" really have 80/20 merits?

I would remove anonymous access types altogether, fixing the real language
problems, which led to introducing them in first place.

-- 
Regards,
Dmitry A. Kazakov
http://www.dmitry-kazakov.de



^ permalink raw reply	[flat|nested] 48+ messages in thread

* Re: Issue with GNAT GPL 2009 and GtkAda
  2009-06-25  9:39     ` Dmitry A. Kazakov
                         ` (2 preceding siblings ...)
  2009-06-26  8:39       ` Alex R. Mosteo
@ 2009-06-26  9:02       ` Stephen Leake
  2009-06-26  9:14         ` Dmitry A. Kazakov
  3 siblings, 1 reply; 48+ messages in thread
From: Stephen Leake @ 2009-06-26  9:02 UTC (permalink / raw)


"Dmitry A. Kazakov" <mailbox@dmitry-kazakov.de> writes:

> On Thu, 25 Jun 2009 05:06:08 -0400, Stephen Leake wrote:
>
>> Another thought: whenever I have trouble with anonymous access types,
>> I replace them with the corresponding named access type, and the
>> problem goes away. That may indicate a conmpiler bug, but I've always
>> had to much to do to find out.
>
> Yes, but that is not necessarily a compiler bug. It is quite simple to
> create a serious problem to oneself:
>
> declare
>    Ptr : access T := new T;
> begin
>    ...
>    External_Ptr := Ptr.all'Uchecked_Access; -- Copy the pointer
>    ...
> end;  -- Now External_Ptr is dangling, because the object is freed.

Yes, but only because you used "Unchecked".

The problems I was refering to were compiler-time errors, or runtime
accessibility check failures.

-- 
-- Stephe



^ permalink raw reply	[flat|nested] 48+ messages in thread

* Re: Issue with GNAT GPL 2009 and GtkAda
  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
  1 sibling, 1 reply; 48+ messages in thread
From: Dmitry A. Kazakov @ 2009-06-26  9:07 UTC (permalink / raw)


On Fri, 26 Jun 2009 10:39:45 +0200, Alex R. Mosteo wrote:

> Dmitry A. Kazakov wrote:
> 
>> On Thu, 25 Jun 2009 05:06:08 -0400, Stephen Leake wrote:
>> 
>>> Another thought: whenever I have trouble with anonymous access types,
>>> I replace them with the corresponding named access type, and the
>>> problem goes away. That may indicate a conmpiler bug, but I've always
>>> had to much to do to find out.
>> 
>> Yes, but that is not necessarily a compiler bug. It is quite simple to
>> create a serious problem to oneself:
>> 
>> declare
>>    Ptr : access T := new T;
>> begin
>>    ...
>>    External_Ptr := Ptr.all'Uchecked_Access; -- Copy the pointer
>>    ...
>> end;  -- Now External_Ptr is dangling, because the object is freed.
>  
> If I understand correctly, this is because the type of Ptr goes out of 
> scope?

Yes

> I strongly suspect that Gnat does not behave this way, but I should test it.

Here is a test:

with Ada.Finalization;
with Ada.Text_IO;  use Ada.Text_IO;

procedure Test_Anonymous_Access is
   package P is
      type T is new Ada.Finalization.Controlled with null record;
      overriding procedure Finalize (X : in out T);
   end P;
   package body P is
      procedure Finalize (X : in out T) is
      begin
         Put_Line ("Finalized");
      end Finalize;
   end P;
   use P;
begin
   declare
      X : access T := new T;
   begin
      Put_Line ("Created");
   end;
   Put_Line ("Left the scope");
end Test_Anonymous_Access;

It should print:

Created
Finalized
Left the scope

-- 
Regards,
Dmitry A. Kazakov
http://www.dmitry-kazakov.de



^ permalink raw reply	[flat|nested] 48+ messages in thread

* Re: Issue with GNAT GPL 2009 and GtkAda
  2009-06-26  9:02       ` Stephen Leake
@ 2009-06-26  9:14         ` Dmitry A. Kazakov
  0 siblings, 0 replies; 48+ messages in thread
From: Dmitry A. Kazakov @ 2009-06-26  9:14 UTC (permalink / raw)


On Fri, 26 Jun 2009 05:02:27 -0400, Stephen Leake wrote:

> "Dmitry A. Kazakov" <mailbox@dmitry-kazakov.de> writes:
> 
>> On Thu, 25 Jun 2009 05:06:08 -0400, Stephen Leake wrote:
>>
>>> Another thought: whenever I have trouble with anonymous access types,
>>> I replace them with the corresponding named access type, and the
>>> problem goes away. That may indicate a conmpiler bug, but I've always
>>> had to much to do to find out.
>>
>> Yes, but that is not necessarily a compiler bug. It is quite simple to
>> create a serious problem to oneself:
>>
>> declare
>>    Ptr : access T := new T;
>> begin
>>    ...
>>    External_Ptr := Ptr.all'Uchecked_Access; -- Copy the pointer
>>    ...
>> end;  -- Now External_Ptr is dangling, because the object is freed.
> 
> Yes, but only because you used "Unchecked".
> 
> The problems I was refering to were compiler-time errors, or runtime
> accessibility check failures.

Unchecked_Access is used to fight runtime accessibility check. There would
be no problem if we could go without Unchecked_Access. It is meaningless
accessibility checks make programmers accustomed to Unchecked_Access. It is
meaningless treatment of "access T" as an anonymous local type, where the
main purpose of anonymous access is to be an equivalent of any access type.
It is naive to expect people (even disciplined Ada programmers) to follow
all these conceptual shifts.

-- 
Regards,
Dmitry A. Kazakov
http://www.dmitry-kazakov.de



^ permalink raw reply	[flat|nested] 48+ messages in thread

* Re: Issue with GNAT GPL 2009 and GtkAda
  2009-06-25 19:02       ` Damien Carbonne
@ 2009-06-26  9:31         ` Stephen Leake
  2009-06-26 11:18           ` Niklas Holsti
  2009-06-26 21:03           ` Damien Carbonne
  0 siblings, 2 replies; 48+ messages in thread
From: Stephen Leake @ 2009-06-26  9:31 UTC (permalink / raw)


Damien Carbonne <damien.carbonne@free.fr> writes:

> Thanks to both of you for your answers.
>
> I managed to create a much simpler example (that does not depend on
> GtkAda) that exhibits the same kind of problem. It also shows that
> depending on the way the Foreach is called, the exception is raised or
> not. Disappointing.

The problem is clear here.

"D : in out Derived" is allowed to create a copy of the actual
parameter. Thus the 'Access in Foreach could be on a stack copy of D,
which will disappear eventually, leaving a dangling pointer in BB. So
the accessibility error is correct.

If you replace "in out" in Process with "access":

   procedure Process (L : access Listener) is abstract;

it works fine (with GNAT 6.2.1 on Windows).


Your original program had the same issue; I just missed it.

> I find usage of 'Access quite annoying, because I never really know
> when there is an exception whether it is becauise my code is incorrect
> or because the compiler is incorrect.

It is frustrating. 

It would be nice if the runtime error had some more info; in this case
"taking 'Access of a stack copy due to 'in out'" would be nice :).

Part of the problem is the implicit conversion from object to access
in Process:

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

The call to Foreach is effectively:

    Foreach (D'access, 2);

If you had written it that way, it would have been clearer what was
happening.

The moral here: if the body of the program needs an access value, pass
in an access value!

My code almost never uses 'Access, because it's better to create the
object via an allocator in the first place, and pass around access
values instead.

Thanks for this puzzle; it has helped me realize exactly why I do
this!

> The last simple example I wrote seems to indicate that GNAT has a
> bug, but I'm not an Ada expert ! If you also consider that there is
> a GNAT bug, I'll submit a bug to AdaCore.

I now think this is not a compiler bug.

-- 
-- Stephe



^ permalink raw reply	[flat|nested] 48+ messages in thread

* Re: Issue with GNAT GPL 2009 and GtkAda
  2009-06-26  9:31         ` Stephen Leake
@ 2009-06-26 11:18           ` Niklas Holsti
  2009-06-26 16:29             ` Damien Carbonne
                               ` (2 more replies)
  2009-06-26 21:03           ` Damien Carbonne
  1 sibling, 3 replies; 48+ messages in thread
From: Niklas Holsti @ 2009-06-26 11:18 UTC (permalink / raw)


 > 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.

-- 
Niklas Holsti
Tidorum Ltd
niklas holsti tidorum fi
       .      @       .



^ permalink raw reply	[flat|nested] 48+ messages in thread

* Re: Issue with GNAT GPL 2009 and GtkAda
  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 21:51             ` Randy Brukardt
  2009-06-27  9:56             ` Stephen Leake
  2 siblings, 1 reply; 48+ messages in thread
From: Damien Carbonne @ 2009-06-26 16:29 UTC (permalink / raw)


Niklas Holsti a �crit :
>  > 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 also thought that tagged types were always passed by reference, 
whatever the mode (in, out, in out) is.
I'll have to read Ada RM !
If this is true, it means that using in/out/in out modes is almost 
impossible in the code I write if this code must be mixed with code from 
third party libraries (like GtkAda) that use access almost everywhere. sad.



^ permalink raw reply	[flat|nested] 48+ messages in thread

* Re: Issue with GNAT GPL 2009 and GtkAda
  2009-06-26 16:29             ` Damien Carbonne
@ 2009-06-26 17:28               ` Dmitry A. Kazakov
  2009-06-26 19:27                 ` Damien Carbonne
  0 siblings, 1 reply; 48+ messages in thread
From: Dmitry A. Kazakov @ 2009-06-26 17:28 UTC (permalink / raw)


On Fri, 26 Jun 2009 18:29:11 +0200, Damien Carbonne wrote:

> Niklas Holsti a �crit :
>>  > 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 also thought that tagged types were always passed by reference, 
> whatever the mode (in, out, in out) is.

Correct.

> I'll have to read Ada RM !
> If this is true, it means that using in/out/in out modes is almost 
> impossible in the code I write if this code must be mixed with code from 
> third party libraries (like GtkAda) that use access almost everywhere. sad.

No, GtkAda does not use controlled or tagged types when it talks to Gtk.
Such types should not have C convention. Instead of that GtkAda associates
a C type with each tagged Ada one, which serves as a proxy. The address of
this C object can be obtained using the Get_Object call. You will often
find it in the implementation of GtkAda subroutines.

-- 
Regards,
Dmitry A. Kazakov
http://www.dmitry-kazakov.de



^ permalink raw reply	[flat|nested] 48+ messages in thread

* Re: Issue with GNAT GPL 2009 and GtkAda
  2009-06-26 17:28               ` Dmitry A. Kazakov
@ 2009-06-26 19:27                 ` Damien Carbonne
  2009-06-26 19:50                   ` Dmitry A. Kazakov
  0 siblings, 1 reply; 48+ messages in thread
From: Damien Carbonne @ 2009-06-26 19:27 UTC (permalink / raw)


Dmitry A. Kazakov a �crit :
>> If this is true, it means that using in/out/in out modes is almost 
>> impossible in the code I write if this code must be mixed with code from 
>> third party libraries (like GtkAda) that use access almost everywhere. sad.
> 
> No, GtkAda does not use controlled or tagged types when it talks to Gtk.
> Such types should not have C convention. Instead of that GtkAda associates
> a C type with each tagged Ada one, which serves as a proxy. The address of
> this C object can be obtained using the Get_Object call. You will often
> find it in the implementation of GtkAda subroutines.
> 

Of course, but I did not meant use of access types to interface C API.
Just some examples from Gtk.Tree_Model:

    function Get_Iter_First
      (Tree_Model : access Gtk_Tree_Model_Record) return Gtk_Tree_Iter;

    function Get_Path
      (Tree_Model : access Gtk_Tree_Model_Record;
       Iter       : Gtk_Tree_Iter) return Gtk_Tree_Path;

    procedure Next
      (Tree_Model : access Gtk_Tree_Model_Record;
       Iter       : in out Gtk_Tree_Iter);

Why use access everywhere ? In the case of functions, one could argue 
that "in out" is not possible. But aren't there any cases where in is 
sufficient for functions ? And for procedures ? Why not write what this:
    procedure Next
      (Tree_Model : in [out] Gtk_Tree_Model_Record;
       Iter       : in out Gtk_Tree_Iter);

One obvious issue is that modes must be guessed from comments in 
original C code, or from the C code itself. Thys may be hard to find 
automatically.


Damien






^ permalink raw reply	[flat|nested] 48+ messages in thread

* Re: Issue with GNAT GPL 2009 and GtkAda
  2009-06-26 19:27                 ` Damien Carbonne
@ 2009-06-26 19:50                   ` Dmitry A. Kazakov
  0 siblings, 0 replies; 48+ messages in thread
From: Dmitry A. Kazakov @ 2009-06-26 19:50 UTC (permalink / raw)


On Fri, 26 Jun 2009 21:27:04 +0200, Damien Carbonne wrote:

> Dmitry A. Kazakov a �crit :
>>> If this is true, it means that using in/out/in out modes is almost 
>>> impossible in the code I write if this code must be mixed with code from 
>>> third party libraries (like GtkAda) that use access almost everywhere. sad.
>> 
>> No, GtkAda does not use controlled or tagged types when it talks to Gtk.
>> Such types should not have C convention. Instead of that GtkAda associates
>> a C type with each tagged Ada one, which serves as a proxy. The address of
>> this C object can be obtained using the Get_Object call. You will often
>> find it in the implementation of GtkAda subroutines.
> 
> Of course, but I did not meant use of access types to interface C API.
> Just some examples from Gtk.Tree_Model:
> 
>     function Get_Iter_First
>       (Tree_Model : access Gtk_Tree_Model_Record) return Gtk_Tree_Iter;
> 
>     function Get_Path
>       (Tree_Model : access Gtk_Tree_Model_Record;
>        Iter       : Gtk_Tree_Iter) return Gtk_Tree_Path;
> 
>     procedure Next
>       (Tree_Model : access Gtk_Tree_Model_Record;
>        Iter       : in out Gtk_Tree_Iter);
> 
> Why use access everywhere ? In the case of functions, one could argue 
> that "in out" is not possible. But aren't there any cases where in is 
> sufficient for functions ? And for procedures ? Why not write what this:
>     procedure Next
>       (Tree_Model : in [out] Gtk_Tree_Model_Record;
>        Iter       : in out Gtk_Tree_Iter);
> 
> One obvious issue is that modes must be guessed from comments in 
> original C code, or from the C code itself. Thys may be hard to find 
> automatically.

The reason for that (as I can guess) is that GtkAda tries to mimic Gtk. So
that you call Get_Iter_First using Gtk_Tree_Model rather than
Gtk_Tree_Model_Record. Since Gtk_Tree_Model is an access type,
Get_Iter_First must deal with access Gtk_Tree_Model_Record in order to
become a primitive operation.

If I designed GtkAda I would probably tried to make it thicker hiding Gtk
reference counting behind Ada controlled types. Note that this would be
extremely tedious to do, because Ada lacks any means for building related
hierarchies of types. E.g. of handles (Gtk_Tree_Model) and objects they
refer to (Gtk_Tree_Model_Record).

The only way that works more or less automatic in Ada is anonymous access
types *because* of implicit conversion of pointers (named to anonymous).

-- 
Regards,
Dmitry A. Kazakov
http://www.dmitry-kazakov.de



^ permalink raw reply	[flat|nested] 48+ messages in thread

* Re: Issue with GNAT GPL 2009 and GtkAda
  2009-06-26  9:31         ` Stephen Leake
  2009-06-26 11:18           ` Niklas Holsti
@ 2009-06-26 21:03           ` Damien Carbonne
  2009-06-27 11:21             ` Stephen Leake
  2009-06-30  0:48             ` Adam Beneschan
  1 sibling, 2 replies; 48+ messages in thread
From: Damien Carbonne @ 2009-06-26 21:03 UTC (permalink / raw)


Stephen Leake a �crit :
> The problem is clear here.
> 
> "D : in out Derived" is allowed to create a copy of the actual
> parameter. Thus the 'Access in Foreach could be on a stack copy of D,
> which will disappear eventually, leaving a dangling pointer in BB. So
> the accessibility error is correct.
> 
> If you replace "in out" in Process with "access":
> 
>    procedure Process (L : access Listener) is abstract;
> 
> it works fine (with GNAT 6.2.1 on Windows).
> 
> 
> Your original program had the same issue; I just missed it.
> 
>> I find usage of 'Access quite annoying, because I never really know
>> when there is an exception whether it is becauise my code is incorrect
>> or because the compiler is incorrect.
> 
> It is frustrating. 
> 
> It would be nice if the runtime error had some more info; in this case
> "taking 'Access of a stack copy due to 'in out'" would be nice :).
> 
> Part of the problem is the implicit conversion from object to access
> in Process:
> 
>    procedure Process (D : in out Derived) is
>    begin
>       Ada.Text_IO.Put_Line ("Process");
>       D.Foreach (2);
>    end Process;
> 
> The call to Foreach is effectively:
> 
>     Foreach (D'access, 2);
> 
> If you had written it that way, it would have been clearer what was
> happening.
> 
> The moral here: if the body of the program needs an access value, pass
> in an access value!
> 
> My code almost never uses 'Access, because it's better to create the
> object via an allocator in the first place, and pass around access
> values instead.
> 
> Thanks for this puzzle; it has helped me realize exactly why I do
> this!
> 
>> The last simple example I wrote seems to indicate that GNAT has a
>> bug, but I'm not an Ada expert ! If you also consider that there is
>> a GNAT bug, I'll submit a bug to AdaCore.
> 
> I now think this is not a compiler bug.
> 

If what you say is true, why does the following example work fine (using 
GNAT), without any compiler warning or execution error ?
As I told in a previous message, I don't want to change the "in out" 
mode of Interface (representing the code I wrote and that is independant 
of GtkAda or any graphical toolkit), because one day it could be used in 
cunjunction with third party code that uses access !
Otherwise, it would almost certainly mean that one needs to use access 
almost everywhere, even if it is meaningless.

The following example works as I expect. If it should not, I have to do 
something (go back to school ?) ;-)

-------------------------------------------------------------------
package Pack02 is
    type Base is tagged null record;

    procedure P1M (X : in out Base; Max_Depth : Positive);
    procedure P1A (X : access Base; Max_Depth : Positive);

    procedure P2M (X : in Base; Max_Depth : Positive);
    procedure P2A (X : access constant Base; Max_Depth : Positive);

    procedure P3M (X : out Base; Max_Depth : Positive);
    procedure P3A (X : access Base; Max_Depth : Positive);

    procedure Main;
end Pack02;
-------------------------------------------------------------------
with Ada.Text_IO;

package body Pack02 is

    function Indent (X : Positive) return String is
       S : constant String (1 .. 6 - X) := (others => ' ');
    begin
       return S;
    end Indent;

    procedure P1M (X : in out Base; Max_Depth : Positive) is
    begin
       Ada.Text_IO.Put_Line (Indent (Max_Depth) & "P1M" & Positive'Image 
(Max_Depth));
       if Max_Depth > 1 then
          P1A (X'Access, Max_Depth - 1);
          X.P1A (Max_Depth - 1);
       end if;
    end P1M;

    procedure P1A (X : access Base; Max_Depth : Positive) is
    begin
       Ada.Text_IO.Put_Line (Indent (Max_Depth) & "P1A" & Positive'Image 
(Max_Depth));
       if Max_Depth > 1 then
          P1M (X.all, Max_Depth - 1);
          X.P1M (Max_Depth - 1);
       end if;
    end P1A;

    procedure P2M (X : in Base; Max_Depth : Positive) is
    begin
       Ada.Text_IO.Put_Line (Indent (Max_Depth) & "P2M" & Positive'Image 
(Max_Depth));
       if Max_Depth > 1 then
          P2A (X'Access, Max_Depth - 1);
          X.P2A (Max_Depth - 1);
       end if;
    end P2M;

    procedure P2A (X : access constant Base; Max_Depth : Positive) is
    begin
       Ada.Text_IO.Put_Line (Indent (Max_Depth) & "P2A" & Positive'Image 
(Max_Depth));
       if Max_Depth > 1 then
          P2M (X.all, Max_Depth - 1);
          X.P2M (Max_Depth - 1);
       end if;
    end P2A;

    procedure P3M (X : out Base; Max_Depth : Positive) is
    begin
       Ada.Text_IO.Put_Line (Indent (Max_Depth) & "P3M" & Positive'Image 
(Max_Depth));
       if Max_Depth > 1 then
          P3A (X'Access, Max_Depth - 1);
          X.P3A (Max_Depth - 1);
       end if;
    end P3M;

    procedure P3A (X : access Base; Max_Depth : Positive) is
    begin
       Ada.Text_IO.Put_Line (Indent (Max_Depth) & "P3A" & Positive'Image 
(Max_Depth));
       if Max_Depth > 1 then
          P3M (X.all, Max_Depth - 1);
          X.P3M (Max_Depth - 1);
       end if;
    end P3A;

    procedure main is
       X : aliased Base;
    begin
       P1M (X, 3);
       P2M (X, 3);
       P3M (X, 3);
    end main;

end Pack02;
-------------------------------------------------------------------
with Pack02;
procedure Main02 is
begin
    Pack02.Main;
end Main02;
-- Output:
--
--  P1M 3
--    P1A 2
--       P1M 1
--       P1M 1
--     P1A 2
--       P1M 1
--       P1M 1
--  P2M 3
--    P2A 2
--      P2M 1
--      P2M 1
--    P2A 2
--      P2M 1
--      P2M 1
--  P3M 3
--    P3A 2
--      P3M 1
--      P3M 1
--    P3A 2
--      P3M 1
--      P3M 1
-------------------------------------------------------------------



^ permalink raw reply	[flat|nested] 48+ messages in thread

* Re: Issue with GNAT GPL 2009 and GtkAda
  2009-06-26  7:20         ` Dmitry A. Kazakov
  2009-06-26  8:17           ` Georg Bauhaus
@ 2009-06-26 21:31           ` Randy Brukardt
  2009-06-27  7:53             ` Dmitry A. Kazakov
  1 sibling, 1 reply; 48+ messages in thread
From: Randy Brukardt @ 2009-06-26 21:31 UTC (permalink / raw)


"Dmitry A. Kazakov" <mailbox@dmitry-kazakov.de> wrote in message 
news:10ym4hltpwd4n$.1hcayfi4xidg3.dlg@40tude.net...
...
> The only purpose of
>
>   Ptr : access T := new T;
>
> I can guess is allocation of a large scoped object on the heap. It would 
> be
> better if there were a syntax for that, which does not involve access
> types.

I don't see the point. There is no language semantic reason not to simply 
declare this object on the stack:

   O : T;

Any reason not to is based on the limitations of a particular 
implementation. I don't see any good reason to pollute the language for that 
reason (it would be better for the implementation to relax those limitations 
if they are a problem for their customers).

                                        Randy.





^ permalink raw reply	[flat|nested] 48+ messages in thread

* Re: Issue with GNAT GPL 2009 and GtkAda
  2009-06-26  8:52             ` Dmitry A. Kazakov
@ 2009-06-26 21:38               ` Randy Brukardt
  2009-06-27  7:47                 ` Dmitry A. Kazakov
  0 siblings, 1 reply; 48+ messages in thread
From: Randy Brukardt @ 2009-06-26 21:38 UTC (permalink / raw)


"Dmitry A. Kazakov" <mailbox@dmitry-kazakov.de> wrote in message 
news:1hi0km5xe1802.17l3qjn1g9525$.dlg@40tude.net...
...
> I would remove anonymous access types altogether, fixing the real language
> problems, which led to introducing them in first place.

I don't think that there were any *real* language reasons for introducing 
them; the reasons came from wanting to make Ada more appealing to C and Java 
programmers. (A horrible reason for language design, IMHO.) They can be used 
to work around some of Ada's other limitations.

In any case, it appears likely that Amendment 2 will repeal the prohibition 
on "in out" parameters on functions (adding a conservative call check to 
prevent obvious ordering dependencies).

We're also planning on adding a way to force by-reference parameter passing. 
The motivating use is for the containers, but I'm sure it will find other 
uses as well.

As far as the use of class-wide components, I think that would be easily 
fixed by just allowing them. They would be fairly easy to implement in 
Janus/Ada. (I'd also make it required to support any size of discriminant, 
banning max-size only implementations). But I realize that that would be a 
problem for safety-critical uses (there would be implicit allocation on some 
assignments), so we'd also need a fairly strong set of restrictions for such 
users.

That would reduce the need to use access types some more. (But it can never 
be completely eliminated; sometimes you really do need reference semantics, 
especially for returns.)

                                              Randy.






^ permalink raw reply	[flat|nested] 48+ messages in thread

* Re: Issue with GNAT GPL 2009 and GtkAda
  2009-06-26  8:39       ` Alex R. Mosteo
  2009-06-26  9:07         ` Dmitry A. Kazakov
@ 2009-06-26 21:40         ` Randy Brukardt
  2009-06-29 10:04           ` Alex R. Mosteo
  1 sibling, 1 reply; 48+ messages in thread
From: Randy Brukardt @ 2009-06-26 21:40 UTC (permalink / raw)


"Alex R. Mosteo" <alejandro@mosteo.com> wrote in message 
news:7ajfrgF1vdsnlU1@mid.individual.net...
...
>> declare
>>    Ptr : access T := new T;
>> begin
>>    ...
>>    External_Ptr := Ptr.all'Uchecked_Access; -- Copy the pointer
>>    ...
>> end;  -- Now External_Ptr is dangling, because the object is freed.
>
> If I understand correctly, this is because the type of Ptr goes out of
> scope?
>
> I strongly suspect that Gnat does not behave this way, but I should test 
> it.

Gnat would be wrong if it does *not* behave this way. (Janus/Ada has this 
bug currently.) The master of the anonymous access type is the declare 
block, and it has to be finalized at the end of the scope. I suppose you 
could leave the memory around, but the object has to be finalized (as 
Dmitry's example shows).

                        Randy.





^ permalink raw reply	[flat|nested] 48+ messages in thread

* Re: Issue with GNAT GPL 2009 and GtkAda
  2009-06-26 11:18           ` Niklas Holsti
  2009-06-26 16:29             ` Damien Carbonne
@ 2009-06-26 21:51             ` Randy Brukardt
  2009-06-27 11:11               ` Stephen Leake
  2009-06-30 15:59               ` Adam Beneschan
  2009-06-27  9:56             ` Stephen Leake
  2 siblings, 2 replies; 48+ messages in thread
From: Randy Brukardt @ 2009-06-26 21:51 UTC (permalink / raw)


>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. (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).

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.

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.

The aliased parameters that we're looking to add to Ada will mitigate this 
problem somewhat, but only a little. The addition of "in out" parameters to 
functions will mitigate it some more (eliminating many uses of access 
parameters). We've pretty much given up on fixing the accessibility model in 
favor of changes that allow using fewer access types. We would have liked to 
fix it, but compatibility and overhead concerns make it impossible.

                               Randy.





^ permalink raw reply	[flat|nested] 48+ messages in thread

* Re: Issue with GNAT GPL 2009 and GtkAda
  2009-06-26 21:38               ` Randy Brukardt
@ 2009-06-27  7:47                 ` Dmitry A. Kazakov
  2009-06-29 21:59                   ` Randy Brukardt
  0 siblings, 1 reply; 48+ messages in thread
From: Dmitry A. Kazakov @ 2009-06-27  7:47 UTC (permalink / raw)


On Fri, 26 Jun 2009 16:38:45 -0500, Randy Brukardt wrote:

> "Dmitry A. Kazakov" <mailbox@dmitry-kazakov.de> wrote in message 
> news:1hi0km5xe1802.17l3qjn1g9525$.dlg@40tude.net...
> ...
>> I would remove anonymous access types altogether, fixing the real language
>> problems, which led to introducing them in first place.
> 
> I don't think that there were any *real* language reasons for introducing 
> them; the reasons came from wanting to make Ada more appealing to C and Java 
> programmers. (A horrible reason for language design, IMHO.) They can be used 
> to work around some of Ada's other limitations.

Even so, pointers were introduced in C and Java to for a reason. If this
reason did not apply to Ada, then programmers would have ignored anonymous
access types as superfluous. That did not happen.

> In any case, it appears likely that Amendment 2 will repeal the prohibition 
> on "in out" parameters on functions (adding a conservative call check to 
> prevent obvious ordering dependencies).

Promising...

> We're also planning on adding a way to force by-reference parameter passing. 
> The motivating use is for the containers, but I'm sure it will find other 
> uses as well.

This makes no sense to me. It is another mistake of making after C++. There
is no reason why by-reference must be enforced anywhere if not required by
the type.

> As far as the use of class-wide components, I think that would be easily 
> fixed by just allowing them.

That would make objects non-contiguous. It is not obvious to me how that
will work with streams and pools. I prefer a more transparent model when
all components of a constrained object are constrained.

> That would reduce the need to use access types some more. (But it can never 
> be completely eliminated; sometimes you really do need reference semantics, 
> especially for returns.)

No, this is the mental trap. If something requires by-reference semantics
that is not a return. Considering containers:

   A (I) := X;

It is a semantic mistake to treat A (I) as a function "returning"
something. This can only lead to introducing more and more strange
constructs like limited aggregates, return statements and other mess. 

   A (I) := X;

must be treated as a syntax sugar for a procedure call

   Put (A, I, X);

-- 
Regards,
Dmitry A. Kazakov
http://www.dmitry-kazakov.de



^ permalink raw reply	[flat|nested] 48+ messages in thread

* Re: Issue with GNAT GPL 2009 and GtkAda
  2009-06-26 21:31           ` Randy Brukardt
@ 2009-06-27  7:53             ` Dmitry A. Kazakov
  0 siblings, 0 replies; 48+ messages in thread
From: Dmitry A. Kazakov @ 2009-06-27  7:53 UTC (permalink / raw)


On Fri, 26 Jun 2009 16:31:20 -0500, Randy Brukardt wrote:

> "Dmitry A. Kazakov" <mailbox@dmitry-kazakov.de> wrote in message 
> news:10ym4hltpwd4n$.1hcayfi4xidg3.dlg@40tude.net...
> ...
>> The only purpose of
>>
>>   Ptr : access T := new T;
>>
>> I can guess is allocation of a large scoped object on the heap. It would be
>> better if there were a syntax for that, which does not involve access types.
> 
> I don't see the point. There is no language semantic reason not to simply 
> declare this object on the stack:
> 
>    O : T;
> 
> Any reason not to is based on the limitations of a particular 
> implementation. I don't see any good reason to pollute the language for that 
> reason (it would be better for the implementation to relax those limitations 
> if they are a problem for their customers).

Agreed.

-- 
Regards,
Dmitry A. Kazakov
http://www.dmitry-kazakov.de



^ permalink raw reply	[flat|nested] 48+ messages in thread

* Re: Issue with GNAT GPL 2009 and GtkAda
  2009-06-26  9:07         ` Dmitry A. Kazakov
@ 2009-06-27  9:53           ` Stephen Leake
  0 siblings, 0 replies; 48+ messages in thread
From: Stephen Leake @ 2009-06-27  9:53 UTC (permalink / raw)


"Dmitry A. Kazakov" <mailbox@dmitry-kazakov.de> writes:

> Here is a test:
>
> with Ada.Finalization;
> with Ada.Text_IO;  use Ada.Text_IO;
>
> procedure Test_Anonymous_Access is
>    package P is
>       type T is new Ada.Finalization.Controlled with null record;
>       overriding procedure Finalize (X : in out T);
>    end P;
>    package body P is
>       procedure Finalize (X : in out T) is
>       begin
>          Put_Line ("Finalized");
>       end Finalize;
>    end P;
>    use P;
> begin
>    declare
>       X : access T := new T;
>    begin
>       Put_Line ("Created");
>    end;
>    Put_Line ("Left the scope");
> end Test_Anonymous_Access;
>
> It should print:
>
> Created
> Finalized
> Left the scope

GNAT 6.2.1 on Windows does this.

-- 
-- Stephe



^ permalink raw reply	[flat|nested] 48+ messages in thread

* Re: Issue with GNAT GPL 2009 and GtkAda
  2009-06-26 11:18           ` Niklas Holsti
  2009-06-26 16:29             ` Damien Carbonne
  2009-06-26 21:51             ` Randy Brukardt
@ 2009-06-27  9:56             ` Stephen Leake
  2 siblings, 0 replies; 48+ messages in thread
From: Stephen Leake @ 2009-06-27  9:56 UTC (permalink / raw)


Niklas Holsti <niklas.holsti@tidorum.invalid> writes:

>> 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.

Right; I realized that this morning.

So we're back to a compiler bug.

I have a support contract with AdaCore, and this issue has come up in
my real work, so I'll report it.

-- 
-- Stephe



^ permalink raw reply	[flat|nested] 48+ messages in thread

* Re: Issue with GNAT GPL 2009 and GtkAda
  2009-06-26 21:51             ` Randy Brukardt
@ 2009-06-27 11:11               ` Stephen Leake
  2009-06-27 17:04                 ` Robert A Duff
  2009-06-29 22:11                 ` Randy Brukardt
  2009-06-30 15:59               ` Adam Beneschan
  1 sibling, 2 replies; 48+ messages in thread
From: Stephen Leake @ 2009-06-27 11:11 UTC (permalink / raw)


"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



^ permalink raw reply	[flat|nested] 48+ messages in thread

* Re: Issue with GNAT GPL 2009 and GtkAda
  2009-06-26 21:03           ` Damien Carbonne
@ 2009-06-27 11:21             ` Stephen Leake
  2009-06-27 12:25               ` Damien Carbonne
  2009-06-30  0:48             ` Adam Beneschan
  1 sibling, 1 reply; 48+ messages in thread
From: Stephen Leake @ 2009-06-27 11:21 UTC (permalink / raw)


Damien Carbonne <damien.carbonne@free.fr> writes:

> Stephen Leake a �crit :
>> The problem is clear here.
>>
>> "D : in out Derived" is allowed to create a copy of the actual
>> parameter. Thus the 'Access in Foreach could be on a stack copy of D,
>> which will disappear eventually, leaving a dangling pointer in BB. So
>> the accessibility error is correct.
>>
>> ...
>
> If what you say is true, why does the following example work fine
> (using GNAT), without any compiler warning or execution error ?

Because the object being passed is explicitly labeled "aliased"; that
means 'Access is allowed. See my other post from today.

> As I told in a previous message, I don't want to change the "in out"
> mode of Interface (representing the code I wrote and that is
> independant of GtkAda or any graphical toolkit), because one day it
> could be used in cunjunction with third party code that uses access
> ! Otherwise, it would almost certainly mean that one needs to use
> access almost everywhere, even if it is meaningless.

It's not meaningless. It tells the user that the body needs an access
value. 

Hmm. I guess you mean "If I use a backend (other than GtkAda) that
doesn't require access values, the use of 'access' in my frontend
would be meaningless".

Yes, that's true. Or at least, it only tells the user "if you switch
to some other backend, that might need an access value".

It's the price you pay for supporting multiple backends; you must
support the worst feature of the entire set :).

-- 
-- Stephe



^ permalink raw reply	[flat|nested] 48+ messages in thread

* Re: Issue with GNAT GPL 2009 and GtkAda
  2009-06-27 11:21             ` Stephen Leake
@ 2009-06-27 12:25               ` Damien Carbonne
  2009-06-27 12:35                 ` Damien Carbonne
  0 siblings, 1 reply; 48+ messages in thread
From: Damien Carbonne @ 2009-06-27 12:25 UTC (permalink / raw)


Stephen Leake a �crit :
>>>
>>> ...
>> If what you say is true, why does the following example work fine
>> (using GNAT), without any compiler warning or execution error ?
> 
> Because the object being passed is explicitly labeled "aliased"; that
> means 'Access is allowed. See my other post from today.
> 
In the example, there is only one place where an object is explicitly 
declared and labeled "aliased" : in Main.
In signatures of P[123]M, X is not aliased (only in, out or in out modes).
There is no "aliased" key word in the bodies of corresponding procedures.

e.g.:
    procedure P1M (X : in out Base; Max_Depth : Positive) is
    begin
       Ada.Text_IO.Put_Line (Indent (Max_Depth) & "P1M" & Positive'Image 
(Max_Depth));
       if Max_Depth > 1 then
          P1A (X'Access, Max_Depth - 1); -- Here use of Access on a tyoe 
that is implicitely aliased
          X.P1A (Max_Depth - 1);
       end if;
    end P1M;
Nowhere X is explicitely declared aliased. It is only an "in out" tagged 
parameter. It is however possible to use X'Access, in my mind because X 
is tagged (and so passed by reference).

Do you mean that the fact that X is labeled "aliased" in Main is 
propagated everywhere it is used ? I would find this strange (and 
certainly needing a special support from compiler).

I really don't see the difference with the initial problem, where all 
types are tagged types or interfaces.



^ permalink raw reply	[flat|nested] 48+ messages in thread

* Re: Issue with GNAT GPL 2009 and GtkAda
  2009-06-27 12:25               ` Damien Carbonne
@ 2009-06-27 12:35                 ` Damien Carbonne
  2009-06-29 22:15                   ` Randy Brukardt
  0 siblings, 1 reply; 48+ messages in thread
From: Damien Carbonne @ 2009-06-27 12:35 UTC (permalink / raw)


Damien Carbonne a �crit :
> Stephen Leake a �crit :
>>>>
>>>> ...
>>> If what you say is true, why does the following example work fine
>>> (using GNAT), without any compiler warning or execution error ?
>>
>> Because the object being passed is explicitly labeled "aliased"; that
>> means 'Access is allowed. See my other post from today.
>>
> In the example, there is only one place where an object is explicitly 
> declared and labeled "aliased" : in Main.
> In signatures of P[123]M, X is not aliased (only in, out or in out modes).
> There is no "aliased" key word in the bodies of corresponding procedures.
> 
> e.g.:
>    procedure P1M (X : in out Base; Max_Depth : Positive) is
>    begin
>       Ada.Text_IO.Put_Line (Indent (Max_Depth) & "P1M" & Positive'Image 
> (Max_Depth));
>       if Max_Depth > 1 then
>          P1A (X'Access, Max_Depth - 1); -- Here use of Access on a tyoe 
> that is implicitely aliased
>          X.P1A (Max_Depth - 1);
>       end if;
>    end P1M;
> Nowhere X is explicitely declared aliased. It is only an "in out" tagged 
> parameter. It is however possible to use X'Access, in my mind because X 
> is tagged (and so passed by reference).
> 
> Do you mean that the fact that X is labeled "aliased" in Main is 
> propagated everywhere it is used ? I would find this strange (and 
> certainly needing a special support from compiler).
> 
> I really don't see the difference with the initial problem, where all 
> types are tagged types or interfaces.

I would add that if declaration of X is changed to:
    type Base is null record; -- no more tagged

and that the object notation lines are removed, the compiler complains:

pack03.adb:15:15: prefix of "Access" attribute must be aliased
...

    procedure P1M (X : in out Base; Max_Depth : Positive) is
    begin
       Ada.Text_IO.Put_Line (Indent (Max_Depth) & "P1M" & Positive'Image 
(Max_Depth));
       if Max_Depth > 1 then
          P1A (X'Access, Max_Depth - 1); -- line 15
       end if;
    end P1M;

This behaves as expected (by me).
So a tagged type is really and always aliased, whatever its mode (in, 
out, in out) is. At least, this is what understand from those examples.



^ permalink raw reply	[flat|nested] 48+ messages in thread

* Re: Issue with GNAT GPL 2009 and GtkAda
  2009-06-27 11:11               ` Stephen Leake
@ 2009-06-27 17:04                 ` Robert A Duff
  2009-06-30 11:11                   ` Stephen Leake
  2009-06-29 22:11                 ` Randy Brukardt
  1 sibling, 1 reply; 48+ messages in thread
From: Robert A Duff @ 2009-06-27 17:04 UTC (permalink / raw)


Stephen Leake <stephen_leake@stephe-leake.org> writes:

> "Randy Brukardt" <randy@rrsoftware.com> writes:
>
>>>Niklas Holsti" <niklas.holsti@tidorum.invalid> wrote in message 
>>>news:4a44ae4e$0$6295$4f793bc4@news.tdc.fi...
>> I think he means that the accessibility level of a parameter is that of a 
>> local object, ...

Yes, the accessibility level of a formal parameter is like a local
nested inside the procedure.  This is true for tagged and untagged.

>...as it *might* have been passed by copy. 

Not for tagged -- those are always passed by reference.

> 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.

The compiler is just doing what the language rules require.

Note that "must be passed by reference" does not imply "we could allow
'Access".  Consider:

    type T_Ref is access all T;
    Global : T_Ref;

    procedure P (X : in out T) is -- Suppose T is tagged.
    begin
        Global := X'Access; -- Illegal!
    end P;

    procedure Q (...) is
        Local : aliased T;
    begin
        P (Local);
    end Q;

After calling Q, Global is a dangling pointer.  The language design rule
is:  If you do anything that _might_ create a dangling pointer, you
have to use 'Unchecked_Access (and take care).

The original example is similar to this, except the error
is caught at run time, because you have an access parameter.
Dynamic accessibility levels are a mistake, in my opinion!

>> (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);

The accessibility level of D is "nested inside Process", so that
information is passed to Foreach at run time.  (Note that there's
an implicit D'Access here.)  Foreach then tries to make a value
of type Base_Ref point to it, which fails at run time.  This is
necessary because you might put:

    Some_Global := BB;

in Foreach, which would create a dangling pointer.  If you know
you're not going to do that, you can use 'Unchecked_Access.

I don't see any compiler bug, here.

>    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.

It allows 'Access to work if the resulting access type is nested.
It allows 'Unchecked_Access to work.

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

The actual history is that during Ada 9X, the design team proposed to
allow "aliased" on parameters.  Reviewers didn't like that, partly
because "aliased" was seen as dangerous, and partly because the
language was getting too big and complicated.  So we took it out.

But then after working many examples, we realized that you really
need aliased parameters sometimes, especially in the case of
tagged types.  So we decided that all tagged parameters are
aliased, and if you need aliased parameters for an untagged
type, you just make it tagged even though you didn't want to.
This was acceptable to reviewers, because it doesn't involve
syntax, and many people view "additional syntax" as a bigger
language change than "additional rules".

In my view, this makes the language _more_ complicated, and if
"aliased" is dangerous, surely implicit aliased is even more so.

Allowing explicitly aliased parameters would lead to a simpler rule
about which names denote an aliased object:

    1. If the declaration of X says "aliased", then the name "X"
       denotes an aliased object.

    2. For any X, X.all denotes an aliased object (it has to,
       because the whole point of "aliased" is that it means
       "you can have access values pointing to it" -- the fact
       that X points to X.all implies X.all must be aliased).

But this wouldn't necessary change the accessibility rules -- you
still can't take 'Access of a local and return a global pointer.

>> 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.

No, I don't think they're overly conservative -- see my dangling pointer
example above.  Well, of course compile-time checks are always
conservative (see halting problem!).  The only way to be less
conservative would be to do more checks at run time, which
is heading in the wrong direction.

> 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?

In most compilers, the accessibility level is represented as an integer,
and this integer is passed as an extra implicit parameter whenever
you have an access parameter.  So your Foreach procedure really
has three parameters: B, I, and the accessibility level of B.all.

Except that the extra parameter is not used if the Convention is
some foreign language like C, because obviously that would
mess things up.

>> 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.

Yup.

> 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. ...

This is just saying that if you say "Formal_Param := ...;", the actual param
will be modified immediately.  So, for example, if you then
raise an exception, the actual will have been modified, and
you can see that after handling the exception in the caller.
If it were a by-copy type, then you know the actual will NOT
have been modified.  And for other types, you don't know
-- it MIGHT have been modified.

> I can see why this is complicated :)

It is indeed.

C is much simpler in this area, because everything is aliased,
and you can create dangling pointers willy-nilly.  (Well,
almost everything is aliased.)

- Bob



^ permalink raw reply	[flat|nested] 48+ messages in thread

* Re: Issue with GNAT GPL 2009 and GtkAda
  2009-06-26 21:40         ` Randy Brukardt
@ 2009-06-29 10:04           ` Alex R. Mosteo
  0 siblings, 0 replies; 48+ messages in thread
From: Alex R. Mosteo @ 2009-06-29 10:04 UTC (permalink / raw)


Randy Brukardt wrote:

> "Alex R. Mosteo" <alejandro@mosteo.com> wrote in message
> news:7ajfrgF1vdsnlU1@mid.individual.net...
> ...
>>> declare
>>>    Ptr : access T := new T;
>>> begin
>>>    ...
>>>    External_Ptr := Ptr.all'Uchecked_Access; -- Copy the pointer
>>>    ...
>>> end;  -- Now External_Ptr is dangling, because the object is freed.
>>
>> If I understand correctly, this is because the type of Ptr goes out of
>> scope?
>>
>> I strongly suspect that Gnat does not behave this way, but I should test
>> it.
> 
> Gnat would be wrong if it does *not* behave this way. (Janus/Ada has this
> bug currently.) The master of the anonymous access type is the declare
> block, and it has to be finalized at the end of the scope. I suppose you
> could leave the memory around, but the object has to be finalized (as
> Dmitry's example shows).

No, indeed GNAT GPL 2009 at least is correct. It was my fault; I was almost 
sure of having been doing this in such a way that would have caused dangling 
pointers and immediate crashes. Since this didn't happen, I thought it was 
the compiler's fault. In reality, my remembrance was wrong and in practice 
it was a declaration at the library level so it couldn't happen.

Not nice though, I was completely unaware and that makes me uneasy.



^ permalink raw reply	[flat|nested] 48+ messages in thread

* Re: Issue with GNAT GPL 2009 and GtkAda
  2009-06-27  7:47                 ` Dmitry A. Kazakov
@ 2009-06-29 21:59                   ` Randy Brukardt
  2009-06-30  8:31                     ` Dmitry A. Kazakov
  0 siblings, 1 reply; 48+ messages in thread
From: Randy Brukardt @ 2009-06-29 21:59 UTC (permalink / raw)


"Dmitry A. Kazakov" <mailbox@dmitry-kazakov.de> wrote in message 
news:u7txi934iaog$.gw40yhq8811x.dlg@40tude.net...
> On Fri, 26 Jun 2009 16:38:45 -0500, Randy Brukardt wrote:
...
>> We're also planning on adding a way to force by-reference parameter 
>> passing.
>> The motivating use is for the containers, but I'm sure it will find other
>> uses as well.
>
> This makes no sense to me. It is another mistake of making after C++. 
> There
> is no reason why by-reference must be enforced anywhere if not required by
> the type.

If you need "return by-reference" (however that is described), you need to 
pass the objects involved by-reference.

>> As far as the use of class-wide components, I think that would be easily
>> fixed by just allowing them.
>
> That would make objects non-contiguous. It is not obvious to me how that
> will work with streams and pools. I prefer a more transparent model when
> all components of a constrained object are constrained.

Well, Ada has always allowed non-continguous objects. There is no problem 
with streams: the stream attributes take care of any non-contiguous parts. 
As for pools, multiple calls to Allocate are allowed; again there is no 
requirement that the objects are contiguous. (That's been confirmed by 
AI05-0107-1, but it has always been true for Ada 95; there are plenty of 
AARM notes making that clear).

>> That would reduce the need to use access types some more. (But it can 
>> never
>> be completely eliminated; sometimes you really do need reference 
>> semantics,
>> especially for returns.)
>
> No, this is the mental trap. If something requires by-reference semantics
> that is not a return. Considering containers:
>
>   A (I) := X;
>
> It is a semantic mistake to treat A (I) as a function "returning"
> something. This can only lead to introducing more and more strange
> constructs like limited aggregates, return statements and other mess.
>
>   A (I) := X;
>
> must be treated as a syntax sugar for a procedure call
>
>   Put (A, I, X);

That works for full object assignment, but not in any sane way for in-place 
component updating. And full object assignment really doesn't need any 
special syntax (Replace_Element works just fine); the problem is when you 
need to update a single element of a container which is itself an element. 
It doesn't make sense to try to think of these sorts of operations as a 
single procedure.

                                    Randy.






^ permalink raw reply	[flat|nested] 48+ messages in thread

* Re: Issue with GNAT GPL 2009 and GtkAda
  2009-06-27 11:11               ` Stephen Leake
  2009-06-27 17:04                 ` Robert A Duff
@ 2009-06-29 22:11                 ` Randy Brukardt
  2009-06-30 11:13                   ` Stephen Leake
  1 sibling, 1 reply; 48+ messages in thread
From: Randy Brukardt @ 2009-06-29 22:11 UTC (permalink / raw)


"Stephen Leake" <stephen_leake@stephe-leake.org> wrote in message 
news:uljnej5hp.fsf@stephe-leake.org...
...
> 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"'.

Aside: The "blank screen" problem seems to be somewhere between our web 
server and the broad Internet, because it sometimes happens when I surf out 
as well as surf in. It seems to be caused by overloading with too many 
requests (especially a problem because of spammers constantly pounding our 
mail and web servers); usually all that you need to do to deal with it is 
click on the "Refresh" button.

I suspect that you could get similar effects with other browsers, but I 
don't have any first-hand knowledge of that, because I rarely use other 
browsers (and that seems to be true of the vast majority of the humans that 
visit our web site as well).

                                                  Randy.





^ permalink raw reply	[flat|nested] 48+ messages in thread

* Re: Issue with GNAT GPL 2009 and GtkAda
  2009-06-27 12:35                 ` Damien Carbonne
@ 2009-06-29 22:15                   ` Randy Brukardt
  2009-07-01 19:22                     ` Damien Carbonne
  0 siblings, 1 reply; 48+ messages in thread
From: Randy Brukardt @ 2009-06-29 22:15 UTC (permalink / raw)


"Damien Carbonne" <damien.carbonne@free.fr> wrote in message 
news:4a46121a$0$414$426a74cc@news.free.fr...
...
> This behaves as expected (by me).
> So a tagged type is really and always aliased, whatever its mode (in, out, 
> in out) is. At least, this is what understand from those examples.

That's not right, unfortunately. Tagged *parameters* are always considered 
aliased, but other kinds of tagged objects are not (necessarily) considered 
aliased. The designated object of an access value is considered aliased, 
though.

Bob explained this in more detail.

                                       Randy.





^ permalink raw reply	[flat|nested] 48+ messages in thread

* Re: Issue with GNAT GPL 2009 and GtkAda
  2009-06-26 21:03           ` Damien Carbonne
  2009-06-27 11:21             ` Stephen Leake
@ 2009-06-30  0:48             ` Adam Beneschan
  2009-06-30 11:18               ` Stephen Leake
  1 sibling, 1 reply; 48+ messages in thread
From: Adam Beneschan @ 2009-06-30  0:48 UTC (permalink / raw)


On Jun 26, 2:03 pm, Damien Carbonne <damien.carbo...@free.fr> wrote:
> If what you say is true, why does the following example work fine (using
> GNAT), without any compiler warning or execution error ?

Because you're not trying to store the 'Access anywhere.

The problem in your original example is with the line

   BB := B.all'Access;

where BB is a variable of type Base_Ref.  Since the type Base_Ref is
global (i.e. has library-level accessibility), since it's defined in a
library package, any value of type Base_Ref also has to be global (if
you never use 'Unchecked_Access).  It can't be the 'Access of a local
variable.  Otherwise, you could work things out (by assigning
something else to BB) so that you have a global variable of type
Base_Ref that points to a local variable that no longer exists.

But in the second example, when you take the 'Access of a parameter,
you never try to convert it to a global type.  You're converting it to
an "anonymous access parameter" type when, say, you call P1A
(X'Access...), but that's OK, since anonymous access parameters take
on the accessibility level of whatever you pass them.  (Very roughly
speaking.)

It has nothing to do with "aliased".  Stephe was a tad confused.
Omitting "aliased" can make a program illegal but I do not believe
there is any way that it can cause a Program_Error at runtime.

                            -- Adam



^ permalink raw reply	[flat|nested] 48+ messages in thread

* Re: Issue with GNAT GPL 2009 and GtkAda
  2009-06-29 21:59                   ` Randy Brukardt
@ 2009-06-30  8:31                     ` Dmitry A. Kazakov
  0 siblings, 0 replies; 48+ messages in thread
From: Dmitry A. Kazakov @ 2009-06-30  8:31 UTC (permalink / raw)


On Mon, 29 Jun 2009 16:59:40 -0500, Randy Brukardt wrote:

> "Dmitry A. Kazakov" <mailbox@dmitry-kazakov.de> wrote in message 
> news:u7txi934iaog$.gw40yhq8811x.dlg@40tude.net...
>> On Fri, 26 Jun 2009 16:38:45 -0500, Randy Brukardt wrote:
> ...
>>> As far as the use of class-wide components, I think that would be easily
>>> fixed by just allowing them.
>>
>> That would make objects non-contiguous. It is not obvious to me how that
>> will work with streams and pools. I prefer a more transparent model when
>> all components of a constrained object are constrained.
> 
> Well, Ada has always allowed non-continguous objects. There is no problem 
> with streams: the stream attributes take care of any non-contiguous parts. 
> As for pools, multiple calls to Allocate are allowed; again there is no 
> requirement that the objects are contiguous. (That's been confirmed by 
> AI05-0107-1, but it has always been true for Ada 95; there are plenty of 
> AARM notes making that clear).

OK, but I still feel bad about it. (:-))

>>> That would reduce the need to use access types some more. (But it can never
>>> be completely eliminated; sometimes you really do need reference semantics,
>>> especially for returns.)
>>
>> No, this is the mental trap. If something requires by-reference semantics
>> that is not a return. Considering containers:
>>
>>   A (I) := X;
>>
>> It is a semantic mistake to treat A (I) as a function "returning"
>> something. This can only lead to introducing more and more strange
>> constructs like limited aggregates, return statements and other mess.
>>
>>   A (I) := X;
>>
>> must be treated as a syntax sugar for a procedure call
>>
>>   Put (A, I, X);
> 
> That works for full object assignment, but not in any sane way for in-place 
> component updating. And full object assignment really doesn't need any 
> special syntax (Replace_Element works just fine); the problem is when you 
> need to update a single element of a container which is itself an element. 

Ah, that is an interesting issue. Let us compare it on the example of
multi-dimensional arrays. Should A(I,J) should better be A(I)(J)?

I do not think that LHS indexing is "composable" in "C-way" without further
assumptions. It should not be taken for granted. In cases of genuine
reference semantics I would prefer a container of controlled access types
to T rather than a container of aliased T returned by reference. I want it
explicit like it is now:

   type Container is array (...) of access T;

What is missing is finalization of access T by Unchecked_Deallocation and
assignment T to access T by new T'(...).

BTW, the public view of such container could be array of T. For example:

   type Container is array (...) of T is private;  -- Not Ada!

private
   type Container is array (...) of access T;
       -- implementation per controlled references

> It doesn't make sense to try to think of these sorts of operations as a 
> single procedure.

Why not? In general case of container composition, I would indeed provide
the syntax:

   A (I, J, ...) := X;

implemented by a primitive operation

   Put (A, I, J, ..., X);

With introducing index types (tuples) it does not depend on dimension:

   Put (A, (I, J, ...), X);

-- 
Regards,
Dmitry A. Kazakov
http://www.dmitry-kazakov.de



^ permalink raw reply	[flat|nested] 48+ messages in thread

* Re: Issue with GNAT GPL 2009 and GtkAda
  2009-06-27 17:04                 ` Robert A Duff
@ 2009-06-30 11:11                   ` Stephen Leake
  2009-06-30 18:10                     ` Robert A Duff
  0 siblings, 1 reply; 48+ messages in thread
From: Stephen Leake @ 2009-06-30 11:11 UTC (permalink / raw)


Robert A Duff <bobduff@shell01.TheWorld.com> writes:

> Stephen Leake <stephen_leake@stephe-leake.org> writes:
>
>> "Randy Brukardt" <randy@rrsoftware.com> writes:
>>
>>>>Niklas Holsti" <niklas.holsti@tidorum.invalid> wrote in message 
>>>>news:4a44ae4e$0$6295$4f793bc4@news.tdc.fi...
>>> I think he means that the accessibility level of a parameter is that of a 
>>> local object, ...
>
> Yes, the accessibility level of a formal parameter is like a local
> nested inside the procedure.  This is true for tagged and untagged.
>
>>...as it *might* have been passed by copy. 
>
> Not for tagged -- those are always passed by reference.
>
>> 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.
>
> The compiler is just doing what the language rules require.
>
> Note that "must be passed by reference" does not imply "we could allow
> 'Access".  Consider:
>
>     type T_Ref is access all T;
>     Global : T_Ref;
>
>     procedure P (X : in out T) is -- Suppose T is tagged.
>     begin
>         Global := X'Access; -- Illegal!
>     end P;
>
>     procedure Q (...) is
>         Local : aliased T;
>     begin
>         P (Local);
>     end Q;
>
> After calling Q, Global is a dangling pointer.  The language design rule
> is:  If you do anything that _might_ create a dangling pointer, you
> have to use 'Unchecked_Access (and take care).

But if X was actually a global object, 'Access would be ok; I thought
the run-time accessibility checks would handle that case for tagged
types.

But apparently accessibility information is only passed with access
parameters (either 'access', or 'in [out]' of an access type).

> ..
> In my view, this makes the language _more_ complicated, and if
> "aliased" is dangerous, surely implicit aliased is even more so.

I agree with that!

>>> 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.
>
> No, I don't think they're overly conservative -- see my dangling pointer
> example above.  Well, of course compile-time checks are always
> conservative (see halting problem!).  The only way to be less
> conservative would be to do more checks at run time, which
> is heading in the wrong direction.

This is my key mis-understanding. If 'in out' parameters of tagged types
carried accessibility information that could be checked at runtime,
the above example would be ok.

I'm not clear why you say that is the "wrong direction".

>> 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?
>
> In most compilers, the accessibility level is represented as an integer,
> and this integer is passed as an extra implicit parameter whenever
> you have an access parameter.  So your Foreach procedure really
> has three parameters: B, I, and the accessibility level of B.all.

Right. So I'm proposing that same extra parameter be passed for each
'in out' parameter of a tagged type.

I can see how that is more distributed overhead, on the off chance
that somebody might use 'Access.

Personally, I like the rule:
     
    If the body needs an access value, pass in an access value.

which works fine with the current Ada rules.

But it makes 'access' visible all over the place, which some people
don't like.

-- 
-- Stephe



^ permalink raw reply	[flat|nested] 48+ messages in thread

* Re: Issue with GNAT GPL 2009 and GtkAda
  2009-06-29 22:11                 ` Randy Brukardt
@ 2009-06-30 11:13                   ` Stephen Leake
  2009-06-30 15:26                     ` Adam Beneschan
  0 siblings, 1 reply; 48+ messages in thread
From: Stephen Leake @ 2009-06-30 11:13 UTC (permalink / raw)


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

> "Stephen Leake" <stephen_leake@stephe-leake.org> wrote in message 
> news:uljnej5hp.fsf@stephe-leake.org...
> ...
>> 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"'.
>
> Aside: The "blank screen" problem seems to be somewhere between our web 
> server and the broad Internet, because it sometimes happens when I surf out 
> as well as surf in. It seems to be caused by overloading with too many 
> requests (especially a problem because of spammers constantly pounding our 
> mail and web servers); 

When I switched from Firefox to MS Internet Explorer, the problem was
immediately and consistently solved, so I don't think that's it.

> usually all that you need to do to deal with it is click on the
> "Refresh" button.

That didn't fix it for me.

> I suspect that you could get similar effects with other browsers, but I 
> don't have any first-hand knowledge of that, because I rarely use other 
> browsers (and that seems to be true of the vast majority of the humans that 
> visit our web site as well).

Ada caters to minority programmers :)

-- 
-- Stephe



^ permalink raw reply	[flat|nested] 48+ messages in thread

* Re: Issue with GNAT GPL 2009 and GtkAda
  2009-06-30  0:48             ` Adam Beneschan
@ 2009-06-30 11:18               ` Stephen Leake
  0 siblings, 0 replies; 48+ messages in thread
From: Stephen Leake @ 2009-06-30 11:18 UTC (permalink / raw)


Adam Beneschan <adam@irvine.com> writes:

> On Jun 26, 2:03�pm, Damien Carbonne <damien.carbo...@free.fr> wrote:
>> If what you say is true, why does the following example work fine (using
>> GNAT), without any compiler warning or execution error ?
>
> Because you're not trying to store the 'Access anywhere.

Thank you; that makes more sense than my explanation! I was confused.

-- 
-- Stephe



^ permalink raw reply	[flat|nested] 48+ messages in thread

* Re: Issue with GNAT GPL 2009 and GtkAda
  2009-06-30 11:13                   ` Stephen Leake
@ 2009-06-30 15:26                     ` Adam Beneschan
  0 siblings, 0 replies; 48+ messages in thread
From: Adam Beneschan @ 2009-06-30 15:26 UTC (permalink / raw)


On Jun 30, 4:13 am, Stephen Leake <stephen_le...@stephe-leake.org>
wrote:

>> > Aside: The "blank screen" problem seems to be somewhere between our web
> > server and the broad Internet, because it sometimes happens when I surf out
> > as well as surf in. It seems to be caused by overloading with too many
> > requests (especially a problem because of spammers constantly pounding our
> > mail and web servers);
>
> When I switched from Firefox to MS Internet Explorer, the problem was
> immediately and consistently solved, so I don't think that's it.

I believe I've still had the same behavior occasionally with IE.  (IE7
to be specific.)

                          -- Adam




^ permalink raw reply	[flat|nested] 48+ messages in thread

* Re: Issue with GNAT GPL 2009 and GtkAda
  2009-06-26 21:51             ` Randy Brukardt
  2009-06-27 11:11               ` Stephen Leake
@ 2009-06-30 15:59               ` Adam Beneschan
  2009-06-30 23:11                 ` Randy Brukardt
  1 sibling, 1 reply; 48+ messages in thread
From: Adam Beneschan @ 2009-06-30 15:59 UTC (permalink / raw)


On Jun 26, 2:51 pm, "Randy Brukardt" <ra...@rrsoftware.com> wrote:

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

Randy, is this a proposed new feature that's described in one of the
AI's?  I couldn't find it in AI05-138, although I only did a cursory
search.

                          -- Adam



^ permalink raw reply	[flat|nested] 48+ messages in thread

* Re: Issue with GNAT GPL 2009 and GtkAda
  2009-06-30 11:11                   ` Stephen Leake
@ 2009-06-30 18:10                     ` Robert A Duff
  0 siblings, 0 replies; 48+ messages in thread
From: Robert A Duff @ 2009-06-30 18:10 UTC (permalink / raw)


Stephen Leake <stephen_leake@stephe-leake.org> writes:

> Robert A Duff <bobduff@shell01.TheWorld.com> writes:
>>     type T_Ref is access all T;
>>     Global : T_Ref;
>>
>>     procedure P (X : in out T) is -- Suppose T is tagged.
>>     begin
>>         Global := X'Access; -- Illegal!
>>     end P;
>>
>>     procedure Q (...) is
>>         Local : aliased T;
>>     begin
>>         P (Local);
>>     end Q;
>>
>> After calling Q, Global is a dangling pointer.  The language design rule
>> is:  If you do anything that _might_ create a dangling pointer, you
>> have to use 'Unchecked_Access (and take care).
>
> But if X was actually a global object, 'Access would be ok; I thought
> the run-time accessibility checks would handle that case for tagged
> types.
>
> But apparently accessibility information is only passed with access
> parameters (either 'access', or 'in [out]' of an access type).

Right.  Access parameters (anonymous access types only!) get the extra
info, other parameters, and regular objects and so on do not.

> This is my key mis-understanding. If 'in out' parameters of tagged types
> carried accessibility information that could be checked at runtime,
> the above example would be ok.

Yes.

> I'm not clear why you say that is the "wrong direction".

Because I think it was a mistake to use dynamic accessibility
for access parameters.  For the usual reasons:  Catching
errors sooner is better than later.  Especially when "later"
means "by the customer".  Run-time checks are inefficient.

Run-time checks give more flexibility, usually.  But in this
case, I don't find that important.  When using access parameters,
it's (almost?) always the case that either:

    1. The callee expects to store the pointer in a global,
       so the caller needs to pass a pointer to a global.

    2. The caller can pass pointers to local objects,
       so the callee had better not store the pointer in a global.

And this distinction is known when writing the code.
You don't see code like:

    if (the thing is pointing to a global) then
        Store it globally;
    else
        Do something else;
    end if;

Unfortunately, this distinction is not visible in the spec.
How is the caller supposed to know whether it's OK
to pass a pointer to local?  You have to look at the
body of the callee, or trust in comments.

I also don't like the fact that anonymity causes all kinds of magic.
It's confusing.  I think:

    type T is <some stuff>;
    X : T;

and

    X : <some stuff>;

ought to mean the same thing (whether X is a parameter,
or something else).

- Bob



^ permalink raw reply	[flat|nested] 48+ messages in thread

* Re: Issue with GNAT GPL 2009 and GtkAda
  2009-06-30 15:59               ` Adam Beneschan
@ 2009-06-30 23:11                 ` Randy Brukardt
  0 siblings, 0 replies; 48+ messages in thread
From: Randy Brukardt @ 2009-06-30 23:11 UTC (permalink / raw)


"Adam Beneschan" <adam@irvine.com> wrote in message 
news:1ca4f07b-63a1-49a9-93da-a650e5e9ef28@s6g2000vbp.googlegroups.com...
On Jun 26, 2:51 pm, "Randy Brukardt" <ra...@rrsoftware.com> wrote:

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

>Randy, is this a proposed new feature that's described in one of the
>AI's?  I couldn't find it in AI05-138, although I only did a cursory
>search.

You're looking for AI05-0142-4 - the 4th attempt to make container accessors 
work. (And this one actually does work, even if it is rather goofy under the 
covers.)

                             Randy.





^ permalink raw reply	[flat|nested] 48+ messages in thread

* Re: Issue with GNAT GPL 2009 and GtkAda
  2009-06-29 22:15                   ` Randy Brukardt
@ 2009-07-01 19:22                     ` Damien Carbonne
  0 siblings, 0 replies; 48+ messages in thread
From: Damien Carbonne @ 2009-07-01 19:22 UTC (permalink / raw)


I think I now understand the issue.
Thanks to all of you for your patience and explanations.

I also think that all this explains the issues I had had in the past 
(also with GtkAda) when mixing [in] [out] parameters and access.
I always needed to use Unchecked_Access which I did not find 
satisfactory. This seems to be the only solution when mixing standard 
parameters modes and access.
This time, the Object.Func notation made things less obvious. Next time 
I will be more careful !

Regards,

Damien

Randy Brukardt a �crit :
> "Damien Carbonne" <damien.carbonne@free.fr> wrote in message 
> news:4a46121a$0$414$426a74cc@news.free.fr...
> ...
>> This behaves as expected (by me).
>> So a tagged type is really and always aliased, whatever its mode (in, out, 
>> in out) is. At least, this is what understand from those examples.
> 
> That's not right, unfortunately. Tagged *parameters* are always considered 
> aliased, but other kinds of tagged objects are not (necessarily) considered 
> aliased. The designated object of an access value is considered aliased, 
> though.
> 
> Bob explained this in more detail.
> 
>                                        Randy.
> 
> 



^ permalink raw reply	[flat|nested] 48+ messages in thread

end of thread, other threads:[~2009-07-01 19:22 UTC | newest]

Thread overview: 48+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
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
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

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