[J3] (SC22WG5.6288) WG5 letter ballot 1 on Fortran 2018 interpretations

Steve Lionel steve at stevelionel.com
Thu Sep 24 19:02:39 EDT 2020


                                           ISO/IEC JTC1/SC22/WG5 N2176

           WG5 letter ballot 1 on Fortran 2018 interpretations
                       Steve Lionel, September 24, 2020

This is the first set of draft interpretations for Fortran 2018. They
have all been approved in a J3 letter ballot.

The rules we operate on say:

4. The chair of J3/interp gathers all interp answers that are marked
    "passed by J3 letter ballot" and forwards them to the WG5 convenor.
    The WG5 convenor holds a ballot of individual members; a no vote
    must be accompanied by an explanation of the changes necessary to
    change the member's vote to yes. The answers that pass this ballot
    become "WG5 approved".

    J3/interp reserves the right to recall an interp answer for more
    study even if the answer passes.

5. "WG5 approved" answers are processed into a corrigendum document by
    taking the edits from the interp answers and putting them in the
    format required by ISO.  A WG5 vote is made on forwarding the
    corrigendum to SC22.

The following Fortran 2018 interpretations are being balloted:

Yes  No Number   Title
--- --- F18/001  ACOSH principal value specification is wrong
--- --- F18/002  Internal procedures in generic interface blocks
--- --- F18/003  Pointer association of component of non-definable selector
--- --- F18/004  Program execution sequence with failed images
--- --- F18/005  Does INPUT_UNIT really identify the same unit as *?
--- --- F18/006  Connection of INPUT_UNIT on different images
--- --- F18/008  Contradictory assumed-rank requirements
--- --- F18/009  Bad examples in IEEE_ARITHMETIC functions
--- --- F18/010  Categories of pure procedures
--- --- F18/011  Categories of elemental procedures
--- --- F18/012  Internal procedure in a generic interface
--- --- F18/013  TEAM_NUMBER arguments and intrinsic function are ambiguous
--- --- F18/014  Type of OPERATION arguments to the REDUCE intrinsic
--- --- F18/015  Example in C.6.8 is wrong
--- --- F18/016  Host association changes in Fortran 2018
--- --- F18/017  Final subroutine invocation order
--- --- F18/018  Public namelist and private variable

The text of these interpretations appears below.
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
vote section to

         sc22wg5 at open-std.org

by 0001 Las Vegas time on October 24, 2020, in order to be counted.

Thanks,
Steve


----------------------------------------------------------------------

NUMBER: F18/001
TITLE: ACOSH principal value specification is wrong
KEYWORDS: ACOSH
DEFECT TYPE: Erratum
STATUS: Passed by J3 letter ballot

QUESTION:

Clause 16.9.5 ACOSH( X ) p5 Result Value has:
     "If the result is complex the imaginary part is expressed in
      radians and lies in the range 0 <= AIMAG (ACOSH (X)) <= {pi}".

There is general agreement that the principal value of ACOSH should
have the real part non-negative which means the imaginary part must
range from -pi to +pi.

Is this a mistake in the definition of ACOSH?

ANSWER:

Yes, this is a mistake.  Edits are included to correct this error.
This will be an incompatibility with Fortran 2008.

EDITS to 18-007r1:

[26:17+] 4.3.3 Fortran 2008 compatibility, p10+, insert new para
          "Fortran 2008 required ACOSH of a complex value to have the
           imaginary part nonnegative and had no requirement on
           the real part.  This document requires ACOSH of a complex
           value to have a nonnegative real part and has no such
           requirement on the imaginary part."

[340:34-35] 16.9.5 ACOSH, p5 Result Value,
             after "is complex"
             insert "the real part is nonnegative and",
             change "range 0" to "range $-\pi$".
Making the whole p5 read
     "Result Value. The result has a value equal to a processor-
      dependent approximation to the inverse hyperbolic cosine
      function of X. If the result is complex the real part is non-
      negative, and the imaginary part is expressed in radians and
      lies in the range $-\pi$ <= AIMAG (ACOSH (X)) <= $\pi$."

SUBMITTED BY: Anton Shterenlikht

HISTORY: 18-236   m217  Submitted
          18-236r1 m217  Put into interp format, revised edits.
          18-236r2 m217  Revised draft - Passed by J3 meeting
          19-228   m220  Passed as amended by J3 letter ballot #35

----------------------------------------------------------------------
----------------------------------------------------------------------

NUMBER: F18/002
TITLE:  Internal procedures in generic interface blocks
KEYWORDS: Internal procedure, generic interface block
DEFECT TYPE: Erratum
STATUS: Passed by J3 letter ballot

QUESTION:

An internal procedure is allowed in a GENERIC statement, but
apparently it cannot appear in a generic interface block.

Section 15.4.3.4.1 (12.4.3.4.1 in F2008) Generic identifiers p1 states
   "A generic interface block specifies a generic interface for each
    of the procedures in the interface block.  The PROCEDURE statement
    lists procedure pointers, external procedures, dummy procedures,
    or module procedures that have this generic interface."

Is the apparent prohibition of internal procedures in the PROCEDURE
statement intended?

ANSWER:

No, this was not intended.  An internal procedure should be allowed
in a generic interface body. An edit is provided to correct this
mistake.

DISCUSSION:

In F2003, Section 12.3.2.1 Interface Block has rule R1206

    <procedure-stmt>    is [MODULE] PROCEDURE <procedure-name-list>

with constraint C1270

     "A <procedure-name> shall have an explicit interface and shall
      refer to an accessible procedure pointer, external procedure,
      dummy-procedure, or module procedure."

Edits in paper 05-202r1 allowed internal procedures to be passed as
actual arguments and to be targets of procedure pointers. This meant
an internal procedure could be the target of a procedure pointer
which was specified in a generic interface body.

Paper 08-178 asked the question "What is the point of excluding
internal procedure in C1207?" and replaced C1207 with

    "A <procedure-name> shall be a nonintrinsic procedure that has an
     explicit interface."

The normative text cited in the question was not modified.
This was an oversight.

EDIT to 18-007r1:

[294:11-12] 15.4.3.4.1 Generic identifiers, p1, second sentence,
             Change "procedure pointers, external procedures, dummy
                     procedures, or module procedures"
             to "nonintrinsic procedures with explicit interfaces".

This makes the sentence read:
   "The PROCEDURE statement lists nonintrinsic procedures with explicit
    interfaces that have this generic interface."

SUBMITTED BY: Jon Steidel

HISTORY: 18-251   m217  Submitted
          18-251r1 m217  Revised draft - Passed by J3 meeting
          n/a      n/a   Typos noted at meeting corrected by /Interp.
          19-228   m220  Passed by J3 letter ballot #35

----------------------------------------------------------------------
----------------------------------------------------------------------

NUMBER: F18/003
TITLE: Pointer association of component of non-definable selector
KEYWORDS: Pointer association, Associate name
DEFECT TYPE: Erratum
STATUS: Passed by J3 letter ballot

QUESTION:

Consider the following

   type :: T
     real, pointer :: X
   end type T

   type(t), external :: F
   real, target :: P

   associate ( A => F(42) )
     nullify ( A%X )             !***
     A%X => P                    !***
   end associate

The topic is whether the statements marked "!***" (the NULLIFY
statement and the pointer assignment statement) conform to the
standard.

11.1.3.3p5 ([175:18-21] of 18-007r1) has two requirements that are
relevant to this topic:
     "The associating entity itself is a variable, but if the selector
      is not a definable variable, the associating entity is not
      definable and shall not be defined or become undefined. If a
      selector is not permitted to appear in a variable definition
      context (19.6.7), neither the associate name nor any subobject
      thereof shall appear in a variable definition context."

With regards to the second sentence, neither NULLIFY nor a pointer
assignment statement is a variable definition context (19.6.7,
[516:12-30] lists fifteen variable definition context: neither
statement appears in the list.  Therefore it seems that this
requirement is satisfied.

With regards to the first sentence, the associate-name A "shall not
be defined or become undefined".  It appears that neither of these
statements cause A to be defined or become undefined, because
(a) An object of derived type is defined if and only all of its
     nonpointer components are defined (see 19.6.1p4, [511:11]).
     The pointer association status of the component A%X is thus
     irrelevant to the question of whether A is defined.
(b) Neither statement appears anywhere in the giant lists of "Events
     that cause variables to become defined" (or "undefined") in
     19.6.5 and 19.6.6.

Therefore we must reluctantly conclude that the requirements of the
first sentence also appear to be satisfied.

Against this, it is certainly true that the *value* of A is affected
by the statements in question: see 7.5.8 Derived-type values, which
states that the "component value" of a pointer component is its
association status, and
     "The set of values of a particular derived type consists of all
      possible sequences of the component values..."

However, there is no rule in 11.1.3.3 about changing the values, even
though it might seem contradictory that something that changes the
value of an undefinable object would be permitted.

So the question is, are the two statements standard-conforming?

ANSWER:

No, these statements were not intended to be standard-conforming.
The lack of an explicit rule is an error in the standard.
An edit is provided to correct this error.

EDIT to 18-007r1:

[175:21] 11.1.3.3 Other attributes of associate names, p5,
          After "variable definition context"
          insert " or a pointer association context",
making the whole paragraph read:
   "The associating entity itself is a variable, but if the selector
    is not a definable variable, the associating entity is not
    definable and shall not be defined or become undefined.  If a
    selector is not permitted to appear in a variable definition
    context (19.6.7), neither the associate name nor any subobject
    thereof shall appear in a variable definition context or pointer
    association context."
{Prohibit the marked statements.
  The extra context is only relevant to pointer subobjects, but this
  need not be stated explicitly.}

{This might appear to be an incompatibility since the explicit
  prohibition is missing from Fortran 2003 and 2008, and thus should
  require an edit to the "compatibility" subclauses in clause 4.
  However as it seems somewhat contradictory, it is argued that those
  standards do not establish an unambiguous interpretation of the code
  in question, so no compatibility issue arises.}

SUBMITTED BY: Van Snyder

HISTORY: 18-262r1 m217  Submitted
          18-262r2 m217  Revised draft - Passed by J3 meeting
          19-228   m220  Passed by J3 letter ballot #35

----------------------------------------------------------------------
----------------------------------------------------------------------

NUMBER: F18/004
TITLE: Program execution sequence with failed images
KEYWORDS: Program execution, Termination of execution, Failed image,
DEFECT TYPE: Erratum
STATUS: Passed by J3 letter ballot

QUESTION:

Consider execution of a program with more than one image, and some
image has failed (perhaps by execution of FAIL IMAGE, or perhaps by
some actual failure).  Let us further suppose that all other images
have initiated normal termination.

According to 5.3.7 "Termination of execution", paragraph 1:
     "Termination of execution of the program occurs
      when all images have terminated execution."
This text is unchanged from Fortran 2008, which did not have failed
images.

As an image that has failed "has ceased participating in program
execution but has not terminated execution", it would seem that in
this situation, execution of the program has not terminated.

Should failed images cause execution of the program not to terminate?

ANSWER:

No, failed images have stopped participating in program execution and
therefore their existence should not prevent program termination.
That this definition is unchanged from Fortran 2008 is an oversight.

An edit is supplied to correct this.

EDIT to 18-007r1:

[38:8] 5.3.7 Termination of execution, p1,
        After "when all images have terminated execution"
        insert "or failed",
        making the last sentence of the paragraph read
   "Termination of execution of the program occurs when all images
    have terminated execution or failed."

SUBMITTED BY: Malcolm Cohen

HISTORY: 19-129   m218  Submitted
          19-129r1 m218  Revised draft - Passed by J3 meeting
          19-228   m220  Passed as amended by J3 letter ballot #25

----------------------------------------------------------------------
----------------------------------------------------------------------

NUMBER: F18/005
TITLE: Does INPUT_UNIT really identify the same unit as *?
KEYWORDS: Connection, INPUT_UNIT
DEFECT TYPE: Interpretation
STATUS: Passed by J3 letter ballot

QUESTION:

According to 16.10.2.13 INPUT_UNIT [429:8-9],
     "The value of the default integer scalar constant INPUT_UNIT
      identifies the same processor-dependent external unit
      preconnected for sequential formatted input as the one
      identified by an asterisk in a READ statement;"

Consider the program:

     PROGRAM input_unit_test
         USE iso_fortran_env
         CHARACTER(80) line
         OPEN(input_unit,FILE='test.dat',ACTION='read')
         READ(input_unit,'(a)') line
         PRINT *,TRIM(line)
         READ(*,'(a)') line
         PRINT *,TRIM(line)
     END PROGRAM

Furthermore, let us suppose the file test.dat contains the
following two lines:
dat line 1
dat line 2
and let us further suppose the file that was preconnected before the
OPEN statement contains the following single line:
inp line 1

Is the output of the program (1):
  dat line 1
  dat line 2
or is it (2):
  dat line 1
  inp line 1
?

The plain meaning of the words
     "identifies the same processor-dependent external unit...
      ...as the one identified by an asterisk in a READ"
would seem to imply that (1) is expected, not (2); however, only
some Fortran processors produce output (1), while others have been
observed to produce output (2).

ANSWER:

Output (1) is correct.  According to the quoted words, using
INPUT_UNIT in a READ statement must have the same effect as UNIT=*
(which is the same effect as not having a input/output control list).

It is common for unit 5 to be effectively preconnected to stdin, but
on some processors changing the connection of unit 5 (e.g. with an
OPEN statement) does not affect unit=*.  On such a processor, the
value of INPUT_UNIT should not be equal to 5, but to whatever value,
possibly negative, that will continue to connect to unit=*.

EDIT to 18-007r1:

None.

SUBMITTED BY: Malcolm Cohen

HISTORY: 19-130   m218  Submitted
          19-130r1 m218  Revised draft - Passed by J3 meeting
          19-228   m220  Passed by J3 letter ballot #35

----------------------------------------------------------------------
----------------------------------------------------------------------

NUMBER: F18/006
TITLE: Connection of INPUT_UNIT on different images
KEYWORDS: Connection, INPUT_UNIT
DEFECT TYPE: Erratum
STATUS: Passed by J3 letter ballot

QUESTION:

According to 16.10.2.13 INPUT_UNIT [429:8-9],
     "The value of the default integer scalar constant INPUT_UNIT
      identifies the same processor-dependent external unit
      preconnected for sequential formatted input as the one
      identified by an asterisk in a READ statement;"
and according to 12.5.1 Referring to a file [217:10-11],
     "In a READ statement, an io-unit that is an asterisk identifies
      an external unit that is preconnected for sequential formatted
      input on image 1 in the initial team only (12.6.4.3)."

This leaves unanswered the status of the i/o unit identified by
INPUT_UNIT on images other that 1.  Plausible interpretations are:
(a) it is not preconnected on other images;
(b) it is preconnected, but to a processor-dependent file;
(c) it is preconnected, but it is not standard-conforming for a
     program to use it;
(d) it is preconnected, but it raises an i/o error condition if a
     program attempts to use it;
(e) attempting to use INPUT_UNIT in any way, including connecting it
     to another file, is not conforming;
(f) INPUT_UNIT may be connected to another file, but it is still
     processor-dependent whether it may be used;
(g) on an image other than image 1,
     - it is processor-dependent whether it is preconnected,
     - if it is preconnected,
         * it is processor-dependent to what file,
         * it is processor-dependent whether use is permitted,
     - if it is subsequently connected, it is processor-dependent
       whether it may be used.

Q1. What is the preconnection status of INPUT_UNIT on images other
     than image one?

Q2. On an image other than image one, if INPUT_UNIT happens to be
     preconnected, may it be used?

Q3. On an image other than image one, if INPUT_UNIT is connected to
     a different file by an OPEN statement, may it be used?

Also, the definition text for INPUT_UNIT in 16.10.2.13 makes no
mention of any caveat, but implies it is preconnected on every image.
Perhaps this text could be clarified.

ANSWER:

A1. INPUT_UNIT (and thus the unit identified by an asterisk in a READ
     statement) was not intended to be preconnected on images other
     than image one in the initial team.

     An edit is supplied to correct this omission.

A2. Moot.

A3. Yes.

EDITS to 18-007r1:

[217:11] 12.5.1 Referring to a file, p4,
     After "on image 1 in the initial team only (12.6.4.3)"
     insert "; it is not preconnected on any other image".
{Clarify preconnection state on images other than one.}
{Editor notes that "image 1" should be "image one".}

[429:9,10] 16.10.2.13 INPUT_UNIT, p1,
     Delete "preconnected for sequential formatted input".
{This is a mere parenthetical remark which could confuse.}
     After "input/output control list (12.6.4.3)." insert new sentence
         "This unit is preconnected for sequential formatted input on
          image one in the initial team only, and is not preconnected
          on any other image."
{Make this match clause 12.}

SUBMITTED BY: Malcolm Cohen

HISTORY: 19-131   m218  Submitted
          19-131r1 m218  Revised draft - Passed by J3 meeting
          19-228   m220  Passed by J3 letter ballot #35

----------------------------------------------------------------------
----------------------------------------------------------------------

NUMBER: F18/008
TITLE: Contradictory assumed-rank requirements
KEYWORDS: Assumed rank
DEFECT TYPE: Erratum
STATUS: Passed by J3 letter ballot

QUESTION:

Paragraph 1 of subclause 8.5.8.7 (Assumed-rank entity) states that an
assumed-rank entity is a dummy data object ... or the associate name
of a RANK DEFAULT block in a SELECT RANK construct.

C837 requires an assumed-rank entity to be a dummy data object. It
does not permit an associate name of a RANK DEFAULT block in a SELECT
RANK construct to have assumed rank.

Is an associate name of a RANK DEFAULT block in a SELECT RANK
construct permitted to have assumed rank?

ANSWER:

Yes, the associate name of a RANK DEFAULT block may have assumed rank.

An edit is supplied to remove the contradiction.

EDIT to 18-007r1:

[101:13-14 C837 in 8.5.8.7 Assumed-rank entity]

At the end of C837, after "or VALUE attribute", insert
     ", or the associate name of a RANK DEFAULT block in a SELECT RANK
      construct whose selector has assumed rank",
making the whole constraint read:

C837 An assumed-rank entity shall be a dummy data object that does not
      have the CODIMENSION or VALUE attribute, or the associate name of
      a RANK DEFAULT block in a SELECT RANK construct whose selector
      has assumed rank.

SUBMITTED BY: Van Snyder

HISTORY: 19-119   m218  Submitted
          19-119r1 m218  Revised draft - Passed by J3 meeting
          19-228   m220  Passed by J3 letter ballot #35

----------------------------------------------------------------------
----------------------------------------------------------------------

NUMBER: F18/009
TITLE:  Bad examples in IEEE_ARITHMETIC functions
KEYWORDS: IEEE_VALUE, IEEE_ARITHMETIC module, examples
DEFECT TYPE: Erratum
STATUS: Passed by J3 letter ballot

QUESTION:

In 17.11 the examples for IEEE_MAX_NUM, IEEE_MIN_NUM,
IEEE_QUIET_compare functions, and IEEE_SIGNALING_compare functions all
contain a call to IEEE_VALUE(IEEE_QUIET_NAN).  IEEE_VALUE has two
non-optional arguments, not one. Should calls to IEEE_VALUE in each of
these examples have an additional X= argument?

ANSWER:

Yes, IEEE_VALUE has two non-optional arguments, X and CLASS.
The X argument was mistakenly omitted.

Edits are provided to fix these issues.

EDITS to 18-007r1:

[448:12] 17.11.17 IEEE_MAX_NUM p8
Change "IEEE_VALUE (IEEE_QUIET_NAN)" to
        "IEEE_VALUE (1.0, IEEE_QUIET_NAN)"

[449:9] 17.11.19 IEEE_MIN_NUM p8
Change "IEEE_VALUE (IEEE_QUIET_NAN)" to
        "IEEE_VALUE (1.0, IEEE_QUIET_NAN)"

[451:4] 17.11.24 IEEE_QUIET_EQ p7
Change "IEEE_VALUE (IEEE_QUIET_NAN)" to
        "IEEE_VALUE (1.0, IEEE_QUIET_NAN)"

[451:18] 17.11.25 IEEE_QUIET_GE p7
Change "IEEE_VALUE (IEEE_QUIET_NAN)" to
        "IEEE_VALUE (1.0, IEEE_QUIET_NAN)"

[451:32] 17.11.26 IEEE_QUIET_GT p7
Change "IEEE_VALUE (IEEE_QUIET_NAN)" to
        "IEEE_VALUE (1.0, IEEE_QUIET_NAN)"

[452:10] 17.11.27 IEEE_QUIET_LE p7
Change "IEEE_VALUE (IEEE_QUIET_NAN)" to
        "IEEE_VALUE (1.0, IEEE_QUIET_NAN)"

[452:24] 17.11.28 IEEE_QUIET_LT p7
Change "IEEE_VALUE (IEEE_QUIET_NAN)" to
        "IEEE_VALUE (1.0, IEEE_QUIET_NAN)"

[452:38] 17.11.29 IEEE_QUIET_NE p7
Change "IEEE_VALUE (IEEE_QUIET_NAN)" to
        "IEEE_VALUE (1.0, IEEE_QUIET_NAN)"

[457:37] 17.11.41 IEEE_SIGNALING_EQ p7
Change "IEEE_VALUE (IEEE_QUIET_NAN)" to
        "IEEE_VALUE (1.0, IEEE_QUIET_NAN)"

[458:13] 17.11.42 IEEE_SIGNALING_GE p7
Change "IEEE_VALUE (IEEE_QUIET_NAN)" to
        "IEEE_VALUE (1.0, IEEE_QUIET_NAN)"

[458:27] 17.11.43 IEEE_SIGNALING_GT p7
Change "IEEE_VALUE (IEEE_QUIET_NAN)" to
        "IEEE_VALUE (1.0, IEEE_QUIET_NAN)"

[459:4] 17.11.44 IEEE_SIGNALING_LE p7
Change "IEEE_VALUE (IEEE_QUIET_NAN)" to
        "IEEE_VALUE (1.0, IEEE_QUIET_NAN)"

[459:18] 17.11.45 IEEE_SIGNALING_LT p7
Change "IEEE_VALUE (IEEE_QUIET_NAN)" to
        "IEEE_VALUE (1.0, IEEE_QUIET_NAN)"

[459:32] 17.11.46 IEEE_SIGNALING_NE p7
Change "IEEE_VALUE (IEEE_QUIET_NAN)" to
        "IEEE_VALUE (1.0, IEEE_QUIET_NAN)"

SUBMITTED BY: Jon Steidel

HISTORY: 19-124   m218  Submitted - Passed by J3 meeting
          19-228   m220  Passed by J3 letter ballot #35

----------------------------------------------------------------------
----------------------------------------------------------------------

NUMBER: F18/010
TITLE: Categories of pure procedures
KEYWORDS: pure
DEFECT TYPE: Erratum
STATUS: Passed by J3 letter ballot

QUESTION:

Subclause 15.7 Pure procedures begins with a list of categories of
pure procedures.  The list does not include procedure pointers or
type-bound procedures.  Dummy procedures are included in the list, and
so dummy procedure pointers are allowed, but other procedure pointers
are not.

Q1. Can procedure pointers that are not dummy procedures be pure?

Q2: Can type-bound procedures be pure?

ANSWER:

A1.  Procedure pointers that are not dummy procedures are allowed to
      be pure.  The absence of procedure pointers in the list in
      Subclause 15.7 is an oversight.  An edit to correct the oversight
      is provided.

A2.  Type-bound procedures that are bound to pure procedures are pure.
      The absence of type-bound procedures in Subclause 15.7 is an
      oversight.  An edit to correct the oversight is provided.

EDITS to 18-007r1:

[324:1, 15.7 "Pure procedures" p1]
     Replace
         "specified to be PURE, or"
     with
         "specified to be PURE,
          * a procedure pointer that has been specified to be PURE,
          * a type-bound procedure that is bound to a pure procedure, or"
{ Add missing entries to the list in Subclause 15.7. }

SUBMITTED BY:  Robert Corbett

HISTORY: 19-151   m218  Submitted - Passed by J3 meeting
          19-228   m220  Passed by J3 letter ballot #35

----------------------------------------------------------------------
----------------------------------------------------------------------

NUMBER: F18/011
TITLE: Categories of elemental procedures
KEYWORDS: elemental
DEFECT TYPE: Erratum
STATUS: Passed by J3 letter ballot

QUESTION:

The list of categories of elemental procedures at the start of
Subclause 15.8 "Elemental procedures" [325:11-12] is incomplete.
Procedures that are defined to be elemental in intrinsic modules
are not included.  Type-bound procedures are not included.
Dummy procedures and procedure pointers are not included, but
there is evidence that those omissions were intentional.

The standard intrinsic modules specify several procedures to be
elemental.  The omission of module procedures declared in intrinsic
modules from the list in Subclause 15.8 creates a contradiction.

Subclause 7.5.6.2 [80:5-8] and Subclause 7.5.7.3 [82:16] both
assume that type-bound procedures may be elemental.

Nonintrinsic elemental procedures cannot be used as actual arguments
[301: 29,  15.5.1 "Syntax of a procedure reference" p1]. Elemental
procedures specified in the standard intrinsic modules are generic,
and so they cannot be passed as actual arguments.  Elemental intrinsic
procedures can be passed as actual arguments [309: 2-5, 15.5.2.9
"Actual arguments associated with dummy procedure entities" p1], but
the text cited indicates that dummy procedures cannot be elemental.

Procedure pointers pose a bit of a problem.  A nonintrinsic elemental
procedure cannot be the target of a pointer assignment [165:34,
10.2.2.2 "Syntax of the pointer assignment statement" ].  However,
Subclause 10.2.2.4 "Pointer procedure assignment" paragraph 3 states

       If the pointer object has an explicit interface, its
       characteristics shall be the same as the pointer target except
       that the pointer target may be pure even if the pointer object
       is not pure and the pointer target may be an elemental intrinsic
       procedure even if the pointer object is not elemental.

The final phrase suggests that a pointer object might be elemental,
but it does not say that it can be elemental.

Q1. Is a procedure in an intrinsic module that is specified
     to be elemental an elemental procedure?

Q2. Can a type-bound procedure be elemental?

Q3. Can a dummy procedure be specified to be elemental?

Q4. Can a procedure pointer be specified to be elemental?

ANSWER:

A1. Procedures in intrinsic modules that are specified to be elemental
     are elemental.  An edit is provided to correct the omission in
     Subclause 15.8.

A2. A type-bound procedure that is bound to an elemental
     procedure is elemental.  An edit is provided to correct
     the omission in Subclause 15.8.

A3. A dummy procedure cannot be specified to be elemental.
     An edit is provided to make this restriction explicit.

A4. A procedure pointer cannot be specified to be elemental.
     An edit is provided to make this restriction explicit.

The edits provided are intended to make the impact on the existing
standard small.  More extensive changes are probably desirable, and
could be made in a revision of the standard.  In particular, the
restrictions on dummy arguments and procedure pointers could be made
constraints.

EDITS to 18-007r1:

[167:8] 10.2.4.4 Procedure pointer assignment, p3, Replace
         "elemental intrinsic procedure even if the pointer object
          is not elemental."
     with
         "elemental intrinsic procedure, even though the pointer
          object is not elemental."
{ Remove the suggestion that a procedure pointer might
   be elemental.}

[325:11-12] 15.8.1 Elemental procedure declaration and interface, p1,
     Replace the sentence
         "An elemental procedure is ... an elemental subprogram."
     with
         "An elemental procedure is
           * an elemental intrinsic procedure (16.1),
           * a module procedure in an intrinsic module, if it is
             specified to be elemental,
           * a procedure that is defined by an elemental subprogram, or
           * a type-bound procedure that is bound to an elemental
             procedure."
     and insert a new paragraph following it:
         "A dummy procedure or procedure pointer shall not be
          specified to be ELEMENTAL."
{ Add missing items to the list in Subclause 15.8.  Add a
   missing restriction to Subclause 15.8. }

SUBMITTED BY:  Robert Corbett

HISTORY: 19-153   m218  Submitted
          19-153r1 m218  Amended - Passed by J3 meeting
          19-228   m220  Passed by J3 letter ballot #35

----------------------------------------------------------------------
----------------------------------------------------------------------

NUMBER: F18/012
TITLE:  Internal procedure in a generic interface
KEYWORDS: Internal procedure, Generic interface
DEFECT TYPE: Clarification
STATUS: Passed by J3 letter ballot

QUESTION:

In Fortran 2003, an internal subprogram was not allowed to define a
specific procedure for a generic identifier:

Fortran 2003 [285:14-15]
C1207 (R1206) A <procedure-name> shall have an explicit interface and
       shall refer to an accessible procedure pointer, external
       procedure, dummy procedure, or module procedure.

Paper 08-178 proposed the new feature of permitting an internal
procedure in this context, and this was included in Fortran 2008:

[Fortran 2008 281:8]
C1207 (R1206) A <procedure-name> shall be a nonintrinsic procedure
       that has an explicit interface.

However, this new feature was not mentioned in the Introduction of
Fortran 2008, nor is it mentioned in Annex C.1 of Fortran 2018
(which lists Fortran 2008 features not originally mentioned in its
Introduction).

Should this be mentioned in Annex C.1?

ANSWER:

Yes, this new feature should be mentioned in Annex C.1.

An edit is provided.

EDIT:

[528:22+] C.1 Fortran 2008 features not mentioned in its
           Introduction, p1,
     Insert an item at the end of the bullet list:
         "- An internal procedure name can appear in a
            <procedure-stmt> in a generic interface block."

SUBMITTED BY: Van Snyder

HISTORY: 19-179   m219  Submitted - Passed by J3 meeting
          19-228   m220  Passed by J3 letter ballot #35

----------------------------------------------------------------------
----------------------------------------------------------------------

NUMBER: F18/013
TITLE:  TEAM_NUMBER arguments and intrinsic function are ambiguous
KEYWORDS: NUM_IMAGES, IMAGE_INDEX, TEAM_NUMBER, teams
DEFECT TYPE: Erratum
STATUS: Passed by J3 letter ballot

QUESTION:

Consider

PROGRAM p
    n = NUM_IMAGES()
    n1 = MERGE(1,2,THIS_IMAGE()<2)
    n2 = MERGE(1,3,THIS_IMAGE()<3)
    FORM TEAM(n1,x)
    FORM TEAM(n2,y)
    IF (n1==1) THEN
      CHANGE TEAM (x)
        PRINT *,NUM_IMAGES(TEAM_NUMBER=1) !(A)
        PRINT *,NUM_IMAGES(TEAM_NUMBER=3) !(B)
      END TEAM
    END IF
END PROGRAM

According to 16.9.145 NUM_IMAGES, the TEAM_NUMBER argument
     "shall identify the initial team or a team whose parent is the
      same as that of the current team".

However, at (A), there are two teams with team number 1 and the same
parent, one created by the FORM TEAM with "n1", the other created by
the FORM TEAM with "n2".

At (B), there is only one team with team number 3 and the same parent
as the current team, however, it is not a "sibling" team in that it
was not created by the same FORM TEAM statement.

Referring to the definition of the term "team number" at 3.145.4:
     "-1 which identifies the initial team, or positive integer that
      identifies a team within its parent team"
which has the same flaw in that there could be multiple teams within
the parent team that have that number.

Q1. Was TEAM_NUMBER in NUM_IMAGES, and the "team number" definition,
     intended to limit the identification to teams created by
     corresponding FORM TEAM statement executions?

Q2. The TEAM_NUMBER argument of IMAGE_INDEX suffers from similar
     wording. Was this also intended to be limited to "sibling" teams?

ANSWER:

Yes, this is the intention.  Edits are provided.

The edits use the terminology "corresponding" executions, as execution
on more than one image can hardly be the "same" execution.

The edits also use the term "sibling teams". As sibling teams are
always created as a group, and really only have meaning when there are
more than one, the plural form is probably most appropriate.

EDITS:

[20:27+] Terms and definitions:
   Insert after the definition of "parent team"
   "3.145.3+
    sibling teams
    teams created by a single set of corresponding executions of the
    FORM TEAM statement (11.6.9)"

[20:30] 3.145.4 team number, definition, change
         "within its parent team" -> "among its sibling teams"
making the definition read
     "-1 which identifies the initial team, or a positive integer that
    identifies a team among its sibling teams (5.3.4)

[36:23] 5.3.4 Program execution, para 2, final sentence
         Replace "Within its parent team,"
         with    "Among its sibling teams,"
making the whole sentence read
   "Among its sibling teams, each team is identified by its
    team_number; this is the integer value that was specified in the
    FORM TEAM statement."
{This is just waffle, no need to index "sibling teams".}

[131:18-19] In 9.6 Image selectors, p3 second sentence
             Replace "one of the teams that were formed by execution of
                      the FORM TEAM statement for"
             with    "a sibling team of"
making the whole sentence read
   "If a TEAM_NUMBER= specifier appears in an image-selector and the
    current team is not the initial team, the value of scalar-int-expr
    shall be equal to the value of a team number for a sibling team of
    the current team, and the team of the image selector is that team;
    the object shall be an established coarray in an ancestor team of
    the current team, or an associating entity of the CHANGE TEAM
    construct."

[204:35] 11.6.9 FORM TEAM statement, p1,
          change "creates new teams"
          to     "creates a set of sibling teams"
          and index "sibling teams" here.
This makes that whole paragraph read:
     "The FORM TEAM statement creates a set of sibling teams whose
      parent team is the current team."

[380:12-13] In 16.9.97 IMAGE_INDEX, p3 TEAM_NUMBER
     Change
         "team whose parent is the same as that of the current team"
     to
         "sibling team of the current team"
     and index "sibling teams" here.
making  the whole argument read:
  "TEAM_NUMBER shall be an integer scalar. It shall identify the
   initial team or a sibling team of the current team."

[401:24-25] 16.9.145 NUM_IMAGES, p3 Arguments, TEAM_NUMBER argument,
     Change
         "team whose parent is the same as that of the current team"
     to
         "sibling team of the current team"
     and index "sibling teams" here.
This makes that whole argument read:
  "TEAM_NUMBER shall be an integer scalar. It shall identify the
   initial team or a sibling team of the current team."

[421:9]16.9.189 TEAM_NUMBER([TEAM]), p5 Result Value,
     Change  "within its parent team"
     to      "among its sibling teams",
     and index "sibling teams" here.
This makes that whole paragraph read:
   "The result has the value -1 if the specified team is the initial
    team; otherwise, the result value is equal to the positive integer
    that identifies the specified team among its sibling teams."

SUBMITTED BY: Malcolm Cohen, Jon Steidel, and John Reid

HISTORY: 19-190   m219  Submitted
          19-190r1 m219  Merged with 19-178 - Passed by J3 meeting
          19-228   m220  Passed as amended by J3 letter ballot #35

----------------------------------------------------------------------
----------------------------------------------------------------------

NUMBER: F18/014
TITLE: Type of OPERATION arguments to the REDUCE intrinsic
KEYWORDS: REDUCE, OPERATION, polymorphic, type
DEFECT TYPE: Erratum
STATUS: Passed by J3 letter ballot

QUESTION:

Section 16.9.161 REDUCE p3 describes the arguments to the intrinsic
subroutine CO_REDUCE.

The description of the ARRAY argument states:
  "ARRAY shall be an array of any type."

It describes the OPERATION argument as:

  "OPERATION shall be a pure function with exactly two arguments; each
   argument shall be a scalar, nonallocatable, nonpointer, nonoptional
   dummy data object with the same type and type parameters as ARRAY.
   If one argument has the ASYNCHRONUS, TARGET, or VALUE attribute, the
   other shall have that attribute.  Its result shall be a non-
   polymorphic scalar and have the same type and type parameters as
   ARRAY.  OPERATION should implement a mathematically associative
   operation.  It need not be commutative."

The function result of OPERATION cannot be polymorphic.  The arguments
to OPERATION must have the same type as its result, and thus cannot be
polymorphic.  However, ARRAY can be polymorphic.  This means the dynamic
type of ARRAY must be the same type as the arguments and result of
OPERATION.  This seems like an unfortunate requirement.

Was it intended that the dynamic type of ARRAY be required to match
the type and type parameters of the arguments of OPERATION?

ANSWER:

No, this requirement was not intended.  Edits are provided to correct
the problem.

EDITS:
[408:36] change "type and type parameters"
          to     "declared type and type parameters"

[408:39] change "type and type parameters"
          to     "declared type and type parameters"

so that the description of OPERATION reads:
   "shall be a pure function with exactly two arguments; each argument
    shall be a scalar, nonallocatable, nonpointer, nonoptional dummy
    data object with the same declared type and type parameters as
    ARRAY.  If one argument has the ASYNCHRONOUS, TARGET, or VALUE
    attribute, the other shall have the attribute. Its result shall be
    a non-polymorphic scalar and have the same declared type and type
    parameters as ARRAY.  OPERATION should implement a mathematically
    associative operation. It need not be commutative."

[409:5] change "type and type parameters"
         to     "declared type and type parameters"

so that the first sentence of Result Characteristics reads:
   "The result is of the same declared type and type parameters as
    ARRAY."

SUBMITTED BY: Jon Steidel

HISTORY: 19-192   m219  Submitted
          19-192r1 m219  Revised draft - Passed by J3 meeting
          19-228   m220  Passed by J3 letter ballot #35

----------------------------------------------------------------------
----------------------------------------------------------------------

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?

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.

Some of the noteworthy additional changes are:
  - declarations separated out and many comments added or changed;
  - 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 ! 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 :: read_checkpoint ! If read_checkpoint true on
      ! entering simulation_procedure, go back to previous check point.
   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()-10,1))
   images_used = NUM_IMAGES () - images_spare
   ALLOCATE ( old_failures(0), map(images_used+1:NUM_IMAGES()) )
   read_checkpoint = .FALSE. ! Initial startup, not from checkpoint.

   outer : DO
     local_index = THIS_IMAGE ()
     team_number = MERGE (1, 2, local_index<=images_used)
     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 (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-132   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-132   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<AFIN
     TFIN<OFIN<PFINAL
Note there is no ordering between AFIN and OFIN, and no ordering
between AFIN and PFIN. Thus, after applying the edits below to the
standard, the following execution orders are valid:
     TFIN, AFIN, OFIN, PFIN
     TFIN, OFIN, AFIN, PFIN
     TFIN, OFIN, PFIN, AFIN

EDITS to 18-007r1:

[80:9] 7.5.6.2 The finalization process, p1, item (2),
        "All finalizable" -> "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-132   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-132   m222  Passed as amended by J3 letter ballot #36

----------------------------------------------------------------------



More information about the J3 mailing list