To: J3 J3/20-132 From: Malcolm Cohen Subject: Results of the J3 Fortran interp letter ballot #36 Date: 2020-August-04 Here are the results of J3 letter ballot #35 on Fortran interpretations that officially closed 04-July-2020. The ballot is in J3 paper 20-130 for meeting #222. If I have transcribed a vote or a comment incorrectly, please let me know. Voter / interp F18 F18 F18 F18 015 016 017 018 LB #36 Result C Y C C Richard Bleikamp Y Y C Y Reuben Budiardja Y Y C Y Ondrej Certik Y Y N Y Daniel Chen Y Y C Y Tom Clune Y Y C Y Robert Corbett C Y C Y Brian Friesen Y Y Y Y Tom Knox Y Y Y Y Steve Lionel Y Y Y Y Bill Long Y Y C Y Lorri Menard Y Y C Y Dan Nagle Y Y Y Y John Reid y y y y Van Snyder Y C Y C 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. (*) John Reid is an alternate for Dan Nagle. Not Voting Gary Klimowicz (alternate Mark LeAir) Karla Morris (alternates Craig Rasmussen and Daniel Rouson) 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 *************************************************************************** Robert Corbett's comment on F18/015: I am looking at the new code for C6.8.2. I have yet to convince myself that the new variable "start" is necessary. If it is, I suggest initializing it with an initialization instead of an assignment. Also, the expression INT (0.01*NUM_IMAGES()) might be more clearly expressed as NUM_IMAGES() / 100 Result for F18/015 /interp agrees that these cosmetic changes simplify the example. /interp also notes that MAX(NUM_IMAGES()/100,0,MIN(NUM_IMAGES()-10,1)) does not need the ",0" as NUM_IMAGES()/100 will be non-negative unless the number of images is less than minus 99. But this will remain unchanged for now (perhaps WG5 can decide to polish the example here?). F18/015 passes as amended. F18/016 Host association changes in Fortran 2018 Van Snyder's comment on F18/016: I opposed the no-host-association semantics for interface bodies in 1986. My reasoning was that the prohibition makes it impossible to write an interface body for a dummy procedure that has a derived-type argument if the type is defined in the same scoping unit. It didn't make sense to me. I still don't understand what purpose it served. I don't remember the precise details of the discussion, and the Computer History Museum now has my correspondence with X3J3 from that time so I can't look it up. Result for F18/016 /interp agrees that the semantics of interface vis-a-vis host association was a controversial topic at the time, but considers that it has no bearing on the content of this interp. F18/016 passes unchanged. F18/017 Final subroutine invocation order Richard Bleikamp's comment on F18/017: The order in which finalizations are performed for the components of an object of derived type is confusing. I agree with some other committee members that the most desirable fix is too big for an interp. I am content with the small fix in the edits for this interp request for now, but hope the committee will pursue a better fix in the future. Reuben D. Budiardja's comment on F18/017: Although this interp fix issue with double finalization, it also allows an unintuitive order of finalization to be performed in certain situation that is processor dependent. A better fix, while desired by this committee member, may be too big for this interp. I hope this will be revisited before the next standard for consideration for a more thorough fix. Ondrej Certik's NO vote on F18/017: As we see it, the core conflict is between the finalization order prescribed by 7.5.6.2 and what is considered finalizable. The interp as it stands resolves this conflict (and the double finalization) by sacrificing the former to preserve the latter. This interp argues that including allocatables in the ordering in 7.5.6.2 was a design error, or never intended to be understood as such. We think the opposite; ignoring allocatable components in the definition of a finalizable type was the error, and that 7.5.6.2 as it stands does imply the finalization of allocatables and should continue to do so since it is the more useful behavior for users. Thus we suggested edits to do the opposite of the interp: preserve the finalization order by sacrificing the existing definition of finalizable. The effect is not to change the design of the standard, but rather to preserve what we see as the intended design expressed in 7.5.6.2. Robert Corbett's comment on F18/017: I agree that the order in which finalizations are performed for the components of an object of derived type is confusing. I think the most desirable fix is too big for an interp. (I think that the best fix requires a time machine.) For the interp, I agree with the small fix for the obvious problem (multiple finalizations). I think the committee should pursue a better fix in the upcoming revision of the standard (202x). Daniel Chen's comment on F18/017: We don't think alter the order of finalisation is the best fix for avoiding double finalisation for allocatable components, and believe requiring deallocation of allocatable components when it is finalised is more suitable solution. That being said, with Malcolm's explanation, we think the impact of F18/017 to the current users is very minimal. We also agree that requiring deallocation of allocatable components when it is finalised is more involved and cannot be contained as an interp. If the feature of requiring deallocation of allocatable components when it is finalised is considered for F202Y, we would like to see if the backward compatibility after F18/017 can be preserved. Tom Clune's comment on F18/017: F18/016 allows a nonintuitive ordering of finalization in certain important situations, but does solve the immediate problem. The committee should attempt to address this concern in future revisions of the standard. Bill Long's comment on F18/017: As part of the discussion of this interpretation on the J3 email list, Malcolm Cohen posted a reply that clarified the intent which included: 'Finally, the deallocation of C%A will produce the output "A"; this definitely follows the output "C", but there is no ordering specified between the other components. Given the two partial orderings C images_used) EXIT ! This failed image and ! all further failed images are in team 2 and do not matter. failed = failures(i) ! Check whether this is an old failed image. IF (j <= SIZE (old_failures)) THEN IF (failed == old_failures(j)) THEN j = j+1 CYCLE ! No action needed for old failed image. END IF END IF ! Allow for the failed image being a replacement image. IF (failed > NUM_IMAGES()-images_spare) failed = map(failed) ! Seek a non-failed image DO k = k+1, NUM_IMAGES () IF (IMAGE_STATUS (k) == 0) EXIT END DO IF (k > NUM_IMAGES ()) ERROR STOP "cannot recover" local_index [k] = failed team_number [k] = 1 map(k) = failed END DO old_failures = failures images_used = k ! Find the local indices of team 2 j = 0 DO k = k+1, NUM_IMAGES () IF (IMAGE_STATUS (k) == 0) THEN j = j+1 local_index[k] = j END IF END DO END IF SYNC ALL (STAT = status) IF (status/=0 .AND. status/=STAT_FAILED_IMAGE) EXIT outer ! ! Set up a simulation team of constant size. ! Team 2 is the set of spares, so does not participate. FORM TEAM (team_number, simulation_team, NEW_INDEX=local_index, & STAT=status) IF (status/=0 .AND. status/=STAT_FAILED_IMAGE) EXIT outer simulation : CHANGE TEAM (simulation_team, STAT=status) IF (status == STAT_FAILED_IMAGE) EXIT simulation IF (team_number == 1) THEN iter : DO CALL simulation_procedure (read_checkpoint, status, done) ! The simulation_procedure: ! - sets up and performs some part of the simulation; ! - resets to the last checkpoint if requested; ! - sets status from its internal synchronizations; ! - sets done to .TRUE. when the simulation has completed. IF (status == STAT_FAILED_IMAGE) THEN read_checkpoint = .TRUE. EXIT simulation ELSE IF (done) THEN EXIT iter END IF read_checkpoint = .FALSE. END DO iter END IF END TEAM (STAT=status) simulation SYNC ALL (STAT=status) IF (THIS_IMAGE () > images_used) done = done[1] IF (done) EXIT outer END DO outer IF (status/=0 .AND. status/=STAT_FAILED_IMAGE) & PRINT *,'Unexpected failure',status END PROGRAM possibly_recoverable_simulation " SUBMITTED BY: John Reid HISTORY: 19-182 m219 Submitted 19-182r3 m219 Revised draft - Passed by J3 meeting 19-228 m220 Failed J3 letter ballot #35 20-105 m221 Revised answer - Passed by J3 meeting 20-nnn m222 Passed as amended by J3 letter ballot #36 ---------------------------------------------------------------------- ---------------------------------------------------------------------- NUMBER: F18/016 TITLE: Host association changes in Fortran 2018 KEYWORDS: Host association DEFECT TYPE: Erratum STATUS: Passed by J3 letter ballot QUESTION: The default semantics for accessing entities by host association from an interface body appear to be different in Fortran 2018 than in Fortran 2008. Problem 1: In Fortran 2008, an interface body that is not a module procedure interface body cannot access entities in its host by host association unless an IMPORT statement is present in the interface body. The same rule applies by default in Fortran 2018 if the interface body is for an external or dummy procedure, but not if the interface body is for an abstract interface or a procedure pointer that is not a dummy procedure pointer (see 8.8 "IMPORT statement" [117:17-19]). For example, in DOUBLE PRECISION X ABSTRACT INTERFACE SUBROUTINE SUB(A) REAL(KIND(X)) A END SUBROUTINE END INTERFACE Fortran 2008 specifies that X is default REAL, and that therefore so is argument A, but Fortran 2018 specifies that X is accessed by host association and so argument A is double precision. Problem 2: The Fortran 2008 standard specified that a submodule has access to host entities, but the Fortran 2018 standard does not specify any default host association semantics for a submodule (it specifies IMPORT semantics only for nested scoping units (see 8.8 "IMPORT statement" [117:23-26]). That makes submodules using host association not conforming. For example, in MODULE mod INTERFACE MODULE SUBROUTINE S END SUBROUTINE END INTERFACE INTEGER,PARAMETER :: WP = KIND(0.0) END MODULE SUBMODULE (mod) submod REAL(WP) X END SUBMODULE the submodule references WP by host association in Fortran 2008, but Fortran 2018 does not specify any semantics and so the whole thing is not conforming. Problem 3: The Fortran 2008 standard specified that generic identifiers were accessible by host association, but the Fortran 2018 standard specifies that host association is for named entities. For example, in INTERFACE OPERATOR(.plus.) PROCEDURE plusfun END INTERFACE ... CONTAINS SUBROUTINE SUB(a,b,c) ... c = a.plus.b Fortran 2018 would not permit access to the user-defined operator. Problem 4: The Fortran 2018 standard specifies that BLOCK constructs access named entities in their hosts by host association. This makes no sense because BLOCK constructs already have access to entities in their hosts through inclusive scoping. Were these changes intended? ANSWER: No, none of these changes were intended. Edits are provided to restore the semantics specified in the Fortran 2008 standard. EDITS to 18-007r1: [117:18-19] 8.8 IMPORT statement, p2, second sentence, Replace "interface body for an ... procedure." with "interface body that is not a module procedure interface body." making the sentence read "This is the default for an interface body that is not a module procedure interface body." [117:25-26] 8.8 IMPORT statement, p4, second sentence, Change "for a nested scoping unit ... procedure" to "for a derived-type definition, internal subprogram, module procedure interface body, module subprogram, or submodule" making the sentence read "This is the default for a derived-type definition, internal subprogram, module procedure interface body, module subprogram, or submodule." [502:7] 19.5.1.4 "Host association", p1, first sentence Change "nested scoping unit" to "derived-type definition, interface body, internal subprogram, module subprogram, or submodule", Delete "named", Making the sentence read "A derived-type definition, interface body, internal subprogram, module subprogram, or submodule has access to entities from its host as specified in 8.8." SUBMITTED BY: Robert Corbett HISTORY: 19-257 m220 F18/016 Submitted 19-257r1 m220 Revised draft - Passed by J3 meeting 20-nnn m222 Passed by J3 letter ballot #36 ---------------------------------------------------------------------- ---------------------------------------------------------------------- NUMBER: F18/017 TITLE: Final subroutine invocation order KEYWORDS: FINAL ALLOCATABLE DEFECT TYPE: Erratum STATUS: Passed by J3 letter ballot QUESTION: Consider Module m Type base Contains Final basef End Type Type other Contains Final otherf End Type Type,Extends(base) :: t Type(other),Allocatable :: comp Contains Final tf End Type Contains Subroutine basef(a) Type(base),Intent(InOut) :: a Print *,'basef' End Subroutine Subroutine otherf(b) Type(other),Intent(InOut) :: b Print *,'otherf' End Subroutine Subroutine tf(c) Type(t),Intent(InOut) :: c Print *,'tf' End Subroutine End Module Program test Use m Call sub Contains Subroutine sub Type(t) x Allocate(x%comp) End Subroutine End Program When the subroutine is executed, it will finalize X on exit, so what is the expected output? Finalization of X occurs before auto-deallocation of X%COMP; this follows from 9.7.3.2 paragraph 9. According to 7.5.6.2, in sequence (1) the object's final procedure is invoked, i.e. TF is called, (2) finalizable components are finalized, i.e. OTHERF is called, (3) the parent is finalized, i.e. BASEF is called. And according to 7.5.6.3, deallocating X%COMP finalizes it, and so (4) OTHERF is called. I.e. the output is TF OTHERF BASEF OTHERF However, this violates the principle that you only finalize something once. Q1. Is X%COMP actually finalized twice? It could be argued that "finalizing X before deallocating X%COMP" only puts an order on invocation of TF, and in particular, finalizing the parent pseudo-component need not precede the deallocation. But this would still invoke OTHERF twice. Q3. Is the auto-deallocation of an allocatable component required to follow the finalization of other components and the parent pseudo-component? Now consider the case where X%COMP is not allocated (i.e. delete the ALLOCATE statement). According to 7.5.6.2, it should invoke (1) TF on X (2) OTHERF on X%COMP (3) BASEF on X%BASE however, as X%COMP is unallocated, the invocation in step (2) does not conform to the procedure reference requirements, i.e. the program is not conforming. Q2. Is X%COMP required to be allocated when X is finalized? DISCUSSION: An object is only finalized in situations listed in 7.5.6.3. Every such situation would also unconditionally deallocate any allocatable component, and if that component were finalizable, such deallocation would also unconditionally finalize the component (* except for intrinsic assignment, where a previous interpretation added an exclusion). Therefore it seems to be broken to finalize any allocatable component during finalization of the object it is contained in, as either it will be non-conforming, or will be finalized twice (* except for the previously-added exception). The design where allocatable entities are finalized at the time of deallocation would seem to be simpler, easier to understand, and less buggy. Perhaps the finalization of allocatable components in 7.5.6.2 step (2) should be removed, and the exclusion for intrinsic assignment for deallocation-finalization should also be removed? ANSWER: A1. No object should be finalized twice. A2. No, a finalizable allocatable component should not be required to be allocated when its containing object is finalized. The inclusion of allocatable components in 7.5.6.2 step (2) is an error in the standard, and the intrinsic assignment exception for finalization on deallocation is likewise an error. Edits are provided to correct these errors. A3. An allocatable component should be able to be finalized as soon as the object's final subroutine returns, i.e. there should be no requirement on the processor to produce a particular invocation order here. The ambiguity in whether component deallocation and component finalization should be ordered is inadvertent. An edit is provided to remove any implication that these need to have a specific order. FURTHER ELUCIDATION: Finalization ordering is a partial ordering. When final subroutines will be executed for a type (TFIN), an allocated allocatable component thereof (AFIN), an ordinary (viz nonallocatable nonpointer) component thereof (OFIN), and the type's parent type (PFIN), the orderings are: TFIN "All nonallocatable finalizable". {Remove redundant finalization.} [80:22] 7.5.6.3 When finalization occurs, p2, After "unless it is the variable in an intrinsic assignment statement" Delete "or a subobject thereof". {Remove allocatable component exclusion in intrinsic assignment.} [137:28] 9.7.3.2 Deallocation of allocatable variables, p9, Change "that object is finalized" To "any final subroutine for that object is executed", Making the whole paragraph read "If an allocatable component is a subobject of a finalizable object, any final subroutine for that object is executed before the component is automatically deallocated." SUBMITTED BY: Malcolm Cohen HISTORY: 20-117 m221 F18/017 Submitted - Passed by J3 meeting 20-nnn m222 Passed as amended by J3 letter ballot ---------------------------------------------------------------------- ---------------------------------------------------------------------- NUMBER: F18/018 TITLE: Public namelist and private variable KEYWORDS: NAMELIST PUBLIC PRIVATE DEFECT TYPE: Clarification STATUS: Passed by J3 letter ballot QUESTION: Consider Module m1 Real,Public :: x End Module Module m2 Use m1 Private x Namelist/nml/x End Module On the face of it, module M2 appears to violate C8105 (R868) A namelist-group-object shall not have the PRIVATE attribute if the namelist-group-name has the PUBLIC attribute. as the local X indeed has the PRIVATE attribute. On the other hand, it is just a local name for the remote X which is PUBLIC, which raises doubts. Comment: This seems to be a very old constraint dating back to when the standard was much more restrictive about such things. It is not clear why this should be disallowed. Even if X were a local variable of M2, it is not clear what purpose this constraint serves. A quick compiler survey revealed that most but not all compilers think that it is where the variable is defined that matters, i.e. many accept the example code. Q1. Should PRIVATE local variables really be prohibited from a PUBLIC namelist? If the answer to Q1 is yes, Q2. Is it PRIVATE on the local name that matters, or PRIVATE on the variable where it is defined? COMMENT: A NAMELIST statement can contain several namelist-group-names, so it is also somewhat ambiguous as to which namelist-group-objects this constraint applies to. ANSWER: A1. Yes. Although it would be reasonable to lift this restriction in a future standard, it is a deliberate restriction in this standard. A2. It is whether the local name has the PRIVATE attribute that matters, not where the variable is declared. An edit is provided. EDIT to 18-007r1: [119:8-9] 8.9 NAMELIST statement, C8105, After "PRIVATE attribute" insert "in the local scope", and change "the namelist-group-name" to "its namelist-group-name", making the whole constraint read "C8105 (R868) A namelist-group-object shall not have the PRIVATE attribute in the local scope if its namelist-group-name has the PUBLIC attribute." SUBMITTED BY: Malcolm Cohen HISTORY: 20-127 m221 F18/018 Submitted 20-127r1 m221 Passed by J3 meeting 20-nnn m222 Passed as amended by J3 letter ballot #36 ---------------------------------------------------------------------- ===END===