To: J3 J3/22-130 From: Malcolm Cohen Subject: Results of J3 Fortran interp letter ballot #38 Date: 2022-February-27 Here are the results of J3 letter ballot #38 on Fortran interpretations that officially closed 25-January-2022. The ballot is in J3 paper 22-103 for meeting #226. If I have omitted, or transcribed a vote or a comment incorrectly, please let me know. Voter / interp F18 F18 F18 025 033 034 Richard Bleikamp Y Y Y Reuben D. Budiardja C Y Y Daniel Chen N Y Y Malcolm Cohen c y y Robert Corbett N Y C Brian Friesen Y Y Y Zach Jibben N Y Y Gary Klimowicz N Y Y Mark LeAir N Y Y Steve Lionel Y Y Y Jon Steidel N Y Y LB #38 Result N Y Y where Y means "yes" C "yes with comment" N "no with comment" and lower case has the same meaning but is not a formal vote. (*) Mark LeAir is an alternate for Bryce Adelstein-Lelbach Reuben D. Budiardja is an alternate for David Bernholdt Zach Jibben is an alternate for Ondrej Certik Malcolm Cohen is an alternate for Steve Lionel (not voting here) Jon Steidel is an alternate for Lorri Menard Not Voting Thomas Clune Siddhartha Ghosh Bill Long Karla Morris Craig Rasmussen Srinath Vadlamani The interps marked "Y" pass with no change. The interps marked "A" pass with some minor fixes, as noted below. The interps marked "N" fail. The comments for each interp are attached below in the same order as the table above. Within each interp, the order is by order of voting. Interps that passed unchanged with all Y votes and no comments are not listed in the discussion below. The edited interps in their final form are attached and will appear in the next version of 006. /Malcolm *************************************************************************** F18/025 Robert Corbett's NO vote on F18/025 I previously argued that the proposed answer could break more existing code than other possible emendations and that treating default initializations as attributes is unintuitive. In reviewing the proposed answer for interpretation F18/025, I realized that the proposed answer creates a restriction that cannot, in the general case, be checked at compile time. Other possible fixes for the problem could be checked at compile time. An obvious way to evade the compile-time checks is to define an external procedure that has a dummy argument which has the version of the sequence or BIND type that does not have default initialization. Checking whether procedures match their interfaces in other files cannot be checked at compile time, and so, a call or function reference can create a case where the pointer value becomes accessible. The mismatch between the the interface and the procedure could be detected at link time or run time, but implementations that do such checks are rare. The problem that needs to be solved is that default initialization of components creates a means to assign a data object pointer a value that could allow pure code to define or redefine a variable that should not be touched. The constraints placed on pure code to avoid this problem for variables do not allow the such assignments. Placing similar restrictions on components with default initializations of object pointers solves the problem in a way that can be detected at compile time. Sequence and BIND types could be banned from appearing in array and structure constructors, in object declarations, and in the MOLD= specifiers of ALLOCATE statements. Many other ways of solving the problem are possible, but the one proposed above closely corresponds to the existing restrictions on pointers that are not components. Malcolm Cohen's comment on F18/025 Robert argued that the restriction was undesirable because some checks were not possible at compile time, because users can provide incorrect interface blocks. Well, if we're letting people have incorrect interface blocks (i.e. they are lying to the compiler) to evade the restriction, they can just describe an impure procedure as PURE, and thus escape *all* the purity requirements. The fact that interface blocks cannot be checked at compile time does not make the purity requirements less useful, and is just completely immaterial to the question at hand. The question boils down to whether two types that behave differently are "the same type". In computer science, types that behave differently are not the same type. Did we intend to make a "type equality" rule that violates both computer science and common sense? The evidence available, including the ambiguity of the current wording, would suggest not. Gary Klimowicz's NO vote on F18/025 (1) I find Bob Corbett's comments compelling. (2) From my experience with other languages with duck typing, type equivalence for generic resolution is based on the set of components and values that objects of the type can take on. It is not based on how they obtain those values. Component initialization is about the latter, not the former. Mark LeAir's NO vote on F18/025 I agree with Bob Corbett's dissension. Also, my initial concern on the compiler implementation stands. I feel it unnecessarily complicates the compiler implementation with regard to type comparison. Jon Steidel's NO vote on F18/025 As Bob Corbett points out, nowhere in the standard is there any indication that default initialization or lack there of is an attribute. This is a 2003 feature, implemented in many compilers, and no compiler ever considered default initialization in determination of type. Breaking existing code has been a concern and a justification for not making changes to features in published versions of the standard. Making this change may well break existing programs. Daniel Chen's NO vote on F18/025 I share the same concern about adding component initialization as an attribute and be involved in type determination. Reuben D. Budiardja's comment on F18/025 There are concerns about whether this is check-able at compile time and whether most compilers are even checking this for type equivalence. Another concern is whether this would break existing code. While I share those concerns, I think it is necessary to include this in the standard to prevent problematic / bad code and to be explicit about it. Zach Jibben's NO vote on F18/025 I find the criticism from Bob and others on this point convincing. Making component initialization an attribute seems to create more problems than it solves. /Interp notes that although the standard does not explicitly state that component initialization is an attribute, it also does not explicitly state that it is not, and it seems to fit the description of attributes in clause 8. Thus the standard is ambiguous (making all those alleged programs non-conforming) and needs correction, regardless of one's opinion of how best to resolve the problem with pure procedures. F18/025 FAILS. F18/034 Robert Corbett's comment on F18/034 The additional restrictions proposed in F18/034 are not necessary in the Fortran 2018 standard. No context in which IEEE_GET_FLAG and IEEE_GET_HALT_MODE may appear causes a problem for PURE procedures. The proponent of this answer for the interpretation argued that it would be easy to extend the language to create cases where the restrictions are needed. I agree that it is possible to extend the language in a way that the restrictions needed. I do not think it will be easy. The restrictions are unnecessary, but not onerous, so I do not object to the proposed answer to F19/034. /Interp notes that F18/034 does not impose any additional restrictions; in fact it makes those procedures PURE. F18/034 passes unchanged. ---------------------------------------------------------------------- NUMBER: F18/025 TITLE: Is component initialization an attribute? KEYWORDS: Component initialization, SEQUENCE, Generic DEFECT TYPE: Erratum STATUS: Passed by J3 meeting QUESTION: Consider MODULE m1 TYPE t SEQUENCE INTEGER :: a = 1 END TYPE END MODULE MODULE m2 TYPE t SEQUENCE INTEGER :: a = 999 END TYPE END MODULE MODULE m USE m1,t1=>t USE m2,t2=>t END MODULE The normative text on attributes states: "Every data object has a type and rank and can have ... other properties that determine the uses of the object. Collectively, these properties are the attributes of the object." It does seem that default initialization of components determines the uses of an object, but there is no clear statement either way that specifies that it is or is not an attribute. Obviously, it cannot appear in an attribute specification statement, but then, none of the attributes of a component can appear there. Q. Is component initialization an attribute? This affects type equivalence, and thus generic resolution and pure procedure semantics. For example, PROGRAM test1 USE m TYPE(t1) :: x = t1(0) CALL sub(x) ! Has INTENT(OUT), therefore PRINT *,x ! we expect x%a to be now equal to 1. END PROGRAM SUBROUTINE sub(y) USE m TYPE(t2),INTENT(OUT) :: y PRINT *,y ! We expect y%a to be now equal to 999. END SUBROUTINE This is only a valid program if type T1 is considered to be the same as T2, i.e. if component initialization is not an attribute. But then, is X%A initialised to 1 at the CALL, or to 999 on entry to SUB? Whichever, it seems the user will be surprised. Similarly, if component initialization is an attribute, then MODULE mg USE m INTERFACE s MODULE PROCEDURE s1,s2 END INTERFACE CONTAINS SUBROUTINE s1(a) TYPE(t1) a ... END SUBROUTINE SUBROUTINE s2(a) TYPE(t2) a ... END SUBROUTINE END MODULE would specify a valid generic interface, but if it is not an attribute the module MG is not valid. Finally, if component initialization is not an attribute, it might circumvent restrictions aimed at preventing side-effects of pure procedures, for example: MODULE safe REAL,TARGET :: x TYPE t SEQUENCE REAL,POINTER :: p END TYPE END MODULE MODULE bad USE safe,ONLY:x TYPE t SEQUENCE REAL,POINTER :: p => x END TYPE END MODULE MODULE unsafe CONTAINS PURE SUBROUTINE s(a,b) USE safe,ONLY:t1=>t USE bad,ONLY:t2=>t REAL,INTENT(OUT) :: a REAL,INTENT(IN) :: b TYPE(t1) oops oops = t2() ! Only valid if component init not an attr. oops%p = a ! And then this modifies a global variable. a = b END SUBROUTINE END MODULE ANSWER: The value produced by component initialization was intended to be an attribute. An edit is provided to clarify this ambiguity. EDIT to 18-007r1: [67:18] 7.5.2.4 Determination of derived types, p2, After "attributes" insert "(including the value of any default initialization, converted if necessary to the type, type parameters, and shape of the component)", making that sentence read "Data entities also have the same type if they are declared with reference to different derived-type definitions that specify the same type name, all have the SEQUENCE attribute or all have the BIND attribute, have no components with PRIVATE accessibility, and have components that agree in order, name, and attributes (including the value of any default initialization, converted if necessary to the type, type parameters, and shape of the component)." {Make it clear that default initialization is considered to be an attribute for the purposes of type equivalence.} SUBMITTED BY: Malcolm Cohen HISTORY: 21-128 m223 Submitted 21-128r1 m223 Revised 21-128r2 m223 Passed by J3 meeting 223, 6-5. 21-184r1 m225 Failed J3 letter ballot #37 21-196 m225 Revised edit, passed by J3 meeting 225, 9-3. ---------------------------------------------------------------------- ---------------------------------------------------------------------- NUMBER: F18/033 TITLE: E/EN/ES/D output exponent when w=0 KEYWORDS: I/O, E_format DEFECT TYPE: Erratum STATUS: Passed by J3 meeting QUESTION: Consider the following program: integer, parameter :: DP = selected_real_kind (10,300) integer, parameter :: QP = selected_real_kind (10,3000) real(DP) :: A real(QP) :: B A = 0.12345E123_DP write (*,'(E0.7)') A ! (1) B = 0.12345E1234_QP write (*,'(E0.7)') B ! (2) end 13.7.2.1 p1(6) says: "On output, with I, B, O, Z, D, E, EN, ES, EX, F, and G editing, the specified value of the field width w may be zero. In such cases, the processor selects the smallest positive actual field width that does not result in a field filled with asterisks." and (5) above it says: "On output, if an exponent exceeds its specified or implied width using the E, EN, ES, EX, D, or G edit descriptor, or the number of characters produced exceeds the field width, the processor shall fill the entire field of width w with asterisks. However, the processor shall not produce asterisks if the field width is not exceeded when optional characters are omitted." If we then look at 13.7.2.3.3 (E and D editing), table 13.1 (Exponent forms) says that for the Ew.d form and where the absolute value of the exponent is greater than 99 but less than or equal to 999, the form of the exponent omits the exponent letter. Q1: According to the text of the standard, the exponent form for the output at (1) must be "+123", omitting the exponent letter. Was this intended? Isn't the whole point of w=0 to produce minimal width but complete values? Note that the exponent letter is not an "optional character". Q2: What should the output at (2) be? It would seem that the standard does not provide an interpretation that results in anything but the whole field being filled with asterisks, since the exponent overflows three digits, yet w=0 disallows that. ANSWER: A1: No, this was not intended. E0.d should behave as if it were E0.dE0 (similarly for EN and ES), where the exponent letter is present and there are the minimum number of digits needed to represent the exponent. There is no D0.dE0 form, however, so it needs to be a special case in the standard. A2: The current text provides no interpretation. The proposed change to behave as E0.dE0 provides a reasonable interpretation. Note that G0.d does not have this problem, as the exponent form is specified as a "reasonable processor-dependent value ... of e". The EX descriptor also does not have this problem. EDITS to 18-007r1: 13.7.2.3.3 (E and D editing) 264:Table 13.1 (E and D Exponent forms) Row 1: Add after "Ew.d": " with w > 0" Row 3: Add after "Ew.dE0": " or E0.d" Row 4: Add after "Dw.d": " with w > 0" Add new Row 5: Column 1: "D0.d" Column 2: "any" Column 3: "D\pmz1z2 . . . zs or E\pmz1z2 . . . zs" 13.7.2.3.4 (EN editing) 265:Table 13.2 (EN Exponent forms) Row 1: Add after "ENw.d": " with w > 0" Row 3: Add after "ENw.dE0": " or EN0.d" 13.7.2.3.5 (ES editing) 266:Table 13.3 (ES Exponent forms) Row 1: Add after "ESw.d": " with w > 0" Row 3: Add after "ESw.dE0": " or ES0.d" SUBMITTED BY: Steve Lionel HISTORY: 21-172 m225 Submitted 21-172r1 m225 Revised, passed by J3 meeting 225. ---------------------------------------------------------------------- ---------------------------------------------------------------------- NUMBER: F18/034 TITLE: Purity of IEEE_GET_FLAG and IEEE_GET_HALTING_MODE KEYWORDS: IEEE_GET_FLAG, IEEE_GET_HALTING_MODE, PURE DEFECT TYPE: Erratum STATUS: Passed by J3 meeting QUESTION: 17.11.1 General (in 17.11 Specifications of the procedures) states "all the subroutines are impure unless otherwise stated". Table 17.3 in 17.10 Summary of the procedures classes these as "ES", where "ES indicates that the procedure is an elemental subroutine". Since Fortran 2008, being elemental has no bearing on whether a procedure is pure or impure. If it is declared with the ELEMENTAL keyword it is pure by default, that is, if the IMPURE keyword does not appear; this however only applies to elemental procedures defined by subprograms, not ones defined by standard intrinsic modules. Looking at 17.11.5 and 17.11.6, the standard merely has "Class: Elemental subroutine" which again, does not indicate purity or impurity. The lack of a statement to the contrary means that the specification in 17.11.1 is operative, and therefore IEEE_GET_FLAG and IEEE_GET_HALTING_MODE must be impure. However, these were considered to be pure in Fortran 2003, as Fortran 2003 had no concept of an impure elemental procedure - it only had pure elemental procedures. Further evidence that the current situation might be a mistake is that the non-elemental subroutines IEEE_SET_FLAG and IEEE_SET_HALTING_MODE are explicitly specified to be pure. Are IEEE_GET_FLAG and IEEE_GET_HALTING_MODE intended to be pure? ANSWER: Yes, these subroutines were intended to be pure. Edits are provided to correct this mistake. EDITS to 18-007r1: [440:8] 17.10 Summary of the procedures, p3, line "ES indicates...", "an elemental subroutine" -> "a pure elemental subroutine". [443:23] 17.11.5 IEEE_GET_FLAG (FLAG, FLAG_VALUE), para 2 Class, "Elemental" -> "Pure elemental". [443:34] 17.11.6 IEEE_GET_HALTING_MODE (FLAG, HALTING), para 2 Class, "Elemental" -> "Pure elemental". SUBMITTED BY: Malcolm Cohen HISTORY: 21-202 m225 Submitted, passed by J3 meeting 225. ----------------------------------------------------------------------