comp.lang.ada
 help / color / mirror / Atom feed
* Access to Unconstrained Arrays
@ 1997-04-16  0:00 John Harbaugh
  1997-04-18  0:00 ` Joel VanLaven
                   ` (2 more replies)
  0 siblings, 3 replies; 9+ messages in thread
From: John Harbaugh @ 1997-04-16  0:00 UTC (permalink / raw)



When trying to pass pointers to objects of unconstrained array type, I
am getting confusing compiler errors.  For example:

procedure Main is
   type Lists is array(Natural range <>) of Integer;
   type Lists_Ptrs is access all Lists;

   procedure Do_Something(To : in out Lists_Ptrs) is...

   List1 : Lists(1..4) := (1,2,3,4);
   List2 : Lists       := (1,2,3,4);

begin
   Do_Something(To => List1);  -- Compilation Error.  Why?
   Do_Something(To => List2);  -- No problemo!!!
end Main;

List1 should be an anonymous constrained subtype of type Lists.  I was
under the impression that subtypes are simply a subset of their base
type.  Is this not the case for constrained subtypes of unconstrained
types?

Thanks in advance for any who may respond.

   - John




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

* Re: Access to Unconstrained Arrays
  1997-04-16  0:00 Access to Unconstrained Arrays John Harbaugh
@ 1997-04-18  0:00 ` Joel VanLaven
  1997-04-20  0:00   ` Robert Dewar
  1997-04-18  0:00 ` Robert Dewar
  1997-04-18  0:00 ` John Harbaugh
  2 siblings, 1 reply; 9+ messages in thread
From: Joel VanLaven @ 1997-04-18  0:00 UTC (permalink / raw)



John Harbaugh (john.s.harbaugh2@boeing.com) wrote:
: When trying to pass pointers to objects of unconstrained array type, I
: am getting confusing compiler errors.  For example:

: procedure Main is
:    type Lists is array(Natural range <>) of Integer;
:    type Lists_Ptrs is access all Lists;

:    procedure Do_Something(To : in out Lists_Ptrs) is...

:    List1 : Lists(1..4) := (1,2,3,4);
:    List2 : Lists       := (1,2,3,4);

: begin
:    Do_Something(To => List1);  -- Compilation Error.  Why?
:    Do_Something(To => List2);  -- No problemo!!!
: end Main;

: List1 should be an anonymous constrained subtype of type Lists.  I was
: under the impression that subtypes are simply a subset of their base
: type.  Is this not the case for constrained subtypes of unconstrained
: types?

I think your compiler is stopping at the first error or something.  Our
compiler says that both calls are incorrect.  List1 and List2 are arrays,
NOT access values.  So, neither call matches the procedure profile. In
fact, List2 IS constrained.  It is given a constraint when it is 
initialized.  If your program were to assign (1,2) to either list it would
raise a constraint error (the same as for list1).

Did you try commenting out the first call?  I hope that the compiler you
are using does not really accept the second call.  If it does either it
is a bug in your compiler or in ours :).  I am betting that neither has
a bug with respect to this.

To make this compile, you need to either change Do_Something or change
the two object declarations to be something like

   List1 : Lists_Ptrs := new lists'(1,2,3,4);
   List2 : Lists_Ptrs := new lists'(1,2,3,4);

: Thanks in advance for any who may respond.

:    - John

No problem,
-- 
-- Joel VanLaven




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

* Re: Access to Unconstrained Arrays
  1997-04-16  0:00 Access to Unconstrained Arrays John Harbaugh
  1997-04-18  0:00 ` Joel VanLaven
  1997-04-18  0:00 ` Robert Dewar
@ 1997-04-18  0:00 ` John Harbaugh
  1997-04-20  0:00   ` Robert Dewar
  1997-04-21  0:00   ` Joel VanLaven
  2 siblings, 2 replies; 9+ messages in thread
From: John Harbaugh @ 1997-04-18  0:00 UTC (permalink / raw)



John Harbaugh wrote:
> 
> When trying to pass pointers to objects of unconstrained array type, I
> am getting confusing compiler errors.  For example:
> 
> procedure Main is
>    type Lists is array(Natural range <>) of Integer;
>    type Lists_Ptrs is access all Lists;
> 
>    procedure Do_Something(To : in out Lists_Ptrs) is...
> 
>    List1 : Lists(1..4) := (1,2,3,4);
>    List2 : Lists       := (1,2,3,4);
> 
> begin
>    Do_Something(To => List1);  -- Compilation Error.  Why?
>    Do_Something(To => List2);  -- No problemo!!!
> end Main;
> 
> List1 should be an anonymous constrained subtype of type Lists.  I was
> under the impression that subtypes are simply a subset of their base
> type.  Is this not the case for constrained subtypes of unconstrained
> types?
> 
> Thanks in advance for any who may respond.
> 
>    - John


How embarrasing, please excuse the mangled code.  What I meant to show
was:

 procedure Main is
    type Lists is array(Natural range <>) of Integer;
    type Lists_Ptrs is access all Lists;
 
    procedure Do_Something(To : in Lists_Ptrs) is separate;
 
    List1 : aliased Lists(1..4) := (1,2,3,4);
    List2 : aliased Lists       := (1,2,3,4);

    Ptr : Lists_Ptrs;
 
 begin
    Ptr := List1'access;
    Do_Something(To => Ptr);  -- Compilation Error.  Why?
    Ptr := List2'access;
    Do_Something(To => Ptr);  -- No problemo!!!
 end Main;



Apparently, the problem is that Lists(1..4) is a different subtype
indication than Lists.

Sheepishly,

   - John




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

* Re: Access to Unconstrained Arrays
  1997-04-16  0:00 Access to Unconstrained Arrays John Harbaugh
  1997-04-18  0:00 ` Joel VanLaven
@ 1997-04-18  0:00 ` Robert Dewar
  1997-04-18  0:00 ` John Harbaugh
  2 siblings, 0 replies; 9+ messages in thread
From: Robert Dewar @ 1997-04-18  0:00 UTC (permalink / raw)



John says

<<procedure Main is
   type Lists is array(Natural range <>) of Integer;
   type Lists_Ptrs is access all Lists;

   procedure Do_Something(To : in out Lists_Ptrs) is...

   List1 : Lists(1..4) := (1,2,3,4);
   List2 : Lists       := (1,2,3,4);

begin
   Do_Something(To => List1);  -- Compilation Error.  Why?
   Do_Something(To => List2);  -- No problemo!!!
end Main;

List1 should be an anonymous constrained subtype of type Lists.  I was
under the impression that subtypes are simply a subset of their base
type.  Is this not the case for constrained subtypes of unconstrained
types?

Thanks in advance for any who may respond..>>

The compiler messages are correct. Your pointer type can only point
to objects of the appropriate unconstrained type, like List2. But the
type of List1 is constrained (pretty clearly from your source!!!) so
it is not suitable.

This somewhat annoying rule was done to save a little bit of memory in
some implementations (in some implementations, List2 will materialize
a dope, and List1 will not.

Incidentally, it is helpful if you are careful to post the EXACT sources
that you used, the source above is obvious junk (since you pass the
wrong type in both calls), but I am assumning some obvoius repair (such
as add aliased to both declarations, and replace in out with access.





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

* Re: Access to Unconstrained Arrays
  1997-04-18  0:00 ` Joel VanLaven
@ 1997-04-20  0:00   ` Robert Dewar
  0 siblings, 0 replies; 9+ messages in thread
From: Robert Dewar @ 1997-04-20  0:00 UTC (permalink / raw)



Joel said

<<I think your compiler is stopping at the first error or something.  Our
compiler says that both calls are incorrect.  List1 and List2 are arrays,
NOT access values.  So, neither call matches the procedure profile. In
fact, List2 IS constrained.  It is given a constraint when it is
initialized.  If your program were to assign (1,2) to either list it would
raise a constraint error (the same as for list1).>>

Of course the program is incorrect as presented, but one has to assume
that was just a typo introduced in preparation. if you make the obvious
changes, there is *indeed* a subtle difference between the two cases,
see my previous post.





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

* Re: Access to Unconstrained Arrays
  1997-04-18  0:00 ` John Harbaugh
@ 1997-04-20  0:00   ` Robert Dewar
  1997-04-21  0:00   ` Joel VanLaven
  1 sibling, 0 replies; 9+ messages in thread
From: Robert Dewar @ 1997-04-20  0:00 UTC (permalink / raw)



<<Apparently, the problem is that Lists(1..4) is a different subtype
indication than Lists.

Sheepishly,>>

Exactly, one has an unconstrained nominal subtype, the other has a constrained
nominal subtype (incidentally, it was absolutely clear what you intended,
even though your code was indeed a bit mangled :-)





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

* Re: Access to Unconstrained Arrays
  1997-04-18  0:00 ` John Harbaugh
  1997-04-20  0:00   ` Robert Dewar
@ 1997-04-21  0:00   ` Joel VanLaven
  1997-04-21  0:00     ` Robert A Duff
  1 sibling, 1 reply; 9+ messages in thread
From: Joel VanLaven @ 1997-04-21  0:00 UTC (permalink / raw)



John Harbaugh (john.s.harbaugh2@boeing.com) wrote:
: John Harbaugh wrote:
: > 
: > When trying to pass pointers to objects of unconstrained array type, I
: > am getting confusing compiler errors.  For example:
: > 

[snipped old code]

: > List1 should be an anonymous constrained subtype of type Lists.  I was
: > under the impression that subtypes are simply a subset of their base
: > type.  Is this not the case for constrained subtypes of unconstrained
: > types?
: > 
: > Thanks in advance for any who may respond.
: > 
: >    - John


: How embarrasing, please excuse the mangled code.  What I meant to show
: was:

:  procedure Main is
:     type Lists is array(Natural range <>) of Integer;
:     type Lists_Ptrs is access all Lists;
:  
:     procedure Do_Something(To : in Lists_Ptrs) is separate;
:  
:     List1 : aliased Lists(1..4) := (1,2,3,4);
:     List2 : aliased Lists       := (1,2,3,4);

:     Ptr : Lists_Ptrs;
:  
:  begin
:     Ptr := List1'access;
:     Do_Something(To => Ptr);  -- Compilation Error.  Why?
:     Ptr := List2'access;
:     Do_Something(To => Ptr);  -- No problemo!!!
:  end Main;

: Apparently, the problem is that Lists(1..4) is a different subtype
: indication than Lists.

  I agree with you that this code ought to compile.  In fact, our
compiler does compile your code without error or warning.  Attempting
to resolve the conflict between this fact and Robert Dewar's comments,
I did a bit of Reference Manual snooping and found the following:

RM95: 3.10(14)
  "The first subtype of a type defined by an access_type_definition or an
access_to_object_definition is unconstrained if the designated subtype is
an unconstrained array or discriminated type; otherwise it is constrained."

  So, the first subtype of Lists_Ptrs is an unconstrained access subtype.

RM95 3.10(15)
  "An access value satisfies a composite_constraint of an access subtype
if it equals the null value of its type or if it designates an object
whose value satisfies the constraint."

  So, don't both list1'access and list2'access satisfy the (non-existant)
composite_constraint of the first subtype of lists_ptr?  Making both
assignments valid, right?

  If someone says not, could you explain why not?  (hopefully chapter and
verse of the rm :)
-- 
-- Joel VanLaven




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

* Re: Access to Unconstrained Arrays
  1997-04-21  0:00   ` Joel VanLaven
@ 1997-04-21  0:00     ` Robert A Duff
  1997-04-23  0:00       ` Robert Dewar
  0 siblings, 1 reply; 9+ messages in thread
From: Robert A Duff @ 1997-04-21  0:00 UTC (permalink / raw)



In article <1997Apr21.005646.25460@ocsystems.com>,
Joel VanLaven <jvl@ocsystems.com> wrote:
>John Harbaugh (john.s.harbaugh2@boeing.com) wrote:
>:  procedure Main is
>:     type Lists is array(Natural range <>) of Integer;
>:     type Lists_Ptrs is access all Lists;
>:  
>:     procedure Do_Something(To : in Lists_Ptrs) is separate;
>:  
>:     List1 : aliased Lists(1..4) := (1,2,3,4);
>:     List2 : aliased Lists       := (1,2,3,4);
>
>:     Ptr : Lists_Ptrs;
>:  
>:  begin
>:     Ptr := List1'access;

This 'Access is illegal by RM-3.10.2(27).  Lists(1..4) does not
statically match Lists; neither is Lists "discriminated and
unconstrained".

>:     Do_Something(To => Ptr);  -- Compilation Error.  Why?
>:     Ptr := List2'access;

This 'Access is legal.

>:     Do_Something(To => Ptr);  -- No problemo!!!
>:  end Main;
>
>: Apparently, the problem is that Lists(1..4) is a different subtype
>: indication than Lists.
>
>  I agree with you that this code ought to compile.  In fact, our
>compiler does compile your code without error or warning.  Attempting
>to resolve the conflict between this fact and Robert Dewar's comments,
>I did a bit of Reference Manual snooping and found the following:
>
>RM95: 3.10(14)
>  "The first subtype of a type defined by an access_type_definition or an
>access_to_object_definition is unconstrained if the designated subtype is
>an unconstrained array or discriminated type; otherwise it is constrained."
>
>  So, the first subtype of Lists_Ptrs is an unconstrained access subtype.
>
>RM95 3.10(15)
>  "An access value satisfies a composite_constraint of an access subtype
>if it equals the null value of its type or if it designates an object
>whose value satisfies the constraint."
>
>  So, don't both list1'access and list2'access satisfy the (non-existant)
>composite_constraint of the first subtype of lists_ptr?  Making both
>assignments valid, right?

Yes, the constraint is satisfied, but 3.10.2(27) adds a special case for
arrays.  There's a corresponding rule for type conversions in 4.6(16).
The goal is to prevent an access-to-unconstrained-array from pointing to
an object whose nominal subtype is constrained.  If this were allowed,
all aliased constrained arrays would have to have dope stored with them,
and some Ada 83 compiler writer(s) argued that this would be hard to do.
The rationale is explained in AARM-4.6(16.a).  Consider that in Ada 83,
if I write:

    type T is access String(1..8);

the compiler can store 8 bytes for each allocated object, and real
compilers did that.  If we didn't have this special rule, compiler would
have to store dope, which would increase the size to 16 bytes (on a
typical 32-bit machine -- 24 bytes on a 64-bit machine, if Integer is 64
bits).  Without the special rule, you could convert a value of type T to
an "access all String" type, which needs dope, so the dope has to be
there just in case.  Similarly, for "X.all'Access", which is similar to
a type conversion.  Whether this size increase is important is a matter
of opinion, but without the rule, clearly Ada 83 compilers would have
had to change their run-time model, and we were trying to avoid that.

This is an odd rule, since it treats discriminants differently from
array indices, whereas discrims and indices are essentially the same
thing, conceptually.  (Not quite, but I think Ada would be a simpler
language if they really were the same.  From the point of view of the
run-time model, I mean -- I understand of course that the syntax is
different.)

In Ada 83, if I write "type R(Discrim: ...) is record ... end;
type T is access R(Discrim => 8);", the compiler can avoid storing the
discriminant in each heap object.  But I don't know of any Ada 83
compilers that did that, and it no longer works in Ada 95.

Note that the language designers never considered using fat pointers for
access-to-array.  I continue to think that thin pointers are the better
(simpler) solution overall.  So all of this reasoning assumes thin
pointers.  Aside: with fat pointers, we could have allowed 'Access of
slices under some circumstances.

- Bob




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

* Re: Access to Unconstrained Arrays
  1997-04-21  0:00     ` Robert A Duff
@ 1997-04-23  0:00       ` Robert Dewar
  0 siblings, 0 replies; 9+ messages in thread
From: Robert Dewar @ 1997-04-23  0:00 UTC (permalink / raw)




Bob Duff said

<<Note that the language designers never considered using fat pointers for
 access-to-array.  I continue to think that thin pointers are the better
 (simpler) solution overall.  So all of this reasoning assumes thin
 pointers.  Aside: with fat pointers, we could have allowed 'Access of
 slices under some circumstances.>>

Well of course it is true that thin pointers are simpler, but they are
also less efficient. In particular, they rule out the use of virtual
origins for arrays.

GNAT offers the programmer the choice of fat or thin pointers (to get thin
pointers, you use a size clause on the access type that restricts it to
address size).

However, since we do provide fat pointers, we can indeed allow 'Access
of slices under some circumstances. For example, the following program

   with Text_IO; use Text_IO;
   procedure a is
      type ax is access all String;
      q : String (1 .. 11) := "Hello World";
      p : ax;
   begin
      p := q (1 .. 5)'Unrestricted_Access;
      Put_Line (p.all);
   end a;

Of course this program is not portable (it is relying on the implementation
dependent attribute Unrestricted_Access). It is however reliably portable
to all GNAT implementations.

You cannot use 'Access itself this way of course, since that is not legal
Ada!





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

end of thread, other threads:[~1997-04-23  0:00 UTC | newest]

Thread overview: 9+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
1997-04-16  0:00 Access to Unconstrained Arrays John Harbaugh
1997-04-18  0:00 ` Joel VanLaven
1997-04-20  0:00   ` Robert Dewar
1997-04-18  0:00 ` Robert Dewar
1997-04-18  0:00 ` John Harbaugh
1997-04-20  0:00   ` Robert Dewar
1997-04-21  0:00   ` Joel VanLaven
1997-04-21  0:00     ` Robert A Duff
1997-04-23  0:00       ` Robert Dewar

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