To: J3 J3/21-184 From: Malcolm Cohen Subject: Results of the J3 Fortran interp letter ballot #37 Date: 2021-October-16 Here are the results of J3 letter ballot #37 on Fortran interpretations that officially closed 07-October-2021. The ballot is in J3 paper 21-173 for meeting #225. If I have transcribed a vote or a comment incorrectly, please let me know. Voter / interp F18 F18 F18 F18 F18 F18 F18 F18 F18 F18 F18 F18 F18 007 015 019 023 024 025 026 027 028 029 030 031 032 Richard Bleikamp Y Y Y Y Y Y Y Y Y Y Y Y Y Reuben D. Budiardja Y Y Y Y Y Y Y Y Y Y Y Y Y Ondrej Certik Y Y Y Y Y Y Y Y Y Y Y Y Y Daniel Chen C Y Y Y Y Y Y N Y Y Y Y Y Thomas L. Clune Y Y Y Y Y Y Y Y Y Y Y Y Y Robert Corbett C Y Y Y Y N Y Y Y Y Y Y Y Brian Friesen Y Y Y Y Y Y Y Y Y Y Y Y Y Gary Klimowicz Y Y Y Y Y Y Y Y Y Y Y Y Y Mark LeAir Y Y Y Y Y N Y Y Y Y Y Y Y Steve Lionel Y Y Y Y Y Y Y Y Y Y Y Y Y Lorri Menard Y Y Y Y Y Y Y Y Y Y Y Y Y John Reid Y Y Y Y Y Y Y Y Y Y Y N Y Brad Richardson Y Y Y Y Y Y Y Y Y Y Y Y Y Van Snyder y - n y y y y - y - - - - Jon Steidel y y y y y y y y y y y y y LB #37 Result Y Y A Y Y N Y Y Y Y Y N 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. (*) John Reid is an alternate for Siddhartha Ghosh. Not Voting Bill Long (alternate Anton Shterenlikht) Craig Rasmussen Srinath Vadlamani (alternates Nathan Sircombe and Kiran Chandramohan) 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/007 Daniel Chen's comment on F18/007 I can't see the point of the new constraint why the argument of C_FUNLOC must be pure if C_FUNLOC is referenced in a pure subprogram. I understand if the impure result of C_FUNLOC itself is called, it will violate the rules, but just referencing C_FUNLOC seems OK. Moreover, since C_F_PROCPOINTER is no longer a pure routine, it seems it is even less possible that the result of C_FUNLOC can be referenced in a pure subprogram. I understand it probably makes referencing a C_FUNLOC with an impure argument in a pure subprogram pointless, but it still doesn't seem break anything either. Robert Corbett's comment on F18/007 I agree with Daniel that C_FUNLOC can be PURE without causing a problem. I also agree that making C_FUNLOC impure loses almost no functionality. Result for F18/007 /interp notes that should a pure procedure be implemented in C, there is no call to C_F_PROCPOINTER needed before referencing the procedure. It would be a disservice to our users to silently permit passing an impure procedure pointer in this way. /interp further notes that it is not clear whether a pure procedure may be implemented in C; it is expected that an interp on this will be forthcoming. Interp F18/007 passes as is. F18/019 Van Snyder's NO vote on F18/019 Default initialization to NULL() should be allowed. Default initialization of procedure pointer components to NULL() or pure procedures should be allowed. With those changes, my vote would be Yes. Result for F18/019 /interp notes that default initialization to NULL() is permitted by the edits in this interp - only initialization to a target will be prohibited. /interp further notes that a procedure pointer component that is pure can only be initialized to point to a pure procedure, and a procedure pointer component that is not pure cannot be invoked. That is, it would seem to be safe to permit procedure pointer component initializations. /interp finally notes that the entire discussion around F18/019 was only about data pointers - no one mentioned procedure pointers. Therefore, in the edit for F18/019, change "initialization of a pointer component" to "initialization of a data pointer component". F18/019 passes as amended. F18/025 Robert Corbett's NO vote on F18/025 The proposed fix is an example of bad language design. It has the potential to needlessly break existing standard conforming codes. Many better fixes are possible. A simple fix is to ban type names of sequence types and BIND types that contain non-null data pointer initializations from appearing in pure code. Mark LeAir's NO vote on F18/025 I feel allowing this will unnecessarily complicate the implementation of comparing two derived types. Result for F18/025 /interp notes that the text of F18/025 claims that the standard does not state explicitly or imply that default initialization is not an attribute. Ambiguity in the standard means that the allegedly conforming codes are not in fact conforming, /interp notes that treating two types as equivalent when they behave quite differently is the epitome of bad language design. Treating types that behave differently as different types is good design. /interp notes that the intent, as deducible from the fact that mere spelling differences in the name of a component make the types into different types, is that types really have to behave identically in all contexts to be considered equivalent. /interp further notes that the proposed "simple fix" only addresses one of the concerns expressed in F18/025. /interp agrees that checking default initialisation in type comparison requires the compiler to do work. Given the difference in behaviour, this work is justified. However, /interp also notes that the proposed edit is not clear whether it is the value, or the expression itself, that is important (e.g. is "=4" the same default initialiser as "=2+2"). This should be clarified. F18/025 FAILS. F18/027 Daniel Chen's NO vote on F18/027 This requires deallocation and reallocation on top of assignment to every nested allocatable components. It is not going to have a good performance as it is intended to do. I think we need a bit more discussion on this one. Result for F18/027 /interp notes that this is the exact same situation that applies to all assignment with allocatable components since Fortran 2003. The argument now, as then, was that although in principle the user can do a pre- processing phase to align the allocation status and shape of all allocatable components, this is tedious and error-prone, and highly likely to perform worse than auto-reallocation. /interp further notes that this is not a new issue, as it was debated at some length during the meeting that passed the interp. F18/027 passes unchanged. F18/031 John Reid's NO vote on F18/031 The rules for intrinsic assignment in 10.2.1.2 of 18-007r1 include [160:6-7] "In an intrinsic assignment statement, (1) if the variable is polymorphic it shall be allocatable and ..." so I see disallowing polymorphic A in CO_BROADCAST as overkill. I suggest adding the sentence "If it is polymorphic it shall be allocatable." Result for F18/031 /interp notes that the proposed change would be similar in effect to the previously-rejected ALTERNATIVE answer in 21-151, the main change being the requirement of ALLOCATABLE). /interp further notes that the whole item (1) is only partially quoted "if the variable is polymorphic it shall be allocatable and not a coarray" and that therefore the corresponding requirement on A (which would otherwise be permitted to be a coarray) would be "If it is polymorphic it shall be allocatable and not a coarray." /interp further noted that it seemed strange to require ALLOCATABLE but to effectively forbid reallocation. John further suggested adding ", including (re)allocation of itself and any allocatable ultimate component, and setting its dynamic type and the dynamic type of any polymorphic allocatable ultimate component". However, there is still no reallocation of the variable, because of the requirement (which is not present for intrinsic assignment) that the dynamic type and type parameters be the same on all images. That requirement is not necessary for ALLOCATABLE that is being handled by the receiving image. Apparently, more discussion is required. F18/031 FAILS. ---------------------------------------------------------------------- NUMBER: F18/007 TITLE: Problems with C_FUNLOC and C_F_PROCPOINTER being PURE KEYWORDS: C_FUNLOC, C_F_PROCPOINTER, ISO_C_BINDING DEFECT TYPE: Erratum STATUS: Passed by J3 letter ballot QUESTIONS: 1) Regarding C_FUNLOC (X), In 15.7 Pure procedures, constraint C1590 is: "C1590 The specification-part of a pure subprogram shall specify that all its dummy procedures are pure." In 15.5.2.9 Actual arguments associated with dummy procedure entities, the first paragraph says "If the interface of a dummy procedure is explicit, its characteristics as a procedure (15.3.1) shall be the same as those of its effective argument, except that a pure effective argument may be associated with a dummy argument that is not pure and an elemental intrinsic actual procedure may be associated with a dummy procedure (which cannot be elemental)." If C_FUNLOC is PURE, then these together imply that the actual argument, X, has to be a PURE procedure. This is not stated in the specification of this function in 18.2.3.5. This has the effect of limiting the uses of C_FUNLOC compared to the specification in Fortran 2008. This is not indicated in 4.3.3 Fortran 2008 compatibility. Was this an intentional change, or was making C_FUNLOC PURE a mistake? 2) Regarding C_F_PROCPOINTER (CPTR, FPTR), a similar argument to that above implies that the INTENT(OUT) procedure pointer, FPTR, is a PURE procedure. However, there is no stated requirement that the input argument CPTR be PURE, and indeed there is no specification of what that even means if CPTR is a pointer to an interoperable C function. This suggests that C_F_PROCPOINTER provides a backdoor allowing an impure procedure to appear to be pure, invalidating the assumptions that are associated with a pure procedure. Was making C_F_PROCPOINTER PURE a mistake? ANSWER: 1) It was not an error to make C_FUNLOC pure in principle. But if a reference to C_FUNLOC appears in a pure procedure, its argument should have been required to be pure. It is noted that constraint C1590 does not apply to C_FUNLOC as it is a procedure from an intrinsic module, and as such is not defined by a subprogram. The only question is whether its argument is required to be pure, and in what circumstances. 2) Making C_F_PROCPOINTER pure was a mistake. Edits are included to correct these errors. EDITS to 18-007r1: [325:8+] In 15.7 Pure Procedures, following constraint C1599, add a new constraint: "C1599a A reference to the function C_FUNLOC from the intrinsic module ISO_C_BINDING shall not appear in a pure subprogram if its argument is impure." [469:26-27] In 18.2.3 Procedures in the module, 18.2.3.1 General, second sentence, change "C_F_POINTER subroutine is" to "C_F_POINTER and C_F_PROCPOINTER subroutines are". Making the whole sentence read "The C_F_POINTER and C_F_PROCPOINTER subroutines are impure; all other procedures in the module are pure." [472:16] In 18.2.3.4 C_F_PROCPOINTER (CPTR, FPTR), Class paragraph, Change "Pure subroutine" to "Subroutine". SUBMITTED BY: Bill Long HISTORY: 19-114 m218 Submitted 19-114r1 m218 Revised draft 19-114r2 m218 Passed as amended by J3 meeting 19-228 m220 Failed J3 letter ballot #35 21-124 m223 Repair edits to satisfy objections raised in letter ballot, passed by J3 meeting 223, 11-2. 21-nnn m225 Passed by J3 letter ballot #37 ---------------------------------------------------------------------- ---------------------------------------------------------------------- NUMBER: F18/015 TITLE: Example in C.6.8 is wrong KEYWORDS: failed images DEFECT TYPE: Erratum STATUS: Passed by J3 letter ballot The example code for failed images in C.6.8 raises several issues about its correctness. QUESTION: Q1. A: In the example in C.6.8, the assignments me[k] = failures(i) id[k] = 1 are made by image 1 and the assignments me = THIS_IMAGE () id = MERGE (1, 2, me<=images_used) are made by image k in unordered segments. Was this intended? B: In the example in C.6.8, the assignment me[k] = failures(i) is made by image 1 and me[k] is referenced on other images in the FORM TEAM statement in unordered segments. Was this intended? Q2. Suppose the program in C.6.8 is executed by 11 images, so 1 is intended to be a spare. If image 9 in the initial team fails immediately before it executes the first FORM TEAM statement, then image 10 in the initial team, which executes FORM TEAM with a team-number == 1 and NEW_INDEX == 10 (== me), will have specified a NEW_INDEX= value greater than the number of images in the new team. Should there be a test for this in the code? Q3. A: If a replacement image has failed, its image index will be the value of an element of the array failures, a replacement for it will be found, and the replacement will be placed in team 1. Was this intended? B: The value of images_used increases each time the setup loop is executed. However, the array failures will contain the image indices of all the failed images and allocate all of them fresh replacements. Was this intended? Q4. The variable images_used is incremented only on image 1 but is referenced by other images near the beginning and end of DO setup. Was this intended? Q5. The intention is that on each cycle of the DO iter loop, a calculation is performed on the worker images and if any of them fail during this, the calculation is resumed from a checkpoint with the failed images replaced by spares. On resumption, the variable read_checkpoint has the value true on all the old worker images to indicate that they should access the checkpoint data. On a replacement image, this variable will still have its initial value of false. Was this intended? Q6. The code for choosing the number of spares does not correspond to the comment for it. Was this intended? ANSWER: 1-A: No. An image control statement that provides segment ordering is needed. 1-B: No. 2: This is quite a low-probability event, so exiting with the error condition seems appropriate. 3-A: No. 3_B: No. It was intended to allocate replacements only for the newly failed images. Furthermore, the example contains more errors than in the list above. Therefore an edit is provided that replaces the entire example with a complete rewrite, involving correction of additional errors, a better choice of names, and more comments. 4: No. The problem near the end of DO setup may be avoided by replacing the statement IF (THIS_IMAGE () > images_used) done = done[1] by IF (team_number == 2) done = done[1] The problem near the beginning of DO setup may be avoided by making the variable images_used a coarray and referencing images_used[1]. This will need the addition of a SYNC ALL statement just before the statement outer : DO to ensure that the correct value is used on all images on the first iteration of the loop. 5. No. The variable read_checkpoint is not needed and should be removed. The initial entry is just the special case of the checkpoint data being null so that the calculation needs to be started. 6. No. In the line images_spare = MAX(NUM_IMAGES()/100,0,MIN(NUM_IMAGES()-10,1)) "10" should be "9". Some of the noteworthy additional changes are: - declarations separated out and many comments added or changed; - logical variable START added to distinguish the first execution of the outer do loop when READ_CHECKPOINT should be false; - rename ME to LOCAL_INDEX and ID to TEAM_NUMBER; - code added to calculate the local indices of team 2; - THEN keyword added to ELSE IF (done) statement. EDITS to 18-007r1: [543:42-545:17] C.6.8 Example involving failed images, Replace the entire example with the code below. Note that many lines and comments are broken to keep them within 70 columns, these should be joined up or reformatted in the actual standard. " PROGRAM possibly_recoverable_simulation USE, INTRINSIC :: ISO_FORTRAN_ENV, ONLY:TEAM_TYPE, STAT_FAILED_IMAGE IMPLICIT NONE INTEGER, ALLOCATABLE :: failures (:) ! Indices of the failed images. INTEGER, ALLOCATABLE :: old_failures(:) ! Previous failures. INTEGER, ALLOCATABLE :: map(:) ! For each spare image k in use, ! map(k) holds the index of the failed image it replaces. INTEGER :: images_spare ! No. spare images. ! Not altered in main loop. INTEGER :: images_used [*] ! On image 1, max index of image in use. INTEGER :: failed ! Index of a failed image. INTEGER :: i, j, k ! Temporaries INTEGER :: status ! stat= value INTEGER :: team_number [*] ! 1 if in working team; 2 otherwise. INTEGER :: local_index [*] ! Index of the image in the team. TYPE (TEAM_TYPE) :: simulation_team LOGICAL :: done [*] ! True if computation finished on the image. ! Keep 1% spare images if we have a lot, just 1 if 10-199 images, ! 0 if <10. images_spare = MAX(NUM_IMAGES()/100,0,MIN(NUM_IMAGES()-9,1)) images_used = NUM_IMAGES () - images_spare ALLOCATE ( old_failures(0), map(images_used+1:NUM_IMAGES()) ) SYNC ALL (STAT=status) outer : DO local_index = THIS_IMAGE () team_number = MERGE (1, 2, local_index<=images_used[1]) SYNC ALL (STAT = status) IF (status/=0 .AND. status/=STAT_FAILED_IMAGE) EXIT outer IF (IMAGE_STATUS (1) == STAT_FAILED_IMAGE) & ERROR STOP "cannot recover" IF (THIS_IMAGE () == 1) THEN ! For each newly failed image in team 1, move into team 1 a ! non-failed image of team 2. failures = FAILED_IMAGES () ! Note that the values ! returned by FAILED_IMAGES increase monotonically. k = images_used j = 1 DO i = 1, SIZE (failures) IF (failures(i) > 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 (status, done) ! The simulation_procedure: ! - sets up and performs some part of the simulation; ! - starts from checkpoint data if these are available; ! - stores checkpoint data for all images from time to ! - time and always before return; ! - sets status from its internal synchronizations; ! - sets done to .TRUE. when the simulation has completed. IF (status == STAT_FAILED_IMAGE) THEN EXIT simulation ELSE IF (done) THEN EXIT iter END IF END DO iter END IF END TEAM (STAT=status) simulation SYNC ALL (STAT=status) IF (team_number == 2) 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-132 m222 Passed as amended by J3 letter ballot #36 N2178 n/a Failed WG5 letter ballot N2176. 21-105 m223 Revised answer 21-105r1 m223 Further revised, Passed by J3 meeting 223. 21-nnn m225 Passed by J3 letter ballot #37 ---------------------------------------------------------------------- ---------------------------------------------------------------------- NUMBER: F18/019 TITLE: PURE and default initialization DEFECT TYPE: Erratum STATUS: Passed by J3 letter ballot QUESTION: An essential property of pure procedures is that they do not modify the values of nonlocal variables except through dummy arguments. The addition of default initialization of pointer components makes it possible to violate this property. Because default initialization does not imply the SAVE attribute, a local variable of derived type in a pure procedure can include a pointer component whose target is a nonlocal variable. The definition of pure procedures in subclause 15.7 allows a program to modify the value of a nonlocal variable through such a component. For example, PROGRAM EXAMPLE1 REAL, TARGET :: X = 1.0 TYPE T REAL, POINTER :: P => X END TYPE T CALL SUBR PRINT *, X ! X has been changed to 2.0 CONTAINS PURE SUBROUTINE SUBR TYPE(T) Y Y%P = 2.0 END SUBROUTINE SUBR END A local variable is not needed, for example, PROGRAM example2 REAL,TARGET :: x = 123 TYPE t REAL,POINTER :: p => x END TYPE CALL sub PRINT *,x ! No longer == 123? CONTAINS PURE SUBROUTINE sub() ASSOCIATE(y=>t()) y%p = -999 ! Affects x. END ASSOCIATE END SUBROUTINE END PROGRAM A polymorphic variable can be used, for example, PROGRAM example2 REAL,TARGET :: x = 123 TYPE t END TYPE TYPE,EXTENDS(t0) :: t REAL,POINTER :: p => x END TYPE CALL sub PRINT *,x ! No longer == 123? CONTAINS PURE SUBROUTINE sub() CLASS(t0) y ! Declared type has no initialized ptr comp. ALLOCATE(t::y) ! Without SOURCE=, gets a pointer to x. SELECT TYPE(y) TYPE IS (t) y%p = -999 ! Affects x. END SELECT END SUBROUTINE END PROGRAM ALLOCATE with MOLD= instead of a type-spec can do the same. If component initialization is not an attribute of the component, more convoluted examples are possible using SEQUENCE types so that the local variable does not have default initialization but can be initialized using a compatible type that does. Q. Was it intended to allow nonlocal variables to be modified by a pure procedure in this way? ANSWER: A: No. An edit is supplied to correct the standard. Note: The question of whether component initialization is an attribute should be addressed by a separate interpretation request. EDIT to 18-007r1: [324:20-] 15.7 Pure procedures, between NOTE 1 and C1590, insert new constraint "C1589a A named local entity or construct entity of a pure subprogram shall not be of a type that has default initialization of a data pointer component to a target at any level of component selection." {With no local or construct entity designator of a "bad" type being allowed, one cannot write a pointer component reference to it. This is stricter than strictly necessary, as it effectively forbids such types from any usage within pure, even unproblematic usage.} SUBMITTED BY: Robert Corbett HISTORY: 20-151 m222 Submitted 21-123 m223 Revised with answer 21-123r1 m223 Passed by J3 meeting 223. 21-nnn m225 Passed as amended by J3 letter ballot #37 ---------------------------------------------------------------------- ---------------------------------------------------------------------- NUMBER: F18/023 TITLE: CLASS(*) ambiguous operator overloading KEYWORDS: CLASS(*) generic OPERATOR DEFECT TYPE: Erratum STATUS: Passed by J3 letter ballot QUESTION: Consider the program Module m Interface Operator(==) Module Procedure mp End Interface Contains Logical Function mp(a,b) Class(*),Intent(In) :: a,b mp = .False. Select Type(a) Type Is (Integer) Select Type(b) Type Is (Integer) mp = .True. End Select End Select End Function End Module Program ambiguous Use m If (13==999) Then Print *,'Invoked the user function' Else Print *,'Did not invoke the user function' End If End Program Is this program valid? If so, does it invoke the user function or the intrinsic operation? It is clear from the standard that the user is not supposed to be able to override intrinsic operators, merely extend them. The last sentence of 15.4.3.4.2p1 "Defined operations" says: "If the operator is an intrinsic-operator (R608), the number of dummy arguments shall be consistent with the intrinsic uses of that operator, and the types, kind type parameters, or ranks of the dummy arguments shall differ from those required for the intrinsic operation (10.1.5)." However, CLASS(*) encompasses these while "differing". ANSWER: The program is not conforming because it is ambiguous. However, the interface was intended to be forbidden; as noted, the standard clearly intended to prohibit overriding intrinsic operations. An edit is provided to correct this oversight. EDITS to 18-007r1: [295:11] 15.4.3.4.2 Defined operations, p1, last sentence, After "(10.1.5)" insert ", treating a CLASS(*) dummy argument as not differing in type or kind". {A bit ugly, but we can't use "distinguishable" because operations have operands not arguments." SUBMITTED BY: Paul Richard Thomas HISTORY: 21-113 m223 Submitted, passed by J3 meeting 223. 21-nnn m225 Passed by J3 letter ballot #37 ---------------------------------------------------------------------- ---------------------------------------------------------------------- NUMBER: F18/024 TITLE: CFI_setpointer with result a deferred length character KEYWORDS: C interoperability DEFECT TYPE: Erratum STATUS: Passed by J3 letter ballot QUESTION: Is the requirement in CFI_setpointer that the elem_lem member have the same value in the source and result arguments intended to apply if the result is of type CHARACTER with the length parameter deferred? ANSWER: No. It is an oversight in the standard that this rule apply to the case of result being of type CHARACTER and having the length parameter deferred. Currently in section 18.5.5.9 "The CFI_setpointer function" states in para 2 that "If source is not a null pointer, the corresponding values of the elem_len, rank, and type members shall be the same in the C descriptors with the addresses source and result." The function can therefore not work correctly if the "result" parameter is a descriptor address for a deferred-length character entity coming in from Fortran, because the elem_len value is not available. Manual updates to result->elem_len are prohibited by 18.6 para 1. The CFI_setpointer function in the intrinsic module ISO_C_BINDING is intended to provide a means for C programmers to replicate the pointer association capability in Fortran, for dummy arguments in interfaces with with interoperable interfaces. Thus, for the case of a character result having deferred length, which is allowed at [478:21], the correct action should be for the elem_len value from the source to be copied to the same member of result as part of execution of the function. Edits are supplied to correct this defect. EDITS to 18-007r1: In 18.5.5.9 The CFI_setpointer function - [491:27] In the description of the source formal parameter, second sentence, delete "elem_len, ". - [491:28+] In the description of the source formal parameter, after the second sentence add new sentence: "If source is not a null pointer and the C descriptor with the address result does not describe a deferred length character pointer, the corresponding values of the elem_len member shall be the same in the C descriptors with the addresses source and result." - [491:31] In the first sentence of paragraph 3, "Description" replace "base_addr and dim" by "base_addr, dim and possibly elem_len". - [491:38] At the end of the second bullet point of paragraph 3, "Description", add new sentence; "If the C descriptor with the address result describes a character pointer of deferred length, the value of its elem_len member is set to source->elem_len". SUBMITTED BY: Reinhold Bader HISTORY: 21-102r1 m223 Submitted 21-102r3 m223 Passed by J3 meeting 223. 21-nnn m225 Passed by J3 letter ballot #37 ---------------------------------------------------------------------- ---------------------------------------------------------------------- NUMBER: F18/025 TITLE: Is component initialization an attribute? KEYWORDS: Component initialization, SEQUENCE, Generic DEFECT TYPE: Erratum STATUS: J3 consideration in progress 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: 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 any default initialization)". {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-nnn m225 Failed J3 letter ballot #37 ---------------------------------------------------------------------- ---------------------------------------------------------------------- NUMBER: F18/026 TITLE: C_SIZEOF argument DEFECT TYPE: Erratum STATUS: Passed by J3 letter ballot QUESTION: Consider the example SUBROUTINE test(b) USE iso_c_binding REAL(c_double) b(:),a(SIZE(b)) PRINT *,c_sizeof(a) ! A PRINT *,c_sizeof(b) ! B PRINT *,c_sizeof(a(::2)) ! C PRINT *,c_sizeof(a+1) ! D PRINT *,c_sizeof(1.0_c_double) ! E END SUBROUTINE 18.2.3.7 C_SIZEOF (X) states "X shall be an interoperable data entity..." According to that, the reference to C_SIZEOF marked A is valid, as A is interoperable (an explicit-shape array of interoperable type and type parameters). And the reference marked B is invalid, as only explicit-shape arrays and assumed-size arrays are interoperable, thus assumed-shape arrays are definitely not. For the references at C and D, the standard seems to be silent on the matter of whether they are interoperable. It is clear for named variables, but although subobject designators can denote variables, they are not names, and expressions are not variables at all. Being silent implies non-conformance as no interpretation is established. The reference at E also appears to be non-conforming, as the standard specifies no criteria for interoperability of expressions. However, the description of the result of C_SIZEOF only makes use of the interoperability of the type and type parameters. Are these references intended to be conforming? If not, should the standard be clarified to say that X shall be an interoperable named variable? ANSWER: Yes, these references were all intended to be conforming. An edit is supplied to correct this mistake. EDIT to 18-007r1: [473:27] 18.2.3.7 C_SIZEOF (X), p3 Argument, Change "an interoperable data entity that is not" to "of interoperable type and type parameters, and shall not be", making the whole paragraph read: "Argument. X shall be of interoperable type and type parameters, and shall not be an assumed-size array or an assumed-rank array that is associated with an assumed-size array." {Loosen the requirements.} SUBMITTED BY: Malcolm Cohen HISTORY: 21-134 m224 Submitted 21-134r1 m224 Revised 21-134r2 m224 Revised again, passed by J3 meeting 224. 21-nnn m225 Passed by J3 letter ballot #37 ---------------------------------------------------------------------- ---------------------------------------------------------------------- NUMBER: F18/027 TITLE: CO_BROADCAST with allocatable component KEYWORDS: CO_BROADCAST allocatable component DEFECT TYPE: Erratum STATUS: Passed by J3 letter ballot QUESTION: Consider the program program example type :: my_string_t character(len=:), allocatable :: contents end type type(my_string_t) :: string if (this_image() == 1) string%contents = "Hello, World!" call co_broadcast(string, source_image=1) print *, string%contents end program Is this program valid? If so, what is the status of string%contents on images other than 1? The description for argument A in the standard (Section 16.9.46) states that A: "shall have the same shape, dynamic type, and type parameter value, in corresponding references." and given the example that follows, would indicate that allocatable array arguments must be allocated to the same shape on all images prior to the call to CO_BROADCAST. However, it also states that A: "becomes defined, as if by intrinsic assignment, on all images" which would indicate that objects with allocatable components would have those components (re)allocated. Is it intended for CO_BROADCAST to be usable by objects with allocatable components, and have those components be (re)allocated on the receiving images? Furthermore, can those components be polymorphic, (i.e. be declared with CLASS instead of TYPE)? ANSWER: The program is conforming because argument A satisfies the requirements: "shall have the same shape, dynamic type, and type parameter value, in corresponding references." and string%contents should be allocated with value "Hello, World!" because string shall: "becomes defined, as if by intrinsic assignment, on all images" EDIT to 18-007r1: [355:22] 16.9.46 CO_BROADCAST, p3 Arguments, argument A, last sentence At the end of the last sentence add ", including (re)allocation of any allocatable ultimate component, and setting the dynamic type of any polymorphic allocatable ultimate component". Somewhat redundant because "as if by intrinsic assignment" should already indicate it, but clearly the clarification is needed, as some compilers have not interpreted it as such. SUBMITTED BY: Brad Richardson HISTORY: 21-139 m224 Submitted 21-139r1 m224 Removed alternate answer, repaired edit, passed by J3 meeting 224, 8-5. 21-nnn m225 Passed by J3 letter ballot #37 ---------------------------------------------------------------------- ---------------------------------------------------------------------- NUMBER: F18/028 TITLE: Specification inquiry DEFECT TYPE: Erratum STATUS: Passed by J3 letter ballot QUESTION: Consider the following program: implicit type (t) (a-z) integer,parameter :: n = storage_size(x) type t character(len=n) :: s end type t print *, n end Two compilers tested issue a compile time error message while a third compiler compiled the program and printed "0" when executed. Is the use of storage_size(x) a valid specification expression in this program? DISCUSSION: In the above program, x is implicitly typed to be type(t). It is used in a specification expression requiring knowledge of type(t), prior to the specification of type(t). There is no text in the standard to prohibit this usage. The rules for specification expressions require the type, type parameters, array bounds, and cobounds of a variable to be known via prior specification, or use or host association when the variable is used in a specification expression. If an element of an array whose value is used in a specification expression, the array must be fully specified in prior declarations. The intent is that specification expressions which are constant ex- pressions can be evaluated when seen. ANSWER: No, the program is not conforming. The use of an implicitly typed var- iable of derived type in a specification inquiry prior to the spec- ification of the derived type was overlooked. An edit is provided to correct this oversight. EDIT to 18-007r1: [158:4] 10.1.11 Specification expression p6 Insert at the end of the paragraph: "If a specification inquiry depends on the type of an object of derived type, that type shall be previously defined." {It is only possible for the type of a variable not to be previously defined if it is typed by the implicit typing rules, but a pointer component can refer a type before its definition.} SUBMITTED BY: Jon Steidel HISTORY: 21-146 m224 Submitted 21-146r1 m224 Revised edit, passed by J3 meeting 224. 21-nnn m225 Passed by J3 letter ballot #37 ---------------------------------------------------------------------- ---------------------------------------------------------------------- NUMBER: F18/029 TITLE: Type of main argument of CO_REDUCE KEYWORDS: CO_REDUCE DEFECT TYPE: Erratum STATUS: Passed by J3 letter ballot QUESTION: The arguments of OPERATION are required to be scalar data objects that are nonallocatable, nonpointer, and nonpolymorphic. Was it intended to allow the type to have components that are allocatable, pointer, or polymorphic? ANSWER: No. The restrictions were imposed to allow an implementation to involve an image copying a scalar value to another image as for intrinsic assignment to a scalar coarray. This would not be possible if the type were to have an ultimate component that is allocatable, a pointer, or polymorphic. It was intended for this to be forbidden. An edit is provided to correct this oversight. Forbidding allocatable and pointer ultimate components is sufficient to forbid polymorphic ultimate components too. EDIT to 18-007r1: [356:42] In 16.9.49 CO_REDUCE, para 3, after first sentence, add "It shall not be of a type with an ultimate component that is allocatable or a pointer". SUBMITTED BY: John Reid HISTORY: 21-137 m224 Submitted 21-137 m224 Passed by J3 meeting 224, 8-6. 21-nnn m225 Passed by J3 letter ballot #37 ---------------------------------------------------------------------- ---------------------------------------------------------------------- NUMBER: F18/030 TITLE: CO_REDUCE/REDUCE OPERATION with coarray argument DEFECT TYPE: Erratum STATUS: Passed by J3 letter ballot QUESTION: Consider the function Pure Real Function f(a,b) Result(r) Real,Intent(In) :: a[*],b[*] r = a[1]*b[1] End Function This function appears to satisfy all the requirements on the OPERATION argument to CO_REDUCE. Q1. Was this intended to be a valid operation for CO_REDUCE? Q2. Was this intended to be a valid operation for REDUCE? ANSWER: A1. No, this was not intended to be valid; the arguments of OPERATION should not have been permitted to be coarrays. A2. Likewise, this was not intended to be valid. Edits are supplied to correct this oversight. EDIT to 18-007r1: [357:9] 16.9.49 CO_REDUCE, p3 Arguments, OPERATION argument, After "nonallocatable," insert "noncoarray,". That makes the first sentence of the argument read: "OPERATION shall be a pure function with exactly two arguments; the result and each argument shall be a scalar, nonallocatable, noncoarray, nonpointer, nonpolymorphic data object with the same type and type parameters as A." {The "noncoarray" requirement is superfluous for the result, but that is not harmful.} [408:36] 16.9.161 REDUCE, p3 Arguments, OPERATION argument, Before "nonpointer," insert "noncoarray,". That makes the first sentence of the argument read: "OPERATION shall be a pure function with exactly two arguments; each argument shall be a scalar, nonallocatable, noncoarray, nonpointer, nonpolymorphic, nonoptional dummy data object with the same type and type parameters as ARRAY." {It is "interesting" that these two very similar requirements are being expressed differently. Perhaps there is a good reason.} SUBMITTED BY: Malcolm Cohen HISTORY: 21-150 m224 Submitted, passed by J3 meeting 224. 21-nnn m225 Passed by J3 letter ballot #37 ---------------------------------------------------------------------- ---------------------------------------------------------------------- NUMBER: F18/031 TITLE: CO_BROADCAST with polymorphic argument DEFECT TYPE: Erratum STATUS: J3 consideration in progress QUESTION: Consider the code fragment Subroutine asgn_for_image(a,b,srcimg) Class(*) a,b Integer,Intent(In) :: srcimg ! The assignment A = B is not allowed, so... If (This_Image()==srcimg) Then Call asgn(b) Else Call asgn(a) End If Contains Subroutine asgn(x) Class(*) x Call co_broadcast(x,Source_Image=srcimg) End Subroutine End Subroutine There is no requirement forbidding the A argument of CO_BROADCAST from being polymorphic, so on the face of it, this appears to get around the prohibition against nonallocatable polymorphic assignment. However, CO_BROADCAST states "A becomes defined, as if by intrinsic assignment" but intrinsic assignment is not defined when the variable is a nonallocatable polymorphic. It can be convincingly argued that the standard therefore does not establish an interpretation, and thus the call to CO_BROADCAST is not valid. Philosophically, it would seem to be strange to allow polymorphic broadcast across images, but not to allow polymorphic assignment of a single variable within an image let alone across images. Is the call to CO_BROADCAST in the example standard-conforming? (And if so, what are the actual semantics?) ANSWER: No, this was not intended to be conforming. An edit is supplied with the missing requirement. EDIT to 18-007r1: [355:20] 16.9.46 CO_BROADCAST, p3 Arguments, argument A, After "It shall not be" Insert "polymorphic or" Making that sentence read "It shall not be polymorphic or a coindexed object." SUBMITTED BY: Malcolm Cohen HISTORY: 21-151 m224 Submitted 21-151r1 m224 Eliminated alternative answer, passed by J3 meeting 224. 21-nnn m225 Failed J3 letter ballot #37 ---------------------------------------------------------------------- ---------------------------------------------------------------------- NUMBER: F18/032 TITLE: CO_BROADCAST and pointer components DEFECT TYPE: Clarification STATUS: Passed by J3 letter ballot QUESTION: Consider the following program fragment: TYPE t CHARACTER(100) name REAL location(3) TYPE(t),POINTER :: antecedent END TYPE TYPE(t) x INTEGER src_image ... CALL co_broadcast(x,src_image) On every image other than src_image itself, this will leave x with its antecedent component having an undefined pointer association status (except when it is disassociated on src_image). This would seem to be not useful and likely to lead to further errors. Was it intended to permit the A argument of CO_BROADCAST to have an ultimate pointer component? ANSWER: Yes, this was intended. Otherwise, individual CO_BROADCAST executions would be required for every other component; this would be very inconvenient. EDIT to 18-007r1: None. SUBMITTED BY: Malcolm Cohen HISTORY: 21-167 m224 Submitted 21-167r1 m224 Selected alternative answer, passed by J3 meeting 224. 21-nnn m225 Passed by J3 letter ballot #37 ----------------------------------------------------------------------