comp.lang.ada
 help / color / mirror / Atom feed
* Default_Storage_Pool
@ 2018-02-21  2:00 sbelmont700
  2018-02-22  1:13 ` Default_Storage_Pool Randy Brukardt
  0 siblings, 1 reply; 4+ messages in thread
From: sbelmont700 @ 2018-02-21  2:00 UTC (permalink / raw)


Can anyone offer insight into what exactly should happen when Default_Storage_Pool is explicitly set within an extended return statement to a pool within the return object?  In particular, consider these shenanigans:

package O is

   pool_1 : My_Fancy_Pool
   pragma Default_Storage_Pool(pool_1);
   
   type T is limited
      record
         pool_2 : My_Fancy_Pool
         p1     : access Integer;
      end record;
   
   function F return T;
   
end O;

package body O is

   function F return T is
   begin
      return Result : T do
         declare
            pragma Default_Storage_Pool(Result.pool_2);  -- legal?
            p2 : access Integer;
         begin
            p2 := new integer'(42);
            Result.p1 := new integer'(43);
         end;
      end return;
   end F;
   
end O;
   
GNAT happily accepts this, but based on print lines, it allocates Result.p1 from pool_1 and p2 from some unspecified default pool (i.e. neither pool_1 or pool_2).  I wasn't sure what I was expecting; I assumed an error message, but failing that, both to go into result.pool_2, and was surprised to get neither.

Any clarifications are appreciated.

-sb


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

* Re: Default_Storage_Pool
  2018-02-21  2:00 Default_Storage_Pool sbelmont700
@ 2018-02-22  1:13 ` Randy Brukardt
  2018-02-22 13:02   ` Default_Storage_Pool sbelmont700
  0 siblings, 1 reply; 4+ messages in thread
From: Randy Brukardt @ 2018-02-22  1:13 UTC (permalink / raw)


Default_Storage_Pool only has an effect when an access type is declared (not 
when it is used). Thus the allocators for the component of type T should use 
Pool_1 regardless of what the Default_Storage_Pool is when the allocator is 
written.

But I'd expect the local anonymous access allocator to use Pool_2. I don't 
see any reason to use some other pool in this case - 13.11.3(6-6.3/4) is 
pretty clear about this, and the rules specifically were designed so that it 
would apply to anonymous access types.

Thus, this appears to be a bug, but I also fail to see any use for it (the 
anonymous access type having to disappear long before anyone can used the 
return value), so I would probably not give it much priority if it was 
reported to me. (Of course, a fuller example could cause me to change my 
mind on that.)

                                    Randy.

<sbelmont700@gmail.com> wrote in message 
news:74cfbf22-7082-4a43-aef9-6a55a049fe61@googlegroups.com...
Can anyone offer insight into what exactly should happen when 
Default_Storage_Pool is explicitly set within an extended return statement 
to a pool within the return object?  In particular, consider these 
shenanigans:

package O is

   pool_1 : My_Fancy_Pool
   pragma Default_Storage_Pool(pool_1);

   type T is limited
      record
         pool_2 : My_Fancy_Pool
         p1     : access Integer;
      end record;

   function F return T;

end O;

package body O is

   function F return T is
   begin
      return Result : T do
         declare
            pragma Default_Storage_Pool(Result.pool_2);  -- legal?
            p2 : access Integer;
         begin
            p2 := new integer'(42);
            Result.p1 := new integer'(43);
         end;
      end return;
   end F;

end O;

GNAT happily accepts this, but based on print lines, it allocates Result.p1 
from pool_1 and p2 from some unspecified default pool (i.e. neither pool_1 
or pool_2).  I wasn't sure what I was expecting; I assumed an error message, 
but failing that, both to go into result.pool_2, and was surprised to get 
neither.

Any clarifications are appreciated.

-sb 


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

* Re: Default_Storage_Pool
  2018-02-22  1:13 ` Default_Storage_Pool Randy Brukardt
@ 2018-02-22 13:02   ` sbelmont700
  2018-02-23  0:06     ` Default_Storage_Pool Randy Brukardt
  0 siblings, 1 reply; 4+ messages in thread
From: sbelmont700 @ 2018-02-22 13:02 UTC (permalink / raw)


On Wednesday, February 21, 2018 at 8:14:03 PM UTC-5, Randy Brukardt wrote:
> Default_Storage_Pool only has an effect when an access type is declared (not 
> when it is used). Thus the allocators for the component of type T should use 
> Pool_1 regardless of what the Default_Storage_Pool is when the allocator is 
> written.
> 
> But I'd expect the local anonymous access allocator to use Pool_2. I don't 
> see any reason to use some other pool in this case - 13.11.3(6-6.3/4) is 
> pretty clear about this, and the rules specifically were designed so that it 
> would apply to anonymous access types.
> 
> Thus, this appears to be a bug, but I also fail to see any use for it (the 
> anonymous access type having to disappear long before anyone can used the 
> return value), so I would probably not give it much priority if it was 
> reported to me. (Of course, a fuller example could cause me to change my 
> mind on that.)
> 
>                                     Randy.


Thank you, that was what I thought it should do.  I had no legitimate use case, I was just trying to tease out counter-examples to confirm my understanding.  

I claim no in-depth comprehension, but because of either subsequent bugs or perhaps 2012 changes to AATs (or perhaps legitimately), GNAT also takes this:

package body O is

   janky : access Integer;
   
   function F return T is
   begin
      return Result : T do
         declare
            pragma Default_Storage_Pool(Result.pool_2);
            p2 : access Integer;
         begin
            p2 := new integer'(42);
            janky := p2;  --legal?
         end;
      end return;
   end F;
end;

When does janky become a dangling pointer?  Surely if the default pool is local to F (because the entire pool goes away after F ends), never if the default pool is pool_1 (since it has the same lifetime as janky), and 'possibly' if it's contained within Result.pool_2 (since it depends on where the client has creates the result). GNAT accepts all three variations (well, subject to the aforementioned bug presumably making case 3 the same as 1) and raises no exceptions for any of them.

Thank you for the continued explanations

-sb


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

* Re: Default_Storage_Pool
  2018-02-22 13:02   ` Default_Storage_Pool sbelmont700
@ 2018-02-23  0:06     ` Randy Brukardt
  0 siblings, 0 replies; 4+ messages in thread
From: Randy Brukardt @ 2018-02-23  0:06 UTC (permalink / raw)


I think the assignment to Janky should raise Program_Error, as it can take 
an object of any lifetime that is *longer* than itself.

RM 3.10.2(13.3/4) says this explicitly "...; accessibility checks ensure 
that this is never deeper than that of the declaration of the stand-alone 
object".

Trying to figure out precisely what check this is talking about is hard, 
however (the AARM is supposed to explain that part as it is claimed to 
follow from other rules -- but it doesn't). I'm not going to try to work 
that out in detail (it's also possible that it is supposed to be illegal).

                                      Randy.

<sbelmont700@gmail.com> wrote in message 
news:86a8a87c-72ca-4718-a2a1-11ee07d66fa8@googlegroups.com...
On Wednesday, February 21, 2018 at 8:14:03 PM UTC-5, Randy Brukardt wrote:
> Default_Storage_Pool only has an effect when an access type is declared 
> (not
> when it is used). Thus the allocators for the component of type T should 
> use
> Pool_1 regardless of what the Default_Storage_Pool is when the allocator 
> is
> written.
>
> But I'd expect the local anonymous access allocator to use Pool_2. I don't
> see any reason to use some other pool in this case - 13.11.3(6-6.3/4) is
> pretty clear about this, and the rules specifically were designed so that 
> it
> would apply to anonymous access types.
>
> Thus, this appears to be a bug, but I also fail to see any use for it (the
> anonymous access type having to disappear long before anyone can used the
> return value), so I would probably not give it much priority if it was
> reported to me. (Of course, a fuller example could cause me to change my
> mind on that.)
>
>                                     Randy.


Thank you, that was what I thought it should do.  I had no legitimate use 
case, I was just trying to tease out counter-examples to confirm my 
understanding.

I claim no in-depth comprehension, but because of either subsequent bugs or 
perhaps 2012 changes to AATs (or perhaps legitimately), GNAT also takes 
this:

package body O is

   janky : access Integer;

   function F return T is
   begin
      return Result : T do
         declare
            pragma Default_Storage_Pool(Result.pool_2);
            p2 : access Integer;
         begin
            p2 := new integer'(42);
            janky := p2;  --legal?
         end;
      end return;
   end F;
end;

When does janky become a dangling pointer?  Surely if the default pool is 
local to F (because the entire pool goes away after F ends), never if the 
default pool is pool_1 (since it has the same lifetime as janky), and 
'possibly' if it's contained within Result.pool_2 (since it depends on where 
the client has creates the result). GNAT accepts all three variations (well, 
subject to the aforementioned bug presumably making case 3 the same as 1) 
and raises no exceptions for any of them.

Thank you for the continued explanations

-sb 


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

end of thread, other threads:[~2018-02-23  0:06 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2018-02-21  2:00 Default_Storage_Pool sbelmont700
2018-02-22  1:13 ` Default_Storage_Pool Randy Brukardt
2018-02-22 13:02   ` Default_Storage_Pool sbelmont700
2018-02-23  0:06     ` Default_Storage_Pool Randy Brukardt

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