To: J3 J3/22-192 From: Malcolm Cohen Subject: ASSOCIATED is defective Date: 2022-October-17 1. Introduction The requirements on the TARGET argument of ASSOCIATED are wrong, leading to a contradiction in the standard. This needs to be fixed sometime. Now is our last chance to fix it without going through the interp process. Examples of the defect appear at the end of this paper. 2. The defect The basic requirement on TARGET is that it "shall be allowable as the data-target or proc-target in a pointer assignment statement (10.2.2) in which POINTER is data-pointer- object or proc-pointer-object". This is both too loose and too strict. The "too loose" part is that with rank-remapping pointer assignment, it permits POINTER and TARGET to have different rank. As the result of the function ASSOCIATED is unambiguously .FALSE. when the shapes of POINTER and TARGET differ, this will always be .FALSE. (the shapes not even having the same number of elements cannot be the same), and is thus useless. (Or worse: permitting this can mislead the user into thinking that he might get the answer .TRUE., and this cannot be the case.) Aside: ASSOCIATED has always been a much stricter test than mere address comparison. Even in Fortran 90, it was trivial to end up with two pointers to the same memory locations in the same order, but with different shape, resulting in the answer .FALSE.. The "too strict" part comes because one could previously use ASSOCIATED with the POINTER argument being a pointer that cannot appear as the pointer-object in a pointer assignment statement. In this case, there is no possible statement for TARGET to satisfy. Examples include POINTER being INTENT(IN), PROTECTED (outside of its module), a reference to a pointer- valued function, or an assumed-rank pointer. 3. Historical background The requirements on TARGET were correct in Fortran 90 and 95. In Fortran 2003, procedure pointers were added (necessitating a change to the requirements), and rank-remapping pointer assignment was added. In the course of developing Fortran 2003, it was observed that the requirements on the TARGET argument of ASSOCIATED were very similar to the requirements on the target in a pointer assignment, and as a simplification the words were changed to the current wording. The paper that did this also mentioned rank remapping, apparently thinking that it was desirable that this be addressed by ASSOCIATED, and forgetting that the shape equality condition would make that worse than useless. 4. Recommended solution Reword it to be "how we intended" (i.e. retain backwards compatibility, and do the obviously-right thing for new cases). For data pointers that are not assumed-rank, require the rank to be the same. 5. Possible wording strategies (a) Revise the wording to explicitly list all the requirements, like we used to do before. This will be fairly long. (b) Revise the wording so that instead of a pointer assignment statement for POINTER, it is one for a modifiable pointer with the same characteristics or attributes (except for intent and accessibility). Because there is no directly modifiable assumed-rank pointer, it is hard to see how the second part could be worded. We could use the weasel-wording for procedure pointers though (there being no functions that return assumed-rank pointers), and explicitly list the requirements for data pointers. 6. Edits to N2209 [361] 16.9.20 ASSOCIATED, Arguments paragraph, TARGET argument, replace entire description with that below. It is unusual for an argument description to have multiple paragraphs, but not unprecedented (e.g. CO_REDUCE, SPLIT, TOKENIZE). Note: the second sentence of the first paragraph is unchanged. "shall be a pointer or an entity that could be a target. If TARGET is a pointer then its pointer association status shall not be undefined. If POINTER is a procedure pointer, TARGET shall be a procedure (or procedure pointer) that would be allowable as the target of a pointer assignment (10.2.2) for a procedure pointer with the same characteristics as POINTER. Otherwise, TARGET shall be a noncoindexed variable that is not an array section with a vector subscript, or a reference to a function that returns a data pointer. If POINTER is not unlimited polymorphic, TARGET shall be type compatible with it, and the corresponding kind type parameters shall be equal. If POINTER is not assumed-rank, TARGET shall have the same rank as POINTER." {We don't have to require the POINTER/TARGET explicitly, as that is covered by "shall be a pointer or an entity that could be a target".} {In the procedure pointer para, "(or procedure pointer)" is parenthesised because a procedure pointer is a procedure; i.e. those words could be deleted.} {I don't think any edit is needed to the compatibility subclause, as this is correcting a contradiction.} ALTERNATIVE WORDING FOR THE PROCEDURE POINTER CASE. "If POINTER is a procedure pointer, TARGET shall be a named procedure, a procedure pointer component, or a reference to a function whose result is a procedure pointer. TARGET shall not be a nonintrinsic elemental procedure. If POINTER has an explicit interface, TARGET shall have the same characteristics as POINTER, except that TARGET may be pure or simple even if POINTER is not pure or simple, and may be an elemental intrinsic procedure even though POINTER cannot be elemental. If the characteristics of POINTER or TARGET require an explicit interface, both POINTER and TARGET shall have an explicit interface. If POINTER has an implicit interface and is explicitly typed or referenced as a function, TARGET shall be a function with the same type and type parameters. If POINTER has an implicit interface and is referenced as a subroutine, TARGET shall be a subroutine." 7. Examples 7.1 Fortran 90 demonstrating shape difference Module example_1 Real,Pointer :: p1(:,:), p2(:,:) End Module Subroutine set1 Use example_1 Common/c/target(2,3) Save /c/ Target target p1 => target End Subroutine Subroutine set2 Use example_1 Common/c/target(3,2) Save /c/ Target target p2 => target End Subroutine Program test Use example_1 Common/c/x(6) x = [ 1,2,3,4,5,6 ] Call set1 Call set2 Print *,Associated(p1,p2) ! Prints "F" because the shapes differ. Print *,All([p1]==[p2]) ! Prints "T" because same values in array ! element order. End Program 7.2 Valid Fortran 90/95, invalid F2003+ Program example2 Real,Target :: x(6) Real,Pointer :: p(:) p => x Call test(p) Contains Subroutine test(q) Real,Pointer,Intent(In) :: q(:) Print *,Associated(q,x) ! Valid F90/95, but not allowed in F2003+, ! as the pointer assignment q => x is invalid. End Subroutine End Program 7.3 Invalid Fortran 90/95, possibly valid F2003+ Program example3 Real,Target :: x(6) Real,Pointer :: p(:,:) p(1:2,1:3) => x Print *,Associated(p,x) ! Wrong rank, so invalid F90/95... ! ... but the pointer assignment is valid, so valid F2003+? ! ... it can only print "F" if it is valid. End Program 7.4 Invalid for assumed-rank even though it is allowed in ASSOCIATE Program example4 Real,Target :: x(6) Real,Pointer :: p(:) p => x Call test(p) Contains Subroutine test(q) Real,Pointer :: q(..) ! Assumed-rank Print *,Associated(q) ! Valid, prints "T". Print *,Associated(q,x) ! We would expect this to work too, ! but there are no pointer assignments q=>x with or without ! rank remapping. End Subroutine End Program ===END===