From phl@rational.com Tue Apr 16 09:57:20 1996 Return-Path: Received: from inmet.camb.inmet.com by dsd.camb.inmet.com (4.1/SMI-4.1) id AA15939; Tue, 16 Apr 96 09:57:20 EDT Received: from sw-eng.falls-church.va.us (ns1.sw-eng.falls-church.va.us) by inmet.camb.inmet.com (4.1/SMI-4.1) id AA19302; Tue, 16 Apr 96 09:57:35 EDT Received: from rational2.rational.com by sw-eng.falls-church.va.us (8.7.1/) id NAA26676; Tue, 16 Apr 1996 13:56:40 GMT Received: from igor (igor.rational.com [89.64.2.102]) by rational2.rational.com (8.6.12/8.6.9) with ESMTP id GAA08610 for ; Tue, 16 Apr 1996 06:57:09 -0700 Received: from sorbonne.rational.com (sorbonne.rational.com [89.30.2.172]) by igor (8.6.9/igor-1.0-wwong) with ESMTP id GAA11028 for ; Tue, 16 Apr 1996 06:57:07 -0700 Received: from eiffel.Rational.COM (eiffel [89.30.1.2]) by sorbonne.rational.com (8.6.9/8.6.9) with SMTP id PAA24390 for ; Tue, 16 Apr 1996 15:57:00 +0200 From: "Pascal Leroy" Message-Id: <9604161556.ZM26531@rational.com> Date: Tue, 16 Apr 1996 15:56:59 +0200 In-Reply-To: bobduff@world.std.com (Robert A Duff) "Re: Lower bounds should be 1" (Apr 13, 6:04) References: <199604121745.AA04241@world.std.com> Organization: Rational Software Corporation Phone: +33 (1) 30 12 09 50 Reply-To: pleroy@Rational.COM X-Mailer: Z-Mail (3.2.0 06sep94) To: ada-comment@sw-eng.falls-church.va.us Subject: Re: Lower bounds should be 1 Mime-Version: 1.0 Content-Type: text/plain; charset=us-ascii !topic Lower bounds should be 1 !reference RM95-A.4.3(02) !reference RM95-A.4.3(73) !reference 96-5475.a Robert A Duff 96-4-12 !from Pascal Leroy 96-04-16 <> !discussion > The lower bounds of the above concatenations give Source'First as the > lower bound, which might not be 1. > > Clearly, the intent is that the lower bound should always be 1, as > stated in A.4.3(2). I think a "friendly" reading is that A.4.3(74) is > just telling us the characters of the string (it says "comprises", and > not "is equivalent to"), and is not intended to define the bounds. Note that there are (at least) two other functions to which this comment applies: Insert: RM95 A.4.3(78) says "otherwise returns Source (Source'First .. Before - 1) & New_Item & Source (Before .. Source'Last)." Delete: RM95 A.4.3(86) says "otherwise it is Source." There may be other functions for which the wording may also be misleading. So I guess that the AI should be worded in a way that makes it clear that it applies to all functions of package Fixed. (Maybe by stating that the wording of all paragraphs in RM95 A.4.3 is just specifying the characters of the string but not its bounds.) _____________________________________________________________________ Pascal Leroy +33.1.30.12.09.68 pleroy@rational.com +33.1.30.12.09.66 FAX From bobduff@world.std.com Tue Apr 16 15:37:40 1996 Return-Path: Received: from inmet.camb.inmet.com by dsd.camb.inmet.com (4.1/SMI-4.1) id AA24464; Tue, 16 Apr 96 15:37:40 EDT Received: from sw-eng.falls-church.va.us (ns1.sw-eng.falls-church.va.us) by inmet.camb.inmet.com (4.1/SMI-4.1) id AA25331; Tue, 16 Apr 96 15:37:54 EDT Received: from europe.std.com by sw-eng.falls-church.va.us (8.7.1/) id TAA05321; Tue, 16 Apr 1996 19:37:00 GMT Received: from world.std.com by europe.std.com (8.7.5/BZS-8-1.0) id PAA18962; Tue, 16 Apr 1996 15:37:29 -0400 (EDT) Received: by world.std.com (5.65c/Spike-2.0) id AA17994; Tue, 16 Apr 1996 15:37:34 -0400 Date: Tue, 16 Apr 1996 15:37:34 -0400 From: bobduff@world.std.com (Robert A Duff) Message-Id: <199604161937.AA17994@world.std.com> To: ada-comment@sw-eng.falls-church.va.us Subject: Exception raised at end of text stream !topic Exception raised at end of text stream !reference RM95-A.13(13) !from Bob Duff <> !discussion Robert Dewar requested a (confirmation) AI on this topic: Suppose I get a stream from the Ada.Text_IO.Streams.Stream function. (The same question applies to the Wide_Text_IO version, and also to streams created by Ada.Streams.Stream_IO.) What happens if the stream's position corresponds to end-of-file, and I try to get an item using T'Read, for some type T? Is End_Of_File raised? The answer is, no, End_Of_File is not raised. Data_Error is raised, or else a junk value is returned. A.13(13,17) say: 13 The exception Data_Error can be propagated by the procedure Read (or by the Read attribute) if the element read cannot be interpreted as a value of the required subtype. ... 17 If the element read by the procedure Read (or by the Read attribute) cannot be interpreted as a value of the required subtype, but this is not detected and Data_Error is not propagated, then the resulting value can be abnormal, and subsequent references to the value can lead to erroneous execution, as explained in 13.9.1. The Read procedure in package Streams clearly does not raise any exception on end-of-stream -- if there are no more bytes available, it returns a count of zero bytes read. So, clearly, if you're trying to interpret zero bytes as something-or-other, you'll get Data_Error. Alternatively, the implementation might take advantage of A.13(17), and return junk. The Read attribute doesn't know that it's reading from a file -- it's reading from a stream, which may or may not have a concept of "end of stream". Robert points out that it is somewhat strange to raise Data_Error, since streams having nothing in particular to do with I/O. True; perhaps the Streams package ought to have defined its own exceptions, but it's too late for that now. I certainly see no reason to raise End_Error. A user-defined stream can raise whatever exceptions it likes, but the language-defined ones should not, and the Read attribute needs to work in the presence of any stream. - Bob From bobduff@world.std.com Tue Apr 16 15:37:40 1996 Return-Path: Received: from inmet.camb.inmet.com by dsd.camb.inmet.com (4.1/SMI-4.1) id AA24465; Tue, 16 Apr 96 15:37:40 EDT Received: from sw-eng.falls-church.va.us (ns1.sw-eng.falls-church.va.us) by inmet.camb.inmet.com (4.1/SMI-4.1) id AA25332; Tue, 16 Apr 96 15:37:54 EDT Received: from europe.std.com by sw-eng.falls-church.va.us (8.7.1/) id TAA05322; Tue, 16 Apr 1996 19:37:00 GMT Received: from world.std.com by europe.std.com (8.7.5/BZS-8-1.0) id PAA18956; Tue, 16 Apr 1996 15:37:28 -0400 (EDT) Received: by world.std.com (5.65c/Spike-2.0) id AA17982; Tue, 16 Apr 1996 15:37:33 -0400 Date: Tue, 16 Apr 1996 15:37:33 -0400 From: bobduff@world.std.com (Robert A Duff) Message-Id: <199604161937.AA17982@world.std.com> To: bobduff@world.std.com, dismukes@gnat.com, eachus@spectre.mitre.org Cc: ada-comment@sw-eng.falls-church.va.us In-Reply-To: <199604121745.AA04229@world.std.com> (bobduff@world.std.com) Subject: Re: Freezing of incomplete types !topic Freezing of incomplete types !reference RM95-13.14(11) !reference 96-5476.a Robert A Duff 96-4-12 !reference 96-5489.a Robert I Eachus 96-4-15 !from Bob Duff <> !discussion I wrote the following, which is wrong. I had forgotten that incomplete types are special -- the freezing rules don't need to cover them, because there are other rules specific to incomplete types, which are much more strict than the freezing rules. Thanks to Robert Eachus for reminding me. > Consider the following example: > > package P is > type T is private; > private > type R(D: Boolean); -- Completed in body > type T is access all R; > Obj: T; > end P; > > package body P is > B1: Boolean := Obj.D; -- Legal? Illegal. > procedure Q is separate; -- Legal? Legal. > type R(D: Boolean) is null record; > begin > Q; > end P; > > First question, pointed out to me by Gary Dismukes: > Does the declaration of B1 freeze the type R? If we replaced "Obj.D" > with "Obj.all.D", then it would freeze R, and therefore be illegal. > Clearly, the same rules should apply to "Obj.all.D" and "Obj.D". Nonsense. 3.10.1(10) already covers this case: 10 A dereference (whether implicit or explicit -- see 4.1) shall not be of an incomplete type. > 13.14(11-11.b) says: > > 11 {freezing [entity caused by a name]} At the place where a name > causes freezing, the entity denoted by the name is frozen, unless > the name is a prefix of an expanded name; {freezing [nominal > subtype caused by a name]} at the place where an object name > causes freezing, the nominal subtype associated with the name is > frozen. > 11.a Ramification: This only matters in the presence of deferred > constants or access types; an object_declaration other than a > deferred_constant_declaration causes freezing of the nominal > subtype, plus all component junk. > > 11.b Implicit_dereferences are covered by expression. > > It seems that (11.b) is wrong -- an implicit_dereference is *not* an > expression. 13.14(11) should be extended to cover > implicit_dereferences, so that the "Obj" in "Obj.D" freezes the same > things that "Obj.all" would freeze. That is, an implicit_dereference > should freeze the denoted object and its nominal subtype. I still think that (11.b) is wrong. Here's a different example, which I think illustrates the problem here: package P is type T(D: Integer) is private; type A is access T; Obj: A; I: Integer := Obj.D; -- Does this freeze T? private type T(D: Integer) is ...; end P; The declaration of I would clearly be illegal if we had written Obj.all.D. It should be illegal as written, too. > Second question: Does the procedure body Q freeze R? It certainly > should, for all the reasons given in 13.14(3.d) -- in particular, Q > might contain something that would need to freeze R, but we can't tell > at compile time of the body of P. > > 13.14(3) says: > > A noninstance body causes freezing of each entity declared before it > within the same declarative_part. > > It not cover this case, because R is not declared in the same > declarative_part as the body Q. Therefore, "declarative_part" should be > changed to "declarative region", so Q freezes R, and is thus illegal. Nonsense again. If the body of Q contains anything nasty, the rules for incomplete types will make it illegal. There is no need to make the freezing rules cover this case. - Bob From bobduff@world.std.com Tue Apr 16 15:37:41 1996 Return-Path: Received: from inmet.camb.inmet.com by dsd.camb.inmet.com (4.1/SMI-4.1) id AA24466; Tue, 16 Apr 96 15:37:41 EDT Received: from sw-eng.falls-church.va.us (ns1.sw-eng.falls-church.va.us) by inmet.camb.inmet.com (4.1/SMI-4.1) id AA25333; Tue, 16 Apr 96 15:37:55 EDT Received: from europe.std.com by sw-eng.falls-church.va.us (8.7.1/) id TAA05320; Tue, 16 Apr 1996 19:36:59 GMT Received: from world.std.com by europe.std.com (8.7.5/BZS-8-1.0) id PAA18957; Tue, 16 Apr 1996 15:37:28 -0400 (EDT) Received: by world.std.com (5.65c/Spike-2.0) id AA17986; Tue, 16 Apr 1996 15:37:34 -0400 Date: Tue, 16 Apr 1996 15:37:34 -0400 From: bobduff@world.std.com (Robert A Duff) Message-Id: <199604161937.AA17986@world.std.com> To: ada-comment@sw-eng.falls-church.va.us Subject: A couple of freezing issues !topic A couple of freezing issues !reference RM95-13.14(00) !from Bob Duff <> !discussion Does an implicit call to Initialize freeze the subprogram? The freezing rules seem to apply to explicit constructs. For example: type T is new Controlled with record...; procedure Initialize(X: in out T); X: T; -- Implicit call to Initialize. for Initialize'Address use ...; -- Legal? If this is legal, it will raise P_E, but 13.14(1.o) argues that that's no excuse. The same question applies to Adjust and Finalize. It also seems unclear whether an implicit type conversion freezes. E.g.: type Color is (Red, Yellow); subtype S is Color range Red..Red; -- The expression "Red" freezes type Color. BUT: type T is range 1..100; subtype S is T range 1..10; -- Freezes type T? The expressions "1" and "10" are of type universal_integer, so T is not frozen. But it seems like it should be -- the value is implicitly converted to type T, and so it's very much like an expression of type T. 13.14(12) seems to agree that the implicit conversion should freeze. 12 [{freezing [type caused by a range]} At the place where a range causes freezing, the type of the range is frozen.] 12.a Proof: This is consequence of the facts that expressions freeze their type, and the Range attribute is defined to be equivalent to a pair of expressions separated by ``..''.} Here's a case not covered by 13.14(12): type T is range 1..10; function F(X: T) return boolean; X: Boolean := F(10); -- Freezes type T? for T'Size use 4; -- Legal? (I hope not.) It seems to me the recent (draft) AI on freezing rules should cover these two cases as well. - Bob From bobduff@world.std.com Tue Apr 16 16:33:20 1996 Return-Path: Received: from inmet.camb.inmet.com by dsd.camb.inmet.com (4.1/SMI-4.1) id AA24868; Tue, 16 Apr 96 16:33:20 EDT Received: from sw-eng.falls-church.va.us (ns1.sw-eng.falls-church.va.us) by inmet.camb.inmet.com (4.1/SMI-4.1) id AA26430; Tue, 16 Apr 96 16:33:33 EDT Received: from europe.std.com by sw-eng.falls-church.va.us (8.7.1/) id UAA07151; Tue, 16 Apr 1996 20:32:38 GMT Received: from world.std.com by europe.std.com (8.7.5/BZS-8-1.0) id QAA25124; Tue, 16 Apr 1996 16:33:01 -0400 (EDT) Received: by world.std.com (5.65c/Spike-2.0) id AA28740; Tue, 16 Apr 1996 16:33:06 -0400 Date: Tue, 16 Apr 1996 16:33:06 -0400 From: bobduff@world.std.com (Robert A Duff) Message-Id: <199604162033.AA28740@world.std.com> To: bobduff@world.std.com Cc: dewar@gnat.com, dewar@gnat.com, ada-comment@sw-eng.falls-church.va.us In-Reply-To: <199604131828.AA01826@world.std.com> (bobduff@world.std.com) Subject: Re: Dewar's comments on the SIZE problem and Issue !topic Re: Dewar's comments on the SIZE problem and Issue !reference RM95-13.1(14) !reference RM95-13.3(55) !reference 96-5486.a Robert Dewar !reference 96-5487.a Robert A Duff 96-4-13 !from Bob Duff <> !discussion Another correction. Robert Dewar wrote: > > At the Paris meeting, we considered it essential that a size clause for > > a first subtype be imposed on all subsequent subtypes, because otherwise > > confirming rep clauses would be impossible. And I replied: > Unfortunately, Ada 95 allows: > > type T is range 0..1; > for T'Size use 1; > subtype S is range -1..1; I meant "subtype S is T'Base range -1..1;". My point was that S has a ^^^^^^ wider range than the first subtype, so: > Clearly, we cannot require that S'Size be 1. > > I suppose we could require it for subtypes whose range happens to be > small enough. > > No, that won't work, either, because the range might not be known at > compile time. I guess the rule would have to say something about > staticness. Or, we could make it all implementation-defined, and let > implementations worry about how to be compatible with (various) Ada 83 > compilers. Sorry for the confusion. - Bob From bobduff@world.std.com Tue Apr 16 16:33:24 1996 Return-Path: Received: from inmet.camb.inmet.com by dsd.camb.inmet.com (4.1/SMI-4.1) id AA24900; Tue, 16 Apr 96 16:33:24 EDT Received: from sw-eng.falls-church.va.us (ns1.sw-eng.falls-church.va.us) by inmet.camb.inmet.com (4.1/SMI-4.1) id AA26431; Tue, 16 Apr 96 16:33:37 EDT Received: from europe.std.com by sw-eng.falls-church.va.us (8.7.1/) id UAA07148; Tue, 16 Apr 1996 20:32:35 GMT Received: from world.std.com by europe.std.com (8.7.5/BZS-8-1.0) id QAA25123; Tue, 16 Apr 1996 16:33:01 -0400 (EDT) Received: by world.std.com (5.65c/Spike-2.0) id AA28752; Tue, 16 Apr 1996 16:33:06 -0400 Date: Tue, 16 Apr 1996 16:33:06 -0400 From: bobduff@world.std.com (Robert A Duff) Message-Id: <199604162033.AA28752@world.std.com> To: dewar@gnat.com, ada-comment@sw-eng.falls-church.va.us In-Reply-To: <199604131828.AA01826@world.std.com> (bobduff@world.std.com) Subject: Re: Dewar's comments on the SIZE problem and Issue !topic Re: Dewar's comments on the SIZE problem and Issue !reference RM95-13.1(14) !reference RM95-13.3(55) !reference 96-5486.a Robert Dewar !reference 96-5487.a Robert A Duff 96-4-13 !from Bob Duff <> !discussion Robert and I have discussed the Size issue in private e-mail lately. (It's a hobby we have, which has taken up most of our spare time in the last few years. ;-) ) Anyway, Robert recommends the following (I'm paraphrasing what he wrote): Keep the RM rules (13.3(55)) as they are with respect to default sizes. Add a rule that the minimum size default rule does not apply to subtypes that happen to statically match the first subtype. Implementation Permission: *Allow* implementations to support Size clauses for secondary subtypes. Say that two subtypes do not statically match if their Sizes differ (this can be interesting only if one or other of them is a subtype whose Size has been set using the above permission). I can live with Robert's recommendations. I won't go *quite* so far as to say I *agree* with them -- I don't strongly disagree. ;-) How's that for wishy-washy? Robert notes that if the above Implementation Permission is not granted by the ARG, then GNAT will implement essentially the same thing, but call it by a different name ('Subtype_Size). This is important, because when porting real Ada 83 code to GNAT, such a feature has been needed. Robert says: P.S. I do not care two hoots about Alignment, I think having Alignment as a subtype specific attribute is silly, and GNAT ignores the possibility of different subtypes having different alignments as much as it can! Bob says: I agree -- it's not important. For uniformity, we could extend the Impl Permission to Alignment, too. No big deal. The only important thing, is that if Alignments of subtypes can be different, we can't have static matching of those subtypes. Alignments are largely implementation dependent anyway, so this is, I suppose, the implementer's problem. - Bob From bobduff@world.std.com Tue Apr 16 17:23:43 1996 Return-Path: Received: from inmet.camb.inmet.com by dsd.camb.inmet.com (4.1/SMI-4.1) id AA25189; Tue, 16 Apr 96 17:23:43 EDT Received: from sw-eng.falls-church.va.us (ns1.sw-eng.falls-church.va.us) by inmet.camb.inmet.com (4.1/SMI-4.1) id AA27561; Tue, 16 Apr 96 17:23:57 EDT Received: from europe.std.com by sw-eng.falls-church.va.us (8.7.1/) id VAA08383; Tue, 16 Apr 1996 21:23:02 GMT Received: from world.std.com by europe.std.com (8.7.5/BZS-8-1.0) id RAA00783; Tue, 16 Apr 1996 17:23:30 -0400 (EDT) Received: by world.std.com (5.65c/Spike-2.0) id AA03391; Tue, 16 Apr 1996 17:23:36 -0400 Date: Tue, 16 Apr 1996 17:23:36 -0400 From: bobduff@world.std.com (Robert A Duff) Message-Id: <199604162123.AA03391@world.std.com> To: ada-comment@sw-eng.falls-church.va.us Subject: Size of Mutable Variables !topic Size of Mutable Variables !reference RM95-13.3(40) !from Bob Duff <> !discussion What is the meaning of the Size attribute for an unconstrained variable that is of a mutable type? Consider: subtype Small_Natural is Natural range 0..100; type Mutable(Len: Small_Natural := 0) is record Chars: String(1..Len); end record; X: Mutable; Suppose the implementation allocates the maximum possible size for X (perhaps 104 bytes). The "current size" of the value of X (i.e. the "constrained size", with Len constrained to 0) is perhaps just 4 bytes (for Len -- the Chars field is empty). Should X'Size be the current size (perhaps 4*8) or the maximum size (perhaps 104*8)? The RM does not answer this question. After some discussion with Tucker and Robert Dewar, I believe the answer should be the max size. Here's why: Suppose we add a Size clause to the above: for X'Size use 104*8; -- Specify the Size of the *object*. Clearly, this will not be legal if 104*8 is less than the max possible size. By 13.1(17), a query of X'Size *must* now return 104*8. 13.1(17.a) gives an example of this. So, in the case of a specified Size (on the object), the query *cannot* return the current size. To preserve the principle that confirming rep clauses shouldn't change things, we must use the same rule even when there's *not* a Size clause. Now, suppose we have a constrained object: subtype Mutable_3 is Mutable(Len => 3); Y: Mutable_3; Z: constant Mutable := (Len => 3, Chars => "abc"); Here, the compiler will not allocate the max size. Y'Size and Z'Size should clearly be the *constrained* Size -- the Size given that Len = 3. Now, suppose we have a parameter: procedure Proc(Param1: Mutable; -- Constant; therefore constrained. Param2: in out Mutable3; -- Constrained. Param3: in out Mutable) is begin ... end Proc; Proc(X, X, X); -- Unconstrained actual parameters. Proc(Y, Y, Y); -- Constrained actual parameters. Inside Proc, Param1'Size and Param2'Size should be the constrained size, based on the value of the actual parameter's discriminant. The alternative would be to return the max size if the actual parameter denotes an unconstrained object. But that's not really reasonable from an implementation point of view -- inside Proc, we don't know whether the actual denotes an unconstrained object. For Param3, however, we *do* know whether the actual is constrained or unconstrained -- it is necessary to pass extra dope to implement the 'Constrained attribute. Therefore, Param3'Size should be the max size, or the constrained size, depending on the constrainedness of the actual view. (Note: I said "view" there because the actual could be another formal -- we should care about the constrainedness of the actual *view*, not the constrainedness of the actual *object*.) Note: all aliased objects are constrained, so the parameter issue does not come up for access values. That is, Ptr.all'Size will clearly always return the constrained size. My conclusion from all this is that you have to view a declared object as being a fixed-size container. Thus, 'Size should return the max size, if that's what was allocated. Now, what about implementations that don't allocate the max? That is, implementations that use the deallocate/reallocate approach, when assigning to a mutable record? Presumably, such an implementation would return the constrained size, even when the object is unconstrained. One might argue that we should make the rules the same for both kinds of implementation. However, in the example with the rep clause: for X'Size use 104*8; -- Specify the Size of the *object*. it would seem that the RM forbids, or at least frowns upon, the deallocate/reallocate implementation in this case. In any case, the RM requires X'Size to be 104*8. Another point is that you can have aliased components of a record. So you can have pointers into the middle. This implies that the deallocate/reallocate approach is questionable anyway, in the general case. (In Ada 83, the same problem occurs when you rename a component. One Ada 83 compiler, in fact, had exactly this bug -- renaming was implemented as a pointer to the component, and a size-changing assignment to the outer record caused the pointer to dangle. Here, I'm not talking about a discriminant-dependent component, whose renaming is illegal -- just a regular component declared before the variant part. You could get around this for renaming, by implementing renaming differently -- store a pointer to the beginning of the outermost object, and an offset. But that implementation is not reasonable for access-to-components, because unlike renamings, access values can be assigned, so you would have a rather severe distributed overhead. It seems to me we worried about this case during the 9X design, and we asked the DR's what to do. They said to make the rules about access-to-component the same as those for renaming-of-component, which essentially forbids the deallocate/reallocate implementation.) If an implementation does choose the deallocate/reallocate implementation (presumably just in those cases where it works), then it should be free to return the constrained size for an unconstrained object. It seems to me that the answer to the above questions should, at most, be Implementation Advice, saying that Size "should" be such-and-such in these cases. I don't think a hard requirement is called for in this case (even for the SP Annex). - Bob