comp.lang.ada
 help / color / mirror / Atom feed
From: Adrian Hoe <abyhoe@gmail.com>
Subject: Re: Type in allocator has deeper level than designated class-wide type
Date: Mon, 13 Jun 2011 23:04:01 -0700 (PDT)
Date: 2011-06-13T23:04:01-07:00	[thread overview]
Message-ID: <b71e580e-0715-439b-9f20-33e0c6db8b16@r27g2000prr.googlegroups.com> (raw)
In-Reply-To: e507e82a-c8e8-4608-b033-fea6fe93839b@d26g2000prn.googlegroups.com

On Jun 14, 9:24 am, Adam Beneschan <a...@irvine.com> wrote:
> On Jun 13, 6:07 pm, Adrian Hoe <aby...@gmail.com> wrote:
>
> > I changed the line in procedure Add from
>
> >       New_Element := new Element_Record'
> >                         ( Constructor.Init ( Name, Color, Data) ) ;
>
> > to
>
> >       New_Element := new Element_Record;
>
> > The compiler is still pointing the same warning to this line.
>
> > What exactly does the warning message "Type in allocator has deeper
> > level than designated class-wide type" mean? Is the compiler unable to
> > determine the size of the array during allocation? Or the array is a
> > level deeper than the List.Access_Node?
>
> It has nothing to do with arrays.  When you declare a type as "access
> all T'Class", an object of that type can't be made to point to a type
> declared in a more deeply nested subprogram.  A simple example:
>
> package Pack1 is
>     type Root is tagged null record;
>     type Acc is access all Root'Class;
> end Pack1;
>
> package Pack2 is
>     procedure Proc1;
> end Pack2;
>
> with Pack1;
> package body Pack2 is
>     procedure Proc1 is
>         type Child is new Pack1.Root with null record;
>         A : Pack1.Acc;
>     begin
>         A := new Child;   -- ILLEGAL
>     end Proc1;
> end Pack2;
>
> This assignment statement is illegal, because somewhere later, A could
> be copied to, say, another variable of type Pack1.Acc declared
> globally in the body of Pack2, and then you'd have a pointer to a
> Child that would exist after Proc1 has exited and the Child type no
> longer exists, which is a big no-no.  4.8(5.1) prohibits this.
>
> Since in this case, the record type (Element_Record) is declared in a
> generic, that complicates things, because the generic *could* be
> instantiated inside a procedure, which would lead to the same sort of
> problem as above.  I don't remember all the rules, but depending on
> where the type is declared and where the allocator occurs (generic
> specification or body), it might be illegal to instantiate this
> generic inside a procedure, or it might cause Program_Error to be
> raised.  I just tried our compiler again and modified the source to
> instantiate High_Cloud; if there's an instance of High_Cloud inside a
> procedure, it *does* give a warning that Program_Error will be raised
> (if the "new Element_Record" expression is reached).  If your compiler
> gives the warning when the generic is first seen, before an instance
> of the generic is seen, that's just a choice your compiler makes.  But
> unless your program is arranged in a different order than I'm
> guessing, or unless there are some new Ada 2012 rules that I'm not yet
> familiar with, the compiler should not reject your generic, and it
> should not reject it or cause Program_Error to be raised if there's an
> instance of the generic that is *not* inside a subprogram.
>
>                                   -- Adam


I see and I followed this post by Robert Duff:
https://groups.google.com/group/comp.lang.ada/browse_frm/thread/8fc030c3b6c79517/45208b566c079110?lnk=gst&q=generic+and+accessibility#45208b566c079110

Hence,


generic
   type Index is ( <> ) ;
   type Item is private;
package High_Cloud is

   package List renames Heterogeneous_Doubly_Link_List;
   use List;

   type Element_Record           is new List.Node with private;
   type Series_Access            is new List.Access_List;
private
   type Element_Record is new List.Node with
      record
         Name           : Unbounded_String;
         Color          : Unbounded_String;
         Data           : Item;
      end record;
...
end High_Cloud;
In the package body of High_Cloud, I have a procedure:
   procedure Add
      ( Cloud          : in out High_Cloud_Record;
        Name            : in     Unbounded_String;
        Color           : in     Unbounded_String;
        Data            : in     Item )
   is
      New_Element : List.Access_Node;
   begin
      New_Element := new Element_Record'
                        ( Constructor.Init ( Name, Color, Data) ) ;
      Concatenate ( Cloud.Series, New_Element ) ;
   end Add;

To use High_Cloud:


with High_Cloud;

package Hen is

   type I_Array is array ( 1 .. 31 ) of Integer;
   package G is new High_Cloud ( Positive, I_Array ) ;
   use G;

end Hen;



and in the procedure, I have:


with High_Cloud;
with Hen;

procedure smalltest is


   package H renames Hen;
   use H;

   Data_Op : H.I_Array := ( 3, 4, 2, 3, 3, 3, 0, 3, 6, 3, 2, 6, 8, 7,
                            3, 4, 3, 5, 1, 3, 1, 2, 2, 0, 2, 6, 8, 7,
                            3, 3, 3
                          ) ;
begin

   H.G.Init ( Chart ) ;
   H.G.Add  ( Chart, "OP", "#000000", Data_Op ) ;

end smalltest;

I don't know if this is the most elegant and effective way, but it
works.
--
Adrian Hoe
http://adrianhoe.com/adrianhoe



  reply	other threads:[~2011-06-14  6:04 UTC|newest]

Thread overview: 12+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2011-06-13 15:31 Type in allocator has deeper level than designated class-wide type Adrian Hoe
2011-06-13 17:11 ` Adam Beneschan
2011-06-14  0:49   ` Adrian Hoe
2011-06-14  1:08     ` Adam Beneschan
2011-06-14  1:11       ` Adrian Hoe
2011-06-14  1:07   ` Adrian Hoe
2011-06-14  1:24     ` Adam Beneschan
2011-06-14  6:04       ` Adrian Hoe [this message]
2011-06-14  8:01         ` Adrian Hoe
2011-06-14 16:01           ` Adam Beneschan
2011-06-15  2:04             ` Adrian Hoe
2011-06-15 15:44               ` Adam Beneschan
replies disabled

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