comp.lang.ada
 help / color / mirror / Atom feed
From: Robert A Duff <bobduff@shell01.TheWorld.com>
Subject: Re: A Gnother Gnasty bug
Date: Sat, 07 Apr 2012 09:55:29 -0400
Date: 2012-04-07T09:55:29-04:00	[thread overview]
Message-ID: <wccd37jzlwu.fsf@shell01.TheWorld.com> (raw)
In-Reply-To: 87mx6nvlwo.fsf@ludovic-brenta.org

Ludovic Brenta <ludovic@ludovic-brenta.org> writes:

> sbelmont700@gmail.com writes:
>>  new I'class'(F(arg=> 42)))));
>
> I don't think that's legal.

I didn't look at the original post, but
I think it's legal.

>...You can have a class-wide access value but
> not an allocator for a class-wide type because the allocator doesn't
> know how much memory to allocate:

It knows how much to allocate from the initial value.
It's UNinitialized allocators (and uninitialized object
declarations) that are illegal when the type is indefinite.

It also needs to know the alignment, which it can get
from the 'Tag of the initial value.

>> 4.8(4): An initialized allocator is an allocator with a
>> qualified_expression. [...]
>
> Your allocator is initialized because it has a qualified_expression.

Right, and that's why it's legal.

> The type designatd by your qualified_expression is class-wide, it is
> therefore impossible for the allocator to create the object.

There are at least two ways to implement it:

    Call F(42), putting the result in a temp.
    Call Allocate with the size and alignment of that temp.
    Copy the temp into the newly-allocated object,
        with adjustment/finalization if controlled.

    Call F, passing it a hidden thunk, which does
        the allocation.
    At the point where F does "return", call the thunk,
        passing this size and alignment.
    Store the result of F at the address returned by
        the thunk.

If the designated type is limited, the second way is
necessary, because the first way won't work (it involves
a copy, which won't work for limited types).

In this example, the type is nonlimited, so either method
works.  GNAT currently uses the first, but might someday
use the second for better efficiency (avoiding the copy,
if it's big, and avoiding adjust/fin) in some cases.

> with Ada.Finalization;
> procedure T is
>
>    type B is new Ada.Finalization.Controlled with record
>       D : Integer;
>    end record;
>
>    type Access_B is access B'Class;
>
>
>    function F return B'Class is
>    begin
>       return B'(Ada.Finalization.Controlled with D => 42);
>    end F;
>
>    J : Access_B := new B'Class'(Ada.Finalization.Controlled with D => 42); -- Line 16

This is illegal because the expected type for an aggregate
cannot be class-wide.  Otherwise, how would it know what 'Tag
to use, and how would it know whether you've obeyed the
full coverage rule?

This is a property of aggregates, whether or not "new" is involved.
If F said "return B'Class'(...)" instead of "return B'(...)",
then that would be illegal, too.

In general, for aggregates, the compiler does NOT determine
the type (or the 'Tag) by looking inside the aggregate.
It does NOT say, hmm, let's find a type derived from Controlled
that happens to have a component D of some integer type.
Instead, this information must come from the context.

>    K : Access_B := new B'Class'(F); -- Line 17: Not diagnosed

Here, there's no aggregate.  This is legal.

> gnatmake -gnatwa t
> gcc-4.6 -c -gnatwa t.adb
> t.adb:16:32: expected type "B'Class" defined at line 4
> t.adb:16:32: found a composite type

GNAT is correct here.

- Bob



  parent reply	other threads:[~2012-04-07 13:55 UTC|newest]

Thread overview: 7+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2012-04-07  0:44 A Gnother Gnasty bug sbelmont700
2012-04-07 11:09 ` Ludovic Brenta
2012-04-07 12:48   ` sbelmont700
2012-04-07 13:55   ` Robert A Duff [this message]
2012-04-09 21:09     ` Adam Beneschan
2012-04-09 21:39       ` Robert A Duff
2012-04-07 11:54 ` Simon Wright
replies disabled

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