J3 / 97-202 Date: 29 July 1997 To: J3 From: R. Maine Subject: Edits for subobject cleanup In working on the edits for M.2, I quickly ran into difficulties in writing edits that clearly and unambiguously say what we mean. It rapidly became evident that the main source of the problem was that the existing standard had severe internal inconsistencies in its treatment of subobjects. Its hard to add a new feature that has significant interaction with subobject concepts until we first get the existing stuff right. Thus, although I regard this paper and its edits as necessary for the M.2 item (in case someone asks why I'm doing cleanup of the subobject question, which isn't on our list), the edits herein don't directly do anything about the new functionality of M.2. That will be a separate paper (which looks like it will be a lot simpler with the "basics" better in place). This paper could be considered to be an interpretation request (actually several) and edits for f95. It looks to me like there are several actual errors in f95 in this area. See below for details. However, I've not tried to phrase this as an interp request or to do a minimal set of edits as might be appropriate for a corridendum. Instead, I've aimed at getting it right for f2k. Thus, I've included several edits that I think state things more clearly or otherwise cleanup things that were just confusing or strangely stated, but weren't actually wrong. If I were trying to do edits for an interp, they would probably be more limited. Though some of the flaws are basic enough that its hard to do a small, localized fix. The fundamental flaw is that the standard is inconsistent in its definition and use of "subobject" and related terms (notably "parent"). In some contexts, the term subobject is used to mean a part of an object. This is, in fact how it is defined in 2.4.3.1 and in the glossary. In other contexts, the term subobject is clearly used to indicate any that starts from the object in question. These 2 definitions are not at all consistent. They are very different concepts and both are needed. I suspect this flaw might have come in unnoticed with the introduction of pointers, because it is pointers that make it wrong. When a derived type has a pointer component, there is no reasonable way to interpret the target of the pointer as a "part" or "subobject" of the derived type. There are quite a few statements in the standard that are completely wrong if you try to force such an interpretation. (To pick one, from 14.7.1 - "An object is defined if and only if all of its subobjects are defined"). This gets even more ludicrous if there are several pointers in the . In addition to this fundamental flaw, there are quite a large number of smaller flaws, including 1. Failure to mention the real and imaginary parts of a complex object as subobjects until section 14. I didn't think of this myself until I ran into the mention in section 14. 2. Numerous places where the text seems to forget that a subobject is itself an object. 3. Several blatant errors of fact, including a. Definition of subobject that says it only applies to named objects, followed on the same page by an example of a subobjects of an unnamed object. b. The statement that all subobjects of a PARAMETER array have the parameter attribute. c. And others; see below. Plenty of separate f95 interp questions implied here if someone wants to try to separate them out; I didn't. I've spent about half a week pretty close to full time working on this. I can't swear to have caught every subtlety (I'm not that foolish), but I think its in pretty good shape. I'm quite confident that this is substantially more internally consistent than the f95 standard. All occurances of "subobject", "parent", or "designat" (regardless of case) in the standard were checked in developing this edit. Note, by the way, that the term "parent" is not used very many places at all; most occurances of the string "parent" are in the word "parenthesis". Here is a rough outline of the approach I've taken. I have kept the term "subobject" as its English usage (and its definition in the standard) implies - objects that are actually "part" of the parent. I've avoided most uses of the term "parent" to minimize possible confusions (the biggest exception is , which seemed unambiguous and clear as it was). I defined the bnf term "designator" in place of the old "subobject" (R602) and made both the bnf and text use that terminology. With my definition, a "designator" can include an unadorned name; it could be reserved for the forms where there is at least one subobject selector, but several things simplify if I allow it to include simple names as well. Enough introduction. The edits follow. I. Subobject designator and bnf fixes A "subobject designator" as defined in the standard doesn't necessarily designate a subobject; that is, it may designate something that is not a "part" of the parent in any meaningful sense. It does not mesh well with the definition of subobject. I propose that we just define this to be an "object designator". In fact, once we remove the "sub" from its terminology, we get some other simplifications almost for "free". We can then say that the name is followed by 0 or more selectors instead of 1 or more - that is a name itself is also a trivial case of an object designator. This will allow us to just say "object designator" instead of "name or subobject designator" in several places. This simplification isn't required, but I think it worthwhile. Likewise the bnf term "subobject" doesn't necessarily represent a subobject as defined. It invites all sorts of interpretation questions if the term "subobject" has one definition in the bnf and a different, incompatable definition in the text. Fortunately, the bnf term subobject is used only in a few places; namely in R601, R602, R701, R702, R540 (and their constraints). Thus, its not too hard to fix up. In 2.4.3.1 [16:7-8] "subobject designators" -> "object designators" [16:12] "a subobject designator" -> "an object designator" In 2.5.1 [18:4] "A <>" -> "An <>" And change the attached index entry correspondingly. [18:4] "one" -> "zero" [18:5+] Add shaded note "An object name is a special case of an object designator." In 2.5.5 [18:29] "data object name or data subobject designator" -> "data object designator" [18:33] "data object name, data subobject designator," -> "data object designator" [18:34] Delete ", data subobject," In 5.2.10 [61:36] "name or designator" -> "designator" Note to J3: This constraint doesn't appear to explicitly mention the issue of subobjects. One might argue that it is implcitly covered, but we were more explicit in comparable restrictions elsewhere. I'm not going to follow up on this aspect; it is independent of my edit. In 6.0 [73:2] "object name or subobject designator" -> "object designator" [73:5] "object name or subobject designator" -> "object designator" [73:7-14] replace R601 and its constraints with "R601 <> Constraint: shall not be a constant or a subobject of a constant." [73:15] Replace the line with "R602 <> <> " Note to J3: The point of calling out scalar-variable-name and array-variable-name as separate cases elludes me. Likewise, I don't know why it was important to call out as a constraint that array-variable-name shall be the name of a data object that is an array, while it is not equally important to say that scalar-variable-name shall be the name of a data object that is a scalar. Hmm, oh I see - 1.6.3 covers the scalar case, but not the array one; but we never need to make the distinction anyway. After we go to all this trouble to mention array-variable-name, it is never used anywhere else in the document. Note to J3: And the "subobject of a constant" terminology is more like that used elsewhere, in addition to avoiding the issue of defining "parent". In 6.1.2 [75:2-3] "a subobject designator" -> "an object designator" In 6.2 [75:42-43] "name or designator" -> "designator" In 7.1.1.1 [86:3-4] replace the 2 lines with "<> " [86:9-10] Delete these 2 lines. In 10.9 [178:30] "object name or a subobject designator" -> "object designator" In 10.9.1.1 [179:24] "subobject designators" -> "object designators" [179:44-45] "object name or subobject designator" -> "object designator" In Annex A [295:20-21] (definable) " or " -> "designator" [295:35] (designator) "" -> "" [298:15] (named) "a subobject designator" -> "an " Note to J3: Also fixes failure to italicize the term. [299:24] (reference) "a or " -> "an " [300:23] (structure component) " that" -> ". It" Note to J3: "that" would be wrong with the new terminology (and misleading with the old, implying that there are also parts of derived type objects that aren't components). [300:23-24] "" -> "" [300:27] "<>" -> "<>" And, of course, realphabetize the entry. [300:27] (subobject designator) "one" -> "zero" II. Other subobject fixes In 2.4.3.1 [16:4] Delete "named ". Note to J3: We define subobjects of unnamed character strings also. Note 6.3 even has an example of such. The restriction to named objects doesn't appear to have any useful function anyway. As best as I can tell, it was just an (incorrect) observation that all the cases defined happened to apply only to named objects. [16:6] After "(substrings), " add "portions of complex objects (real and imaginary parts), " [16:8] After "designators" add " or intrinsic functions" [16:16+] Add new paragraph "Subobjects of complex objects are referenced by intrinsic functions." Note to J3: I'm shocked that section 14.7.1 was the only place that ever mentioned that the real and imaginary parts of a complex object are subobjects. If we are going to say that (which makes sense), it would be good to have the definition of subobject correspond. This does mean that we have one form of subobject that cannot be referenced by a designator, but I suppose that's ok. Anyway, if we aren't going to include the parts of a complex object as subobjects, then we shouldn't refer to them that way in 14.7.1. In 5.1.2.8 [57:19+] Add as a new paragraph. "If an object has the TARGET attribute, then all of its nonpointer subobjects also have the TARGET attribute." [57:24+] Add a new shaded note "Every object designator that starts from a target object will have either the TARGET or POINTER attribute. If pointers are involved, the designator might not necessarily be a subobject of the original target object, but since pointers may point only to targets, there is no way to end up at a nonpointer that is not a target." Note to J3: This seems like a better place to treat this than trying to cover it separately for each kind of subobject. And this way, we don't forget to mention it for some kinds of subobjects. F95 forgets to say this about substrings and the real and imaginary parts of complex objects. Also, this wording avoids the necessity to talk about the term "parent object", which can be tricky in the presense of pointers. In 5.1.2.3 [53:13-14] "A dummy argument withh the INTENT(IN) attribute, or a subobject of such a dummy argument," -> "An object with the INTENT(IN) attribute" [53:44+] Add new paragraph "If an object has an INTENT attribute, then all of its subobjects have the same INTENT attribute. BEGIN NOTE If a dummy argument is a derived type with a pointer component, the pointer as a pointer is a subobject of the dummy argument, but the target of the pointer is not. Therefore, the restrictions on subobjects of the dummy object apply to the pointer in contexts where it is used as a pointer, but not in contexts where it is dereferenced to indicate its target. For example, if X is a dummy argument of derived type with an integer pointer component P, and X has INTENT(IN), then the statement X%P => NEW_TARGET is prohibited, but X%P = 0 is allowed (provided that X%P is associated with a definable target). END NOTE" Note to J3: The exact meaning of the INTENT restrictions in the presense of pointers was unclear in f95. Even without intent for pointer args, we need to address it because there are still pointer components. The interpretation I've proposed in the note above is consistent with what we voted to do with intent for pointer args. If we have any interpretation *OTHER* than something pretty close to the above, then I think its going to be hard to explain why intent for pointer args is different. In 5.2.10 [61:16] "object or subobject" -> "object" Note to J3: The original "or subobject" added no semantic content. I think it was probably trying to say something, but failed due to confusion of antecedents. I can't actually tell for sure what the original is saying. It could be trying to say that if a type has default initialization of even one component (or subcomponent), then no non-pointer object of that type can appear in a data-stmt-object-list. But you can have subobjects of such objects, as long as the subobjects are the components without default initialization. I could also make some other interpretations. Sounds to me like an interp question. The one thing I'm sure of is that the "or subobject" adds no semantic content as currently phrased; all it does is make one suspicious that perhaps it was supposed to mean something. [61:41-42] "subobject of a pointer" -> "object designator in which a pointer appears other than as the entire rightmost " [62:4] "shall not have a constant parent" -> "shall be a variable" [62:5] "shall not have a constant parent" -> "shall be a variable" Note to J3: These forms avoid the complications of defining the parent. Let the definition of variable handle that one one place. In 5.5.1 [66:40] After "shall not be", add "a designator with a base object that is " [66:41] Delete " sequence". Note to J3: This usage was overly complicated and confusing. The restriction certainly applies regardless of whether the derived type is sequence or not. Apparently the sequence qualification was added here because non-sequence derived types are disallowed on other grounds. But the items in this list are not exclusive, and it just confuses things to try to make them so. For example, it would have made just as much sense to say "a non-allocatable object of derived type containing a pointer at any level..." because allocatable objects were separately covered. In cases like this, it is better to state the restrictions in general form and recognize that a particular object might be disallowed for more than one of the reasons. [66:44] Add "or " before "a named constant" [66:44] Delete "a structure component, or a subobject of any of the preceding objects" [66:44+] Add new constraint "Constraint: An shall not be a designator that has more than one ." Note to J3: This substitutes for the structure component restriction in the original; this one can't be phrased just in terms of the base object. In 6.1.2 [75:16] "<>" -> "<>" The term "parent object" was used only a few places, and many of those were wrong or misleading. Several of them assumed that a data-ref always was a subobject of the parent, which simply was not true; I've fixed all of those to use "subobject" terminology. For the remaining few uses, where this definition is appropriate, I've changed the term to "base object", which I think has less danger of incorrectly implying a subobject relationship. As defined here, "base object" relates only to the syntax used in an object designator. [75:22] "parent" -> "base" [75:22-23] Delete the sentence that spans these lines. See the note about the edit at [76:39-40] for explanation. In 6.2.2 [76:39-40] Replace the sentence with "An array element or an array section never has the POINTER attribute." Note to J3: Everything else that was here is now said in sections 5.1.2.3 and 5.1.2.8....except for those things that were said here that were wrong. The old statement was not true in general for the PARAMETER attribute (namely, if the subscripts were variables). But I don't think we ever needed the statement anyway for the PARAMETER attribute; I think we have words allowing appropriately restricted "subobjects of constants" wherever it comes up. If we do need the statement here, then we need to rewrite it so that it is correct. The old wording also was at best questionable (and likely just wrong) in its identification of the applicable "parent" in the presence of pointers. In 6.3.1 [79:39-41] replace the whole paragraph with "An shall not depend on the value, bounds, allocation status, or association status of any other in the same ALLOCATE statement. A bound shall not depend on the or on the value, bounds, alocation status, or association status of any in the same ALLOCATE statement." Note to J3: Lets use the same kind of wording here as used for similar restrictions elsewhere in section 6.3. That is, instead of restricting "stuff" from appearing in a bound, we restrict the bound from depending on "stuff". Its just the same restriction from the other viewpoint. Either viewpoint can work, but doing all of the similar cases the same way helps get them right. Indeed, it looks like the original here did miss things. It restricts the bounds from depending on other allocate objects, but it fails to restrict an allocate object from depending on another allocate object. That is, it appears to allow type mytype real, pointer :: a end type type(my_type), pointer :: p ... allocate(p,p%a) My edit fixes this. [80:5-6] Delete "or subobject of an " Note to J3: A subobject of an allocate object depends on the association status or allocation status of the allocate object, so the explicit mention of subobject is unnecessary. If we did feel the need to keep it, we'd need to make it right in that it certainly is intended to also cover things that aren't subobjects (because of pointers). Same comment applies to the compatable edits below in 6.3.2 and 6.3.3. If we feel that something more explicit is needed, I'd prefer to add a separate statement somewhere to the effect that a dependence on a subobject constitutes a dependence on its parent (that's probably not quite the right words) instead of trying to get it all into this one sentence (and then repeating it several times). [80:6] "allocated in the same statement" -> "in the same ALLOCATE statement" Note to J3: Just for consistency in wording. [80:1-3] Move note 6.13 to [80:6+]. It seems out of place in the middle of the restrictions; goes better after them all. In 6.3.2 [82:15] Delete ", or subobject of another pointer-object," Note to J3: Also gets rid of the inconsistent comma usage. In 6.3.3 [82:22] Delete "or subobject of another allocate-object" Note to J3: Also gets rid of a typo failure to italicize. [82:25-26] Delete "or subobject of an allocate-object" In 7.1.6.2 [95:23-28] replace these lines with "(2) An obect designator with a base object that is a dummy argument that has neither the OPTIONAL nor the INTENT(OUT) attribute, (3) An object designator with a base object that is in a common block, (4) An object designator with a base object that is made accessible by use or host association, 7.5.1.5 [110:8] Delete "parent ". Note to J3: The term "parent" was superfluous here, and its definition was vague. 7.5.2 [110:43-44] Change this constraint to read "The shall have either the TARGET or POINTER attribute." Note to J3: The subobject stuff was superfluous. A subobject of something with the TARGET attribute either also has the TARGET attribute or is a POINTER. The only case where this hadn't previously been made explicit was for substrings, which we fixed in an edit above. Furthermore, by the use of the term "subobject" here was confusing because it was presumably intended to refer also to things that were not, in fact, subobjects (because of pointers). In 7.5.4.4 [119:2] Delete "or subobject" Note to J3: I never have been able to deduce what this sentence actually says; I can't parse it sensibly. But whatever it does or doesn't mean can't be changed by deleting "or subobject" because a subobject is an object. In 9.3 [138:16-18] Delete the paragraph. Note to J3: This paragraph was oddly inconsistent. Why did we mention subobjects for allocatable arrays, but fail to mention subobjects for pointers in the imediately preceding sentence? The whole paragraph is superfluous anyway. It is just one case of the far more general rules that pointers are required to be associated in order to define them (5.1.2.7) and allocatable arrays are required to be allocated in order to define them (6.3.1.2). There are bazillions of places in section 9 alone where we could state a comparable specific case; why is it stated only for this one? For example, we don't specifically say that an allocatable array in an input list must be allocated. And we don't say that if the in an assignment statement is allocatable, it must be allocated. It seems really out of place to say it here, but nowhere else. Makes it seem like there is something special about its application here; if there is anything so special, it certainly escapes me. In 12.4.1.5 [203:9] "A subobject it it" -> "A designator with it as the base object and with at least one subobject selector" In 12.4.1.6 [203:26] Delete the line and renumber. [205:9] Delete the line and renumber. Note to J3: If the dummy has a pointer component, the target of the pointer is not a "part" of the dummy, so these exceptions are superfluous. See also edits in 5.1.2.3 In 12.5.4 [211:28] Delete "parent " In 12.7.1 [214:3] "A dummy argument, or a subobject thereof," -> "An object designator with a dummy argument as the base object" In 14.6.3.3 [288:4] Delete "or subobjects" Note to J3: Added no content since a subobject is an object. In Annex A [300:25] (subobject) Delete "". [300:26] "or a substring" -> "a substring, or the real or imaginary part of a complex object" [300:43] (target) Add "nonpointer " before "".