From mboxrd@z Thu Jan 1 00:00:00 1970 X-Spam-Checker-Version: SpamAssassin 3.4.4 (2020-01-24) on polar.synack.me X-Spam-Level: X-Spam-Status: No, score=-1.3 required=5.0 tests=BAYES_00,INVALID_MSGID autolearn=no autolearn_force=no version=3.4.4 X-Google-Language: ENGLISH,ASCII-7-bit X-Google-Thread: 103376,58a33c3232e54ed3 X-Google-Attributes: gid103376,public From: dewar@merv.cs.nyu.edu (Robert Dewar) Subject: Re: Why must access to unconstrained array statically match? Date: 1996/11/20 Message-ID: #1/1 X-Deja-AN: 197722174 references: <3290EBC7.4065@itd.sterling.com> organization: New York University newsgroups: comp.lang.ada Date: 1996-11-20T00:00:00+00:00 List-Id: Paul Williams asks about package A is type An_Array is array (Positive range <>) of Integer; type An_Array_Ptr is access all An_Array; The_Array : aliased An_Array (1..10); The_Ptr : An_Array_Ptr := The_Array'Access; end A; Yes, this is indeed illegal. GNAT agrees with a.ads:6:31: object subtype must statically match designated subtype As Paul found out, the RM referene is not much help, it just repeats this rule in more elaborate language. But Paul asks *why* this rule is here, and the answer is that there is an expectation that pointers to unconstrained array types may in fact always point to an array with a preceding descriptor containing the bounds. The question is whether such bounds must be allocated for all aliased objects. In this case, do you want the compiler allocating bounds for The_Array. Well some implementors were very worried about space, and really wanted the answer to be no. So here's the deal, if the nominal subtype of a variable is constrained, as in this case, then the compiler does NOT have to allocate a descriptor, and so you cannot let a pointer point at it. This is of course very dependent on the implementation model, and for example with GNAT we would have no trouble allowing this. However, a worried implementor spoke, and hence the rule. The work around is a bit horrible: package A is type An_Array is array (Positive range <>) of Integer; type An_Array_Ptr is access all An_Array; The_Array : aliased An_Array := (1 .. 10 => 0); The_Ptr : An_Array_Ptr := The_Array'Access; end A; Now the nominal subtype of The_Array is unconstrained, so the compiler must allocate a descriptor, and the pointer is allowed (in RMese, the subtypes now statically match, so all is well). There is no way to work around this without initializing The_Array. The more familiar form of this trap is X : aliased constant String := "abcde"; X : aliased constant String (1 .. 5) := "abcde"; Unlike the situation in Ada 83 where giving bounds on the left was redundant, and we could regard the former as an abbrevation for the latter, these are quite different in Ada 95. The first must allocate a descriptor and would allow an "access all String" to point to it, the second would not. So, another pitfall in Ada 95. BUT, and this is a very important but, like most other similar pitfalls, the result is simply that a program you expected to be legal is illegal. This is a whole lot safer than pitfalls where the result is execution anomolies or chaos :-)