09-292 To: J3 Members From: Stan Whitlock Subject: J3 Fortran interp letter ballot #19 - due 19-Oct-2009 Date: 2009 September 17 Enclosed in the next letter ballot on Fortran interpretations. The rules by which we operate say: o J3 votes on the answer at a J3 meeting; a simple majority vote marks the answer as "passed by J3 meeting". o Between J3 meetings the chair of /interp sends a J3 letter ballot to J3 to approve interp answers that have been "passed by J3 meeting". The letter ballot runs for 30 days. Not voting on three of four consecutive J3 letter ballots is grounds to terminate J3 membership. An interp answer passes by a 2/3rds vote; a no vote must be accompanied by an explanation of the changes necessary to change the member's vote to yes. J3/interp reserves the right to recall an interp answer for more study even if the answer passes. 16 Fortran interpretations are currently "Passed by J3 meeting" after J3 meeting #189. This is the letter ballot phase to go from "Passed by J3 meeting" to "Passed by J3 letter ballot". The following Fortran interpretations are being balloted: Yes No Number Title --- --- F95/0098 Are dummy functions returning assumed-length character legal? --- --- F03/0022 Coexistence of IEEE and non-IEEE kinds --- --- F03/0024 DEALLOCATE and array pointers --- --- F03/0034 IEEE_LOGB() --- --- F03/0039 HYPOT() --- --- F03/0078 IEEE_SUPPORT_DATATYPE vs. mathematical equivalence --- --- F03/0090 Polymorphic array constructors --- --- F03/0130 Elemental specific intrinsic procedure characteristics --- --- F03/0131 SAVE attribute and EQUIVALENCE --- --- F03/0132 Unformatted i/o and private components --- --- F03/0133 Is unlimited polymorphic allowed in COMMON? --- --- F03/0134 Implicit typing of procedure pointers --- --- F03/0135 Interaction between RESULT, recursion, and host generic --- --- F03/0136 Are subroutines distinguishable from arrays? --- --- F03/0137 Dummy procedure type compatibility --- --- F03/0138 External as The text of these interpretations is attached. Each interpretation starts with a row of "-"s. Please mark the above -Y- in the Yes column for "yes", -C- in the Yes column for "yes with comment", or -N- in the No column for a "no" answer {be sure to include your reasons with "no"} and send only the above text {not this entire mail message} with any comments to j3@j3-fortran.org by 11:59:59PM, PDT, Monday, 19-Oct-2009, in order to be counted. Thanks /Stan ---------------------------------------------------------------------- NUMBER: F95/0098 TITLE: Are dummy functions returning assumed-length character legal? KEYWORDS: Dummy function, assumed-length character DEFECT TYPE: Erratum STATUS: Passed by J3 meeting QUESTION: (1) Is a dummy function allowed to have assumed character length? (2) If so, can it be invoked directly from that scoping unit? (3) If so, is this still true if the invoked function itself has a result variable that is assumed-length (this is obsolescent). (4) If an assumed-length function is declared in another scoping unit as a specific length, can it be passed as an actual argument that corresponds to a dummy function of that specific length and be invoked via the dummy function? (5) Clarification request - see discussion - Example 1 does not have any external function with assumed character length, so does it use any obsolescent feature or not? Example 1 (for questions 1 and 2): PROGRAM EX1 CHARACTER F*5 EXTERNAL F CALL S(F) END SUBROUTINE S(D) CHARACTER D*(*) PRINT *,D() END CHARACTER*5 FUNCTION F() F = 'OK' END Example 2 (for question 3): The same as example 1 except for F which is assumed-length, making the whole example 2: PROGRAM EX2 CHARACTER F*5 EXTERNAL F CALL S(F) END SUBROUTINE S(D) CHARACTER D*(*) PRINT *,D() END CHARACTER*(*) FUNCTION F() F = 'OK' END Example 3 (for question 4): The same as example 3 except that S declares the dummy function with a specific length, making it: PROGRAM EX3 CHARACTER F*5 EXTERNAL F CALL S(F) END SUBROUTINE S(D) CHARACTER D*5 PRINT *,D() END CHARACTER*(*) FUNCTON F() F = 'OK' END DISCUSSION: Examples 2 and 3 use the obsolescent feature of "assumed length character for an external function". It seems ambiguous whether example 1 uses an obsolescent feature: by C416 and the text of 4.4.4.1 it would apparently not be obsolescent but by C417 it would appear to be obsolescent. Example 1 does not use any feature described in Annex B, which implies that it is not obsolescent. It would be nice to clarify this. A straightforward reading of the literal words of the standard appears to indicate that example 1 is standard-conforming, but that example 2 is not valid due to it violating item 4 of the list at the end of subclause 4.4.4.1 (page 41). Similarly, example 3 would appear to be invalid by the same rule: this last certainly seems counter-intuitive, but does seem to be what the standard literally says. The basic issue underlying examples 1 and 2 is that the standard says "If used to declare a dummy argument of a procedure, the dummy argument assumes the length of the associated actual argument." It has been argued that this should only apply to dummy variables and not to dummy functions, but that is not what the standard says. ANSWER: (1) Yes, a dummy function is allowed to have assumed length; this is clearly implied by the permission given in C417. (2) Yes, there is no prohibition against invoking such a function. (3) Yes, the actual invoked function may have an assumed-length result. The prohibition against this in item (4) is an error; an edit is supplied to correct this. (4) Yes, this is also valid. The prohibition against this in item (4) is in error; an edit is supplied to correct this. (5) The implication of constraint C417 that a dummy function having assumed length is obsolescent is a typographical error: an edit is provided to correct this. EDITS: [41:11-12] In C417, change "\obs{unless ... dummy function}" to "unless it is of type CHARACTER and is the name of a dummy function \obs{or the name of the result of an external function}". {Note: \obs{...} indicates obsolescent font.} [41:34,36] At the end of 4.4.4.1, item (4), after "invoking the function" insert ", or passing it as an actual argument"; change "host or use" to "argument, host, or use". SUBMITTED BY: Larry Meadows HISTORY: 02-157 m160 F95/0098 submitted 04-417r1 m170 Duplicate of interp #6 05-180 m172 Failed WG5 ballot N1617 - not a duplicate of F95 interp 000006 09-233 m188 Revised answer 09-261 m189 Revised again 09-263 m189 Rewritten and revised to cover more of the issue - Passed by J3 meeting ---------------------------------------------------------------------- NUMBER: F03/0022 TITLE: Coexistence of IEEE and non-IEEE kinds KEYWORDS: IEEE, kind DEFECT TYPE: Erratum STATUS: Passed by J3 meeting QUESTION: Is it allowed for a processor to have one or more real kinds for which there is no IEEE support, while also having real kinds for which there is IEEE support? Much of the IEEE material appears to assume that a processor could simultaneously support both IEEE and non-IEEE kinds. I thought this was the intent. However, the first sentence of the second paragraph in section 14 says that if IEEE_EXCEPTIONS or IEEE_ARITHMETIC is accessible in a scoping unit, then IEEE_OVERFLOW and IEEE_DIVIDE_BY_ZERO are supported in the scoping unit for *ALL* [emphasis mine] kinds of real and complex data. This says to me that if there is any kind of real for which the processor cannot support IEEE_OVERFLOW or IEEE_DIVIDE_BY_ZERO, then pretty much none of the IEEE stuff can be used on that processor at all; there isn't much of the IEEE stuff that can be used without IEEE_ARITHMETIC or IEEE_EXCEPTIONS. This seems draconian and unintended. I speculate that this condition is intended to apply to all IEEE real kinds rather than to all real kinds. ANSWER: Yes, this is allowed. The requirement that IEEE_OVERFLOW and IEEE_DIVIDE_BY_ZERO be supported for all kinds of real and complex data within that scoping unit was unintentional. Support of these two flags means that the exceptions can be detected for real and complex kinds that are IEEE floating point data. The Standard makes no claims about non-IEEE kinds. An edit is provided to clarify this. EDITS: All edits pertain to 04-007. Clause 14 "Exceptions and IEEE arithmetic", 1st sentence of 2nd paragraph [363:9-10] replace "for all kinds of real and complex data" with "for all kinds of real and complex IEEE floating-point data" SUBMITTED BY: Richard Maine HISTORY: 04-419 m170 F03/0022 submitted 04-419r1 m170 Passed by J3 meeting 05-146 m171 Failed J3 letter ballot #10 09-223 m188 Revised answer 09-223r1 m188 Passed by J3 meeting + F2008 fix 09-226 ---------------------------------------------------------------------- NUMBER: F03/0024 TITLE: Pointer deallocation and "whole object" KEYWORDS: DEALLOCATE, POINTER DEFECT TYPE: Erratum STATUS: Passed by J3 meeting QUESTION: 6.3.3.2 paragraph 2 (F03 [116:24-25]) states "If a pointer appears in a DEALLOCATE statement, it shall be associated with the whole of an object that was created by allocation." What does this requirement entail? In particular, which of the following examples conform to this requirement? Q1. REAL,POINTER :: X(:),Y(:) ALLOCATE(X(10)) Y => X(1:10) ! Note that ASSOCIATED(X,Y) is true. DEALLOCATE(Y) Q2. REAL,POINTER :: X(:),Y(:) ALLOCATE(X(10)) Y => X(10:1:-1) ! Note that ASSOCIATED(X,Y) is false because the order differs. DEALLOCATE(Y) Q3. REAL,POINTER :: X(:),Y(:) ALLOCATE(X(0)) Y => X ! Note that ASSOCIATED(X,Y) is false because they are zero-sized. DEALLOCATE(Y) Q4. REAL,POINTER :: X(:),Y(:,:) ALLOCATE(X(100)) Y(1:10,1:10) => X(1:100) ! Note that ASSOCIATED(X,Y) is false because the shapes differ. DEALLOCATE(Y) Q5. REAL,POINTER :: X(:),Y ALLOCATE(X(1)) Y => X(1) ! Note that one is not permitted to ask ASSOCIATED(X,Y). DEALLOCATE(Y) Q6. TYPE T REAL NOTHING(0) REAL A(0) CHARACTER C END TYPE TYPE(T),POINTER :: X CHARACTER,POINTER :: Y ALLOCATE(X) Y => X%C ! Note that one is not permitted to ask ASSOCIATED(X,Y). DEALLOCATE(Y) Q7. TYPE T CHARACTER C END TYPE TYPE,EXTENDS(T) :: XT ! No additional components END TYPE TYPE(XT),POINTER :: X TYPE(T),POINTER :: Y ALLOCATE(X) Y => X%T ! Note that one is not permitted to ask ASSOCIATED(X,Y). DEALLOCATE(Y) ANSWER: In this context, "whole object" requires the type and type parameter values to be the same, and if the object is an array that the elements are the same elements in the same array element order. A scalar is never the "whole" of an array (a processor is permitted to have extra padding between array elements). This gives the answers to the specific questions as follows: Q1 - conforming; Q2 - not conforming (order differs); Q3 - conforming; Q4 - conforming; Q5 - not conforming (scalar vs. array); Q6 - not conforming (type differs); Q7 - not conforming (type differs). An edit is supplied to clarify this intent. EDITS: [116:25] After "by allocation." insert new sentence "The pointer shall have the same dynamic type and type parameters as the allocated object, and if the allocated object is an array the pointer shall be an array whose elements are the same as those of the allocated object in array element order." SUBMITTED BY: Aleksandar Donev HISTORY: 04-378 m170 F03/0024 submitted 04-378r1 m170 Passed by J3 meeting 05-146 m171 Failed J3 letter ballot #10 09-205 m188 Revised answer - passed by J3 meeting + F2008 fix 09-226 ---------------------------------------------------------------------- NUMBER: F03/0034 TITLE: IEEE_LOGB() KEYWORDS: IEEE-754, ieee_logb() DEFECT TYPE: Erratum STATUS: Passed by J3 meeting QUESTION: What is ieee_logb(denormal)? Is it of the hardware representation, or is it as if the hardware had an unbounded exponent range? What is ieee_logb(NaN)? ieee_logb(-INF)? ieee_logb(+INF)? ieee_logb() should be defined as if the hardware representation had an unbounded exponent range. ieee_logb(NaN) should be the same NaN; shall be a NaN. ieee_logb(-INF) shall be +INF ieee_logb(+INF) shall be +INF ANSWER: Case (i) of 14.10.12 correctly specifies that if the value of X is denormal, its unbiased exponent is returned, that IEEE_LOGB(X) is equal to EXPONENT(X)-1. That this conclusion is true is the subject of F2003 interp F03/0054, answered in Corrigendum 1. For consistency with the IEEE International Standard, edits are also supplied for the case where X is infinite and X is NaN. EDITS: Page and line numbers refer to 04-007. Subclause 14.10.12 "IEEE_LOGB (X)" Result value [376:17+] add: "Case (iii) If IEEE_SUPPORT_INF(X) is true and X is infinite, the result is +infinity. Case (iv) If IEEE_SUPPORT_NAN(X) is true and X is a NaN, the result is a NaN." SUBMITTED BY: Fred Tydeman HISTORY: 05-113 m171 F03/0034 submitted 05-113r1 m171 Passed by J3 meeting 05-170 m172 Passed J3 letter ballot #11 N1622 m172 Failed WG5 ballot N1629 09-221 m188 Revised answer 09-221r1 m188 Passed by J3 meeting + F2008 fix 09-226 ---------------------------------------------------------------------- NUMBER: F03/0039 TITLE: HYPOT() KEYWORDS: IEEE-754, hypot() DEFECT TYPE: Erratum STATUS: Passed by J3 meeting QUESTION: HYPOT is the Fortran function defined in Note 14.17. What is HYPOT(NaN,infinity)? HYPOT(NaN,finite)? HYPOT(X,Y) when X and/or Y is an infinity (even if the other is a NaN) shall be +infinity. Reason: hypot(), when one of the arguments is an infinity, is +infinity independent of the value of the other argument. So, if the NaN argument is replaced by zero, any finite number, or any infinity, hypot(infinity,NaN) is still infinity. HYPOT(X,Y) when X and/or Y is a NaN (and neither is infinite) shall be a NaN, and should one of the NaN arguments. ANSWER: The HYPOT example in note 14.17 illustrates the use of the features of this section to provide reliable software that is fast in the uncomplicated case. We did not consider what would happen if one of the arguments is a NaN and have therefore edited the text. DISCUSSION: In fact, if either X or Y is a NaN, the first executable statement will set HYPOT to a NaN without signaling an exception. The slower code in the IF construct will therefore not be executed and a NaN will be returned, which is consistent with the way NaNs are handled by intrinsic operators, see paragraph 3 of section 6.2 of the IEEE International Standard. To make this explicit, an edit is provided to test for these conditions. EDITS: Page and line numbers refer to 04-007. [page 389]. Subclause 14.11, Note 14.17, after the comment "! The processor clears the flags on entry" insert " IF (IEEE_IS_NAN (X) .OR. IEEE_IS_NAN (Y)) THEN HYPOT = SQRT (-1.0) RETURN ENDIF" [page 389]. Subclause 14.11, Note 14.17, final paragraph, line 2. Before "exception" add "overflow or underflow". SUBMITTED BY: Fred Tydeman HISTORY: 05-118 m171 F03/0039 submitted 05-118r3 m171 Passed by J3 meeting 05-170 m172 Passed J3 letter ballot #11 N1622 m172 Failed WG5 ballot N1629 09-222 m188 Revised answer 09-222r1 m188 Revised again to test for NAN arguments 09-222r2 m188 Passed by J3 meeting + F2008 fix 09-226 ---------------------------------------------------------------------- NUMBER: F03/0078 TITLE: IEEE_SUPPORT_DATATYPE vs. mathematical equivalence KEYWORDS: IEEE_SUPPORT_DATATYPE, mathematical equivalence DEFECT TYPE: Interpretation STATUS: Passed by J3 meeting QUESTION: Does the function IEEE_SUPPORT_DATATYPE (Section 14.8) override the mathematical equivalence rule (Section 7.1.8.3)? For example, could the program PROGRAM MAIN USE, INTRINSIC :: IEEE_ARITHMETIC USE, INTRINSIC :: IEEE_FEATURES X = 2.0 + 2.0 PRINT *, X END be executed as PROGRAM MAIN USE, INTRINSIC :: IEEE_ARITHMETIC USE, INTRINSIC :: IEEE_FEATURES X = 220.0*(1.0/55.0) PRINT *, X END if IEEE_SUPPORT_DATATYPE(X) is .TRUE.? Background: The committee recently ruled that 2.0 + 2.0 must produce the value 4.0 if IEEE_ARITHMETIC is in effect. I agree that if the particular operation the processor implements is addition of 2.0 and 2.0, the result must be 4.0. However, if IEEE_ARITHMETIC does not override the mathematical equivalence rule, the requirement is essentially meaningless, since there is no assurance that the expression in the program is the expression that will be evaluated. ANSWER: No, the mathematical equivalence rule is not overridden by USE of the IEEE_ARITHMETIC or IEEE_FEATURES modules. Doing so would prevent many benign and useful compiler optimizations and thus have an unnecessarily deleterious effect on performance. The mathematical equivalence displayed in the example is not a reasonable one, but deciding which mathematical equivalences are reasonable or not is outwith the scope of the standard. EDITS: None. SUBMITTED BY: Michael Ingrassia HISTORY: 06-124 m175 F03/0078 submitted 09-265 m189 Passed by J3 meeting ---------------------------------------------------------------------- NUMBER: F03/0090 TITLE: Polymorphic array constructors KEYWORDS: polymorphic, array constructor DEFECT TYPE: Erratum STATUS: Passed by J3 meeting QUESTION: (1) Consider FUNCTION f1(dummy,n) CLASS(t) dummy TYPE(t) f(n) f = [ (dummy,i=1,n) ] END FUNCTION Is this standard-conforming? (2) If the array constructor elements are polymorphic, is the array constructor polymorphic with the dynamic type of the elements? For example, consider FUNCTION f2(dummy,n) CLASS(t) dummy CLASS(t),ALLOCATABLE :: f(:) IF (...) THEN ALLOCATE(f(n),SOURCE=[(dummy,i=1,n)]) ! **1 ELSE ALLOCATE(f(n),SOURCE=dummy) ! **2 END IF END FUNCTION The second ALLOCATE statement (marked **2) clearly allocates F with size N and the dynamic type of DUMMY. If the array constructor is polymorphic, the first ALLOCATE statement (marked **1) will have the same effect, otherwise it will allocate F with the dynamic type of F equal to the declared type of DUMMY. (3) If the array constructor is polymorphic, what is the dynamic type when multiple items have different dynamic types? ANSWER: (1) Yes. (2) No, it was not intended for array constructors to be polymorphic. A polymorphic array value, if desired, can be safely constructed by using an allocatable array function. (3) Not applicable. An edit is provided to clarify the situation. EDITS: [67:21] "same type" -> "same declared type" [68:9] "type and" -> "declared type and" [68:14+] Insert new paragraph "The dynamic type of the array constructor is the same as its declared type." SUBMITTED BY: Van Snyder HISTORY: 07-231 m180 F03/0090 submitted (revised by M. Cohen) 07-231 m180 Passed by J3 meeting 07-272 m181 Failed J3 letter ballot #13 07-250r1 09-266 m189 Revised answer - Passed by J3 meeting ---------------------------------------------------------------------- NUMBER: F03-0130 TITLE: Elemental specific intrinsic procedure characteristics KEYWORDS: Elemental intrinsic, procedure pointer, dummy procedure DEFECT TYPE: Interpretation STATUS: Passed by J3 meeting QUESTION: (1) Are the specific intrinsic procedures (listed in 13.6 and not marked with a bullet) elemental or nonelemental? (2) What rank do those specific intrinsic procedures have? (3) May one of those procedures become associated with a dummy procedure or procedure pointer with nonzero rank? (4) When one of these procedures is associated with a dummy procedure or procedure pointer, does it still have the elemental property? ANSWER: (1) Those specific intrinsic procedures are elemental. (2) They are elemental functions; thus they are scalar in themselves, but may be applied to an array in which case the reference will be an array. (3) No. As elemental procedures, by definition the dummy arguments and result have rank zero. This does not satisfy the requirements for procedure argument or procedure pointer association. (4) The specific intrinsic procedure itself retains the elemental property (so a reference using its own name can be elemental), but the dummy procedure or procedure pointer associated with it is not elemental and so cannot be used to reference the specific intrinsic procedure elementally. EDIT: None. SUBMITTED BY: Van Snyder HISTORY: 09-171r1 m188 F03/0130 submitted 09-217 m188 Revised question/answer - passed by J3 meeting ---------------------------------------------------------------------- NUMBER: F03/0131 TITLE: SAVE attribute and EQUIVALENCE KEYWORDS: SAVE, EQUIVALENCE DEFECT TYPE: Erratum STATUS: Passed by J3 meeting QUESTION: If one object in an EQUIVALENCE set has the SAVE attribute, do all the other objects in the EQUIVALENCE set implicitly have the SAVE attribute? This can be detected by the program: SUBROUTINE s1 TYPE T SEQUENCE REAL :: C = 3.0 END TYPE TYPE(t) x,y SAVE x EQUIVALENCE(x,y) x = t(1.0) RETURN ENTRY s2 PRINT *,y ! Does this print 1.0 or 3.0? END PROGRAM show CALL s1 CALL s2 END If Y has the SAVE attribute the program will print 1.0; if not, it will print 3.0 due to the default initialization. ANSWER: Yes, the SAVE attribute propagates through EQUIVALENCE. An edit is supplied to clarify this. EDIT: [97:7+] Insert new paragraph "If any data object in an has the SAVE attribute, all other objects in the have the SAVE attribute; this may be confirmed by explicit specification." SUBMITTED BY: Malcolm Cohen HISTORY: 09-194 m188 F03/0131 submitted 09-194r1 m188 Passed by J3 meeting ---------------------------------------------------------------------- NUMBER: F03/0132 TITLE: Unformatted i/o and private components KEYWORDS: UNFORMATTED, INPUT/OUTPUT, PRIVATE DEFECT TYPE: Erratum STATUS: Passed by J3 meeting QUESTION: Consider Module M Type T Private Real :: UDATA(100) End Type End Module ... Type(T) X ... Write (10,*) X ! Formatted Write Write (20) X ! Unformatted Write Both of the WRITE statements were not valid Fortran 95. Are either of them valid Fortran 2003? According to [193:9-12], the formatted WRITE statement is not valid. But the corresponding paragraph for unformatted WRITEs, at [193:1-5], only forbids private components when some component of T would itself be handled by user-defined derived-type input/output. That does not seem to be consistent. DISCUSSION: The "shall not be pointers or allocatables" part of the [193-:1-5] paragraph is repeated later, at [193:13-15]. This makes no mention of accessibility. ANSWER: Both cases were intended to be invalid. An edit is supplied to repair the requirements for unformatted i/o. EDIT: [193:13-15] Replace paragraph "If a derived-type list item is not processed by a user-defined derived-type input/output procedure and is not treated as a list of its individual components, all the subcomponents of that list item shall be accessible in the scoping unit containing the input/output statement and shall not be pointers or allocatable". SUBMITTED BY: Malcolm Cohen HISTORY: 09-195 m188 F03/0132 submitted - passed by J3 meeting ---------------------------------------------------------------------- NUMBER: F03/0133 TITLE: Is unlimited polymorphic allowed in COMMON? KEYWORDS: Unlimited polymorphic, CLASS(*), COMMON DEFECT TYPE: Erratum STATUS: Passed by J3 meeting QUESTION: For a pointer to a derived type to be storable in COMMON, it must be of sequence type. However, there does not seem to be any prohibition against a CLASS(*) pointer in COMMON. Is this allowed? ANSWER: This was inadvertently allowed in the Fortran 2003 standard as published. An edit is supplied to correct this error. EDIT: [98:22] After "BIND attribute," insert "an unlimited polymorphic pointer," SUBMITTED BY: Malcolm Cohen HISTORY: 09-204 m188 F03/0133 submitted - passed by J3 meeting ---------------------------------------------------------------------- NUMBER: F03/0134 TITLE: Implicit typing of procedure pointers KEYWORDS: procedure pointer, implicit type DEFECT TYPE: Erratum STATUS: Passed by J3 meeting QUESTION: Q1. Are procedure pointer components implicitly typed? That is, considering PROGRAM implicitppc EXTERNAL proc TYPE t PROCEDURE(),POINTER,NOPASS :: ptr END TYPE t TYPE(t) :: i i%ptr => proc PRINT *,i%ptr() END PROGRAM is this program standard-conforming and if so, what is the type of the procedure pointer component PTR? In J3/04-007 one finds (p. 93, ll. 8-11) 5.3 "Any data entity that is not explicitly declared by a type declaration statement, is not an intrinsic function, and is not made accessible by use association or host association is declared implicitly to be of the type (and type parameters) mapped from the first letter of its name, provided the mapping is not null." Q2. Are ambiguous procedure pointers allowed? That is, considering SUBROUTINE ppOne(do_the_subroutine) LOGICAL :: do_the_subroutine EXTERNAL some_subroutine, some_function PROCEDURE(), POINTER :: proc_pointer IF (do_the_subroutine) THEN proc_pointer => some_subroutine CALL proc_pointer(5) ELSE proc_pointer => some_function y = proc_pointer(7) END IF END SUBROUTINE (a) Does the subroutine ppOne conform to the Fortran standard? (b) If yes, does a subroutine with the "if"/"else"/"end if" lines removed conforms to the standard? In J3/04-007 one finds (p. 145, ll. 2-4) 7.4.2.2 "If proc-pointer-object has an implicit interface and is explicitly typed or referenced as a function, proc-target shall be a function. If proc-pointer-object has an implicit interface and is referenced as a subroutine, proc-target shall be a subroutine." Q3. If ambiguously-typed procedure pointers are allowed, are they still allowed with IMPLICIT NONE? That is, considering IMPLICIT NONE ! p is not implicitly typeable REAL, EXTERNAL :: func PROCEDURE(), POINTER :: p1 PROCEDURE(REAL),POINTER :: p2 REAL y p1 => func ! A p2 => p1 ! B y = p2() END PROGRAM are the procedure pointer assignments A and B standard-conforming? In J3/04-007 one finds (p.146, ll. 36-38; p. 145, ll. 2-6) 7.4.2.2 Procedure pointer assignment "If the proc-target is not a pointer, proc-pointer-object becomes pointer associated with proc-target. Otherwise, the pointer association status of proc-pointer-object becomes that of proc-target; if proc-target is associated with a procedure, proc-pointer-object becomes associated with the same procedure. [...] If proc-pointer-object has an implicit interface and is explicitly typed or referenced as a function, proc-target shall be a function. If proc-pointer-object has an implicit interface and is referenced as a subroutine, proc-target shall be a subroutine. If proc-target and proc-pointer-object are functions, they shall have the same type; corresponding type parameters shall either both be deferred or both have the same value." ANSWER: (1) No, procedure pointer components are never implicitly typed. The quoted text from the standard does not apply to components; if it did apply to components, data components would also be implicitly typed and that would be a contradiction. A clarifying edit is provided. (2) Yes, ambiguous procedure pointers are allowed. However, a procedure pointer is only ambiguous if it is neither referenced as a subroutine nor as a function. Therefore, as the quoted text from the standard indicates, the example is not conforming. (3) No, a procedure pointer with no type can only be ambiguous if there is a valid implicit type mapping for the initial letter of its name. Therefore, with IMPLICIT NONE, PROCEDURE() declares a subroutine with an implicit interface, the same as EXTERNAL. EDITS: [93:9] After "function," insert "is not a component,". {Components are never implicitly typed.} SUBMITTED BY: Tobias Burnus HISTORY: 09-236 m189 F03/0134 submitted 09-236r1 m189 Passed by J3 meeting ---------------------------------------------------------------------- NUMBER: F03/0135 TITLE: Interaction between RESULT, recursion, and host generic KEYWORDS: RESULT, generic, recursion DEFECT TYPE: Interpretation STATUS: Passed by J3 meeting QUESTION: Consider MODULE example INTERFACE f MODULE PROCEDURE f0,f END INTERFACE CONTAINS INTEGER FUNCTION f0(n) RESULT(y) y = n + 1 END FUNCTION INTEGER FUNCTION f(n1,n2) RESULT(y2) y2 = f(n1+n2) END FUNCTION END MODULE Q1. Does the reference to F in the assignment to Y2 refer to the generic F (and is thus a valid reference to F0) or to the specific F (and is thus an invalid recursive reference to itself with the wrong number of arguments)? Section 12.5.2.1 (Function subprogram, at lines 31-33 on page 296) states: "If RESULT is specified, [...] all occurrences of the function name in execution-part statements in the scoping unit refer to the function itself." That would appear to indicate that it is a reference to the specific F itself, and thus invalid. How should the rules in 12.4.4 for resolving named procedure references be applied to this? In particular, for the reference to F from within F, Q2. Is F established to be generic by rule (1)(d)? If so, that should mean that the reference to F within itself is a valid reference to the generic F (then resolved to F0). Q3. Is F established to be specific by rule (2)(e)? Even if F is not established to be generic, if it is established to be specific then the subsequent rule (6) in 12.4.4.2 means the reference is valid, being resolved via host association to the generic F (then resolved to F0). Q4. If F is not established, then rule (3) in 12.4.4.3 indicates the reference would be to the external procedure F. That does not seem to make sense. Consider the case where F instead looks like this: RECURSIVE INTEGER FUNCTION f(n1,n2) RESULT(y2) IF (n1>1 .AND. n2>1) THEN y2 = f(n1-1,n2-1) ELSE y2 = MAX(n1,n2) END IF END FUNCTION This would appear to be a valid subprogram using the interpretation in 12.5.2.1 (that F is a reference to itself), but if F is not established then it would not be valid. Q5. Is this example conforming? ANSWER: (1) The analysis is correct, the use of F within the function F is, as stated, a reference to F itself (and thus the example is invalid). (2) F is not established to be generic: it contains a declaration of F (the FUNCTION statement itself) so the generic in the host in the rule (1)(d) does not apply. (3) According to the rules as they are now, F is not established to be specific: rule (2)(e) is inapplicable because the FUNCTION statement is a declaration of F. This is an error in the standard. (4) You are correct, that would not make sense. This is an error in the standard. (5) You are correct, these rules are contradictory. The intent was that this example should be conforming. Edits are supplied to correct the rules in 12.4.4 to account for recursive self-references to functions with RESULT clauses. The function F should be established to be specific, and the reference should be to itself. EDITS: [276:36+] Insert new case "(a2) if the scoping unit is a subprogram that defines a procedure with that name;" {Establish the name to be (only) specific.} [278:15+] Insert new case "(3a) If the scoping unit is a subprogram that defines a procedure with that name, the reference is to that procedure." {Resolve to the procedure.} SUBMITTED BY: Tobias Burnus HISTORY: 09-237 m189 F03/0135 submitted 09-237r1 m189 Passed by J3 meeting ---------------------------------------------------------------------- NUMBER: F03/0136 TITLE: Are subroutines distinguishable from arrays? KEYWORDS: Generic resolution, subroutine, array DEFECT TYPE: Erratum STATUS: Passed by J3 meeting QUESTION: Can a subroutine be used as a disambiguator in a generic reference? A subroutine cannot reliably be distinguished from a scalar function because of implicit typing. However, it can always be distinguished from an array function, because an array function needs to have an explicit interface that provides its rank (and type, but rank is the important consideration for this question). For generic resolution, the Fortran 95 standard allowed a dummy argument to be a "disambiguator" if it had a different data type, kind type parameter, or rank (14.1.2.3, page 277). There is no clear definition of what the rank of a subroutine is, but many have assumed that the rank of a subroutine is zero; thus allowing "subroutine vs. array" to be used to disambiguate generic references. However, this text was changed in Fortran 2003 to forbid a subroutine from ever being used as a disambiguator (16.2.3, page 407). Here is an example: Module example Interface gen Module Procedure invoke,aprint End Interface Contains Subroutine invoke(s) External s Call s ! We know this is a subroutine. End Subroutine Subroutine aprint(a) Real a(:) Print *,'[',a,']' End Subroutine End Module It is clear that if the Call s statement were changed to Print *,s() then the module would be standard-conforming. It seems inconsistent to allow scalar functions to disambiguate with arrays but to disallow subroutines from disambiguating with arrays. DISCUSSION: In Fortran 2003, procedureness is a potential disambiguator which would make the above simple example conforming, but there is still a problem with Subroutine invoke(s,n) External s Call s(n) ! We know this is a subroutine. End Subroutine Subroutine aprint(af) Interface Function af(n) Real af(n) End Function End Interface Print *,'[',af(n),']' End Subroutine Again, changing "Call s(n)" to "Print *,s(n)" would make the example conform to the standard as written. ANSWER: This inconsistency was inadvertant. Edits are supplied to correct this oversight. EDITS: [407:28] After "distinguishable if" insert "one is a subroutine and the other is an array, or if". SUBMITTED BY: Malcolm Cohen. HISTORY: 09-264 m189 F03/0136 submitted - Passed by J3 meeting ---------------------------------------------------------------------- NUMBER: F03/0137 TITLE: Dummy procedure type compatibility KEYWORDS: Dummy function, implicit interface DEFECT TYPE: Interpretation STATUS: Passed by J3 meeting QUESTION: Consider PROGRAM EXAMPLE REAL,EXTERNAL :: F CALL S(F) END SUBROUTINE S(A) INTEGER,EXTERNAL :: A PRINT *,A() END SUBROUTINE REAL FUNCTION F() F = HUGE(0.0) END FUNCTION Subclause 12.4.1.3 (pages 271-272) appear to require that the actual argument corresponding to a procedure dummy argument must be a function if the dummy procedure is referenced as a function, but there seems to be no visible requirement for it to have the same type and type parameters. That would seem to make the above program standard conforming. Is there intended to be such a requirement? ANSWER: Yes, there should be such a requirement. An edit is supplied to correct this oversight. EDIT: [271:28] Append new sentences to the end of paragraph 5 of 12.4.1.3 "If both the actual argument and dummy argument are known to be functions, they shall have the same type and type parameters. If only the dummy argument is known to be a function, the function that would be invoked by a reference to the dummy argument shall have the same type and type parameters, \obs{except that an external function with assumed character length may be associated with a dummy argument with explicit character length}". {The second sentence is there to catch an argument association chain, and this case needs to allow the obsolescent assumed-length character function. In the case in the first sentence, the actual argument already is prevented from having assumed length by our other rules.} SUBMITTED BY: Malcolm Cohen HISTORY: 09-267 m189 F03/0137 submitted - Passed by J3 meeting ---------------------------------------------------------------------- NUMBER: F03/0138 TITLE: External as KEYWORDS: procedure name, procedure pointer, procedure pointer assignmant DEFECT TYPE: Erratum STATUS: Passed by J3 meeting QUESTION: 7.4.2 C727 says a " [that is a ] shall be the name of an external ... procedure...." To be passed as an actual argument, a procedure needs to have the EXTERNAL attribute, but there appears to be no such requirement for being a target in a procedure pointer assignment. (1) Is the following example standard-conforming? PROGRAM example1 PROCEDURE(),POINTER :: p PROCEDURE(REAL),POINTER :: q p => x CALL x q => y PRINT *,y(5) CALL p PRINT *,q(5) END SUBROUTINE x PRINT *,'ok so far' END FUNCTION y(n) y = SQRT(REAL(n)) END (2) If example1 is standard-conforming, is this example conforming? MODULE exmod PROCEDURE(),POINTER :: p CONTAINS SUBROUTINE test CALL p END SUBROUTINE END PROGRAM example2 USE exmod p => x CALL test END SUBROUTINE x PRINT *,'ok' END ANSWER: (1) Yes, this example is conforming. As correctly noted, there is no requirement for the EXTERNAL attribute in a procedure pointer assignment, and both X and Y are known within the main program to be external procedures. (2) This example was not intended to be conforming. An edit is provided to clarify this. EDIT: [144:5-6] In 7.4.2 Pointer assignment, constraint C727, Change "an external, module," to "a module", Change "or a procedure pointer" to "a procedure pointer, or an external procedure that is accessed by USE or host association, referenced in the scoping unit as a procedure, or that has the EXTERNAL attribute". SUBMITTED BY: Van Snyder HISTORY: 09-281 m189 F03/0138 submitted - Passed by J3 meeting ----------------------------------------------------------------------