ISO/IEC JTC1/SC22/WG5 N1489 DRAFT (8 August 2002) THE NEW FEATURES OF FORTRAN 2000 John Reid, WG5 Convener 1. INTRODUCTION The aim of this paper is to summarize the new features in the draft Fortran 2000 standard (J3 2002). We take as our starting point Fortran 95 plus the two official extensions (Cohen 2001, Reid 2001) that have been published as Type 2 Technical Reports. These provide features for 1. Allocatable dummy arguments and type components 2. Exception handling and support of the IEEE Floating Point standard There is a firm commitment to include the features of these TRs in Fortran 2000, apart from changes that follow from errors and omissions found during implementation. Therefore, these features are not open to comment and are not described here. For an informal description, see chapters 12 and 13 of Metcalf and Reid (1999). Fortran 2000 is a major extension of Fortran 95. This contrasts with Fortran 95, which was a minor extension of Fortran 90. We hope that this will help people to prepare comments, but it is not an official document and has not been approved by either WG5 or J3. Comments should be based on the draft itself (J3 2002). Note that it is accessible via the web. 2. DATA ENHANCEMENTS AND OBJECT ORIENTATION 2.1 Parameterized derived types An obvious deficiency of Fortran 95 is that whereas each of the intrinsic types has a kind parameter and character type has a length parameter, it is not possible to define a parameterized derived type. This deficiency is remedied with a very flexible facility that allows any number of 'kind' parameters and 'nonkind' parameters. A kind parameter is a constant (fixed at compile time) and may be used for a kind parameter of a component of intrinsic type. A nonkind parameter is modelled on the length parameter for type character and may be used for declaring the bounds of array components. The names of the type parameters are declared on the type statement of the type definition, like the dummy arguments of a function or subroutine. Here is an example for a matrix type TYPE matrix(kind,m,n) INTEGER, KIND :: kind INTEGER, NONKIND :: m,n REAL(kind) : element(m,n) END TYPE Explicit values for the type parameters are normally specified when an object of the type is declared. For example, TYPE(matrix(KIND(0.0D0),10,20)) :: a declares a double-precision matrix of type of size 10 by 20. However, for a pointer or allocatable object, a colon may be used for a nonkind to indicate a deferred value; the actual value is determined when the object is allocated or pointer assigned. For a dummy argument, an asterisk may be used to indicate an assumed value; the actual value is taken from the actual argument. The keyword syntax of procedure calls may be used: TYPE(matrix(KIND(0.0),m=10,n=20)) :: a and the same syntax is used for declaring components of another derived type. For enquiries about the values of type parameters, the syntax of component selection is provided: a%kind, a%m and of course this syntax must not be used to alter the value of a parameter, say by appearing on the left of an assignment statement. This syntax is also available for enquiring about a type parameter of an object of intrinsic type. 2.2 Procedure pointers A pointer or pointer component may be a procedure pointer. It may have an explicit or implicit interface and its association with a target is as for a dummy procedure. As for a dummy procedure, its interface is neither generic nor elemental. The statement PROCEDURE (abstract-interface-name), POINTER :: p => NULL() declares p to be a procedure pointer initialised as null and with the explicit interface of abstract-interface-name, which may be the name of an interface block or a procedure with an explicit interface. As for data pointers, procedure pointers are either uninitialized or initialized to null. The statement PROCEDURE ( ), POINTER :: p declares p to be an uninitialized pointer with an implicit interface. It may be associated with a subroutine or a function. The statement PROCEDURE (TYPE(matrix(KIND(0.0D0),m=10,n=20))), POINTER :: p is similar but specifies that the pointer may be associated only with a function whose result is of the given type. A function may have a procedure pointer result. Pointer assignment takes the form proc-pointer => proc-target where proc-pointer is the name of a pointer or the designator of a pointer component such as a%p and proc-target is the name of a procedure or a reference to a function whose result is a procedure pointer. 2.3 Finalization A derived type may have 'final' subroutines bound to it. Their purpose is to perform clean-up operations such as the deallocation of pointer components when an object of the type ceases to exist. Each final subroutine is a module procedure with a single argument of the derived type to which will be passed an object that is about to cease to exist. The usual rules of argument association apply, so the object has the type and kind type parameters of the dummy argument and has the same rank unless the subroutine is elemental. The dummy argument is required not to have INTENT(OUT) and its array shape and nonkind type parameters are required to be assumed. An example of the syntax for declaring module subroutines to be final is TYPE T : ! Component declarations CONTAINS FINAL :: finish1, finish2 END TYPE T A derived type is finalizable if it has any final subroutines or if it has a component that is of a type that is finalizable but is neither a pointer nor allocatable. A nonpointer data object is finalizable if its type is finalizable. When such an object ceases to exist, a finalization subroutine is called for it if there is one with the right kind type parameters and rank; failing this, an elemental one with the right kind type parameters is called. Next, each finalizable component is finalized; if any is an array, each finalizable component of each element is finalized separately. 2.4 Procedures bound by name to a type A procedure may be bound to a type and accessed by component selection syntax from a scalar object of the type rather as if it were a procedure component with a fixed value. An example of the syntax is TYPE T : ! Component declarations CONTAINS PROCEDURE :: proc => my_proc PROCEDURE :: proc2 END TYPE T which binds my_proc with the name proc and proc2 with its own name. Each procedure must be a module procedure or an external procedure with an explicit interface. If a is of type T, an example of a type-bound call is CALL a%proc(x,y) Several such procedures may be accessed by a single generic name. The PROCEDURE statement is replaced by a GENERIC statement such as GENERIC :: gen => proc1, proc2, proc3 The usual rules about disambiguating procedure calls apply to all the procedures accessible through a single generic binding name. 2.5 The PASS attribute A procedure that is accessed as a component or by being bound by name may be given access to the scalar object through which it is invoked by specifying the PASS attribute: PROCEDURE, PASS, POINTER :: p PROCEDURE, PASS(arg) :: proc2 By default, the first dummy argument is the passed-object dummy argument; alternatively, the name of a dummy argument may be given. It must be a scalar argument of the type, must not be a pointer, must not be allocatable, and all its nonkind type parameters must be assumed. When the procedure is invoked through an object, this dummy argument becomes associated with the object. The specific procedures of a generic binding may be declared within the generic statement to be with or without the pass attribute and the position in the argument list of the passed-on argument can vary, for example GENERIC, PASS :: gen => proc1, proc2 GENERIC, PASS(arg) :: gen => proc3 This significantly complicates the rules (Section 16.2.3 of the draft standard) on the required difference between two procedures with the same generic name. I will not explain the rules here. 2.6 Procedures bound to a type as operators A procedure may be bound to a type as an operator or a defined assignment. In this case, the procedure is accessible wherever the type is accessible. The syntax is through GENERIC statements in the contained part of a type declaration: GENERIC :: OPERATOR(+) => plus1, plus2, plus3 GENERIC :: ASSIGNMENT(=) => assign1, assign2 There is no restriction on the types of the arguments, although one expects that one is likely to be of the type to which it is bound. The usual rules about disambiguating procedure calls apply to all the procedures accessible in a scoping unit through a single operator. 2.7 Type extension A derived type may be defined as extensible: TYPE, EXTENSIBLE :: matrix(kind,n) INTEGER, KIND :: kind INTEGER, NONKIND :: n REAL(kind) : element(n,n) END TYPE and then extended: TYPE, EXTENDS(matrix) :: factored_matrix LOGICAL :: factored=.FALSE. REAL(matrix%kind) : factors(matrix%n,matrix%n) END TYPE An extended type is extensible, too, so the term 'parent type' is used for the type from which an extension is made. All the type parameters, components, and bound procedures of the parent type are normally inherited by the extended type and they are known by the same names. For example, TYPE(factored_matrix(kind(0.0),10)) :: f declares a real factored matrix of order 10. The values of its type parameters are given by f%kind and f%n. The inherited component may be referenced as f%element. In addition, the extended type has the parameters, components, and bound procedures that are declared in its own definition. Here, we have the additional components f%factored and f%factors. The extended type also has a component, called the parent component, whose type and type parameters are those of its parent type and whose name is the name of the parent type. Here, the parent component was needed in the type definition. The inherited parameters, components, and bound procedures may be accessed directly, f%n and f%element, or through the parent component, f%matrix%n and f%matrix%element. The parent component and may be given a default initial value in the TYPE statement: TYPE, EXTENDS(matrix=matrix(kind(0.0),10)(0.0)) :: factored_matrix This overrides any default initialisation defined for the parent type's components. There is an ordering of the nonparent components that is needed in structure constructors and for input-output. It consists of the inherited components in the order of the parent type, followed by the new components. In a structure constructor, values may be given for a parent component or for the inherited components. No component may be explicitly specified more than once and any component that does not have a default value must be specified exactly once. A specific procedure bound by name is permitted to have the name and attributes of a procedure bound to the parent, apart from the type of the PASS argument, if any. It must be not PRIVATE if the parent's binding is PUBLIC. In this case, it overrides the procedure bound to the parent type. Similarly, a procedure bound as a specific within a generic may be overridden if it is given the same generic name or operator and would have been overridden had it been bound as a specific. Such overridding may be prohibited in the parent type: PROCEDURE, NON_OVERRIDABLE :: proc2 GENERIC, PASS, NON_OVERRIDABLE :: gen => proc1, proc2 A further possibility is that the binding may be deferred: PROCEDURE (proc) :: proc2 => null() GENERIC (genr) :: gen => null() Here proc and genr are the names of specific and generic interfaces for which there are no actual procedures (yet). Now overridding is required, though it may be deferred again. 2.8 Polymorphic entities A polymorphic entity is declared to be of a certain type by using the CLASS keyword in place of the TYPE keyword and is able to take this type or any of its extensions during execution. The type at a particular point of the execution is called the dynamic type. The feature allows code to be written for objects of a given type and used later for objects of this type and of any extension of it. An entity is said to be 'type compatible' with entities of the same declared type or of any declared type that is an extension of its declared type. Intrinsic assignment is extended; the left-hand side variable is not permitted to be polymorphic, but the right-hand side may have any dynamic type with which the left-hand side is type compatible. Access is permitted directly to type parameters, components, and bound procedures for the declared type only. However, intrinsic assignment provides indirect access to them. Another way is through the SELECT TYPE construct: CLASS (matrix(kind(0.0),10)) :: f : SELECT TYPE ff => f TYPE IS (matrix) : ! Block of statements TYPE IS (factored_matrix) : ! Block of statements END SELECT The first block is executed if the dynamic type of f is matrix and the second block is executed if it is factored_matrix. In the second block, we may use the associated name ff to access the extensions thus: ff%factored, ff%factor. This construct is described in detail in section 2.9. An object may be declared with the CLASS(*) specifier and is then 'unlimited polymorphic'. It is not type compatible with any other CLASS(*) object, but is compatible with all entities of extensible type. 2.9 ASSOCIATE and SELECT TYPE constructs To be written. 3. MISCELLANEOUS ENHANCEMENTS 3.1 Structure constructors The value list of a structure constructor may use the syntax of an actual argument list with keywords that are component names. Components that were given default values in the type definition may be omitted. Of course, no component may be given an explicit value more than once and explicit values override default values. If the type has parameters, these must be specified: a = TYPE(matrix(KIND(0.0),m=10,n=20)) (element = 0.0) 3.2 The allocate statement The allocatable attribute is no longer restricted to arrays and a source variable may be specified to provide values for deferred nonkind type parameters and an initial value for the object itself. For example, TYPE(matrix(KIND(0.0D0),m=:,n=:)),ALLOCATABLE :: b, c ALLOCATE(b,SOURCE=a) ALLOCATE(c,SOURCE=a) allocates the scalar objects b and c to be 10 x 20 matrices with the value of a. With source present, the allocate statement allocates just one object. The value is assigned by the rules for intrinsic assignment; in particular, the rules of array conformability apply so that the source variable is limited to being a scalar or an array of the same shape as the arrays being allocated. Alternatively, the nonkind type parameters may be specified by a type declaration within the allocate statement: ALLOCATE(TYPE(matrix(KIND(0.0D0),m=10,n=20)) :: b,c) If this feature is used in an allocate statement, initialisation from a source variable is not available. One or other must be used if the type has any deferred type parameters. If either is used, each allocatable object in the list must have the same non-deferred type parameters as the source variable or the type declaration. The allocate statement may also specify the dynamic type of a polymorphic object: ALLOCATE(TYPE(factored_matrix(kind(0.0),10)) :: b,c) ALLOCATE(d,SOURCE=a) ! d takes its dynamic type from a Each allocated object must be type compatible with the type specified type. An ALLOCATE or DEALLOCATE statement may optionally contain an ERRMSG= specifier that identifies a default character scalar variable. If an error condition occurs during execution of the statement, the processor assigns an explanatory message to the variable. If no such condition occurs, the value of the variable is not changed. 3.3 More control of access from a module More detailed control of access from a module is possible. The individual components of a derived type may be declared PUBLIC or PRIVATE: TYPE, EXTENDS(PRIVATE::person) :: s_person ! Parent component is private CHARACTER(:), ALLOCATABLE, PUBLIC :: name INTEGER, PRIVATE :: age The bindings to a type may be declared PUBLIC or PRIVATE: PROCEDURE, PUBLIC, PASS, POINTER :: p GENERIC, PUBLIC, PASS :: gen => proc1, proc2 GENERIC, PRIVATE :: OPERATOR(+) => plus1, plus2, plus3 Note, however, that a final subroutine is always public. The PROTECTED attribute imposes limitations on the usage of a module entity. The PROTECTED statement has the syntax PROTECTED [ :: ] entity-name-list and it may be specified in a type declaration statement such as REAL, PROTECTED :: a(10) If it is not a pointer, the protected entity is definable only within the module in which it is declared. If a pointer, its association status may change only within the module in which it is declared. If an object has the PROTECTED attribute, all of its subobjects have the PROTECTED attribute. 3.4 Pointer assignment Pointer assignment for arrays has been extended to allow lower bounds to be specified: p(0:,0:) => a As for dummy arrays, the lower bounds may be specification expressions. Remapping of the elements of a rank-one array is permitted: p(1:m,1:2*m) => a(1:2*m*m) The mapping is in array-element order and the target array must be large enough. The bounds may be specification expressions. If the target of a pointer assignment is polymorphic, the pointer must he polymorphic and type compatible with it. It takes the dynamic type of the target. Nonkind type parameters of the pointer may be deferred (declared with a colon). Pointer assignment gives these the values of the corresponding parameters of the target. All its other type parameters must have the same values as the corresponding type parameters of the target (but the target may have additional type parameters). 3.5 The VOLATILE attribute The VOLATILE attribute has been introduced for a data object to indicate that its value might change by means not specified in the standard, for example, by another program executing in parallel. Like the ASYNCHRONOUS attribute, whether an object has the VOLATILE attribute may varying between scoping units. If an object has the VOLATILE attribute, all of its subobjects also have the attribute. The effect is that the compiler is required to reference and define the memory that can change by other means rather than rely on values in cache or other temporary memory. 3.6 The IMPORT statement The IMPORT statement has the syntax IMPORT [[ :: ] import-name-list ] and is allowed only in an interface body. It specifies that all entities in the host scoping unit, or those named, are accessible by host association. 3.7 Access to the computing environment The concept of a module being intrinsic was introduced as part of the exception handling technical report (Reid 2001). A new intrisic module is ISO_FORTRAN_ENV. It contains the following constants INPUT_UNIT is a default integer scalar holding the unit identified by an asterisk in a READ statement. OUTPUT_UNIT is a default integer scalar holding the unit identified by an asterisk in a WRITE statement. ERROR_UNIT is a default integer scalar holding the unit used for the purpose of error reporting. THE VALUE may be the same as that of OUTPUT_UNIT. IOSTAT_END is a default integer scalar holding the value that is assigned to the IOSTAT= variable if an end-of-file condition occurs during execution of an input/output statement and no error condition occurs. This value is negative. IOSTAT_EOR is a default integer scalar holding the value that is assigned to the IOSTAT= variable if an end-of-record condition occurs during execution of an input/output statement and no end-of-file or error condition occurs. This value is negative. In addition, the following intrinsic procedures have been added. Note that they are ordinary intrinsics and are not part of the module ISO_FORTRAN_ENV. COMMAND_ARGUMENT_COUNT () is an inquiry function that returns a default integer scalar. The value is equal to the number of command arguments available. If there are no command arguments available or if the processor does not support command arguments, the value is 0. If the processor has a concept of a command name, the command name does not count as one of the command arguments. CALL GET_COMMAND ([COMMAND,LENGTH, STATUS]) returns entire command by which the program was invoked in the following optional INTENT(OUT) arguments COMMAND is a default character scalar. It is assigned the entire command by which the program was invoked. If the command cannot be determined, it is assigned all blanks. LENGTH is a default integer scalar. It is assigned the significant length of the command by which the program was invoked. This may include trailing blanks if the processor allows commands with significant trailing blanks. If the command length cannot be determined, 0 is assigned. STATUS is a default integer scalar. It is assigned the value -1 if the COMMAND argument is present and has a length less than the significant length of the command. It is assigned a processor-dependent positive value if the command retrieval fails. Otherwise, 0 is assigned. CALL GET_COMMAND_ARGUMENT (NUMBER [, VALUE, LENGTH, STATUS]) returns a command argument. NUMBER is a default integer INTENT(IN) scalar. It identifies the required command argument. Useful values are those between 0 and COMMAND_ARGUMENT_COUNT (). Other values are allowed, but will result in error status return (see below). Command argument 0 is the command name by which the program was invoked if the processor has such a concept. VALUE is a default character INTENT(OUT) scalar. It is assigned the value of the command argument specified by NUMBER. If the command argument value cannot be determined, VALUE is assigned all blanks. LENGTH is a default integer INTENT(OUT) scalar. It is assigned the significant length of the command argument specified by NUMBER. This may include trailing blanks if the processor allows command arguments with significant trailing blanks. If the command argument length cannot be determined, a length of 0 is assigned. STATUS is a default integer INTENT(OUT) scalar. It is assigned the value -1 if the VALUE argument is present and has a length less than the significant length of the command argument specified by NUMBER. It is assigned a processor-dependent positive value if the argument retrieval fails. Otherwise, it is assigned the value 0. CALL GET ENVIRONMENT_VARIABLE (NAME [, VALUE, LENGTH, STATUS, TRIM NAME]) Obtain the value of an environment variable NAME is a default character INTENT(IN) scalar. The interpretation of case is processor dependent VALUE is a default character INTENT(OUT) scalar. It is assigned the value of the environment variable specified by NAME. VALUE is assigned all blanks if the environment variable does not exist or does not have a value or if the processor does not support environment variables. LENGTH is a default integer INTENT(OUT) scalar. If the specified environment variable exists and has a value, LENGTH is set to the length of that value. Otherwise LENGTH is set to 0. STATUS is a default integer INTENT(OUT) scalar. If the environment variable exists and either has no value or its value is successfully assigned to VALUE, STATUS is set to zero. STATUS is set to -1 if the VALUE argument is present and has a length less than the significant length of the environment variable. It is assigned the value 1 if the specified environment variable does not exist, or 2 if the processor does not support environment variables. Processor-dependent values greater than 2 may be returned for other error conditions. TRIM_NAME is a logical INTENT(IN) scalar. If it is present with the value false then trailing blanks in NAME are considered significant if the processor supports trailing blanks in environment variable names. Otherwise trailing blanks in NAME are not considered part of the environment variable's name. 3.8 Support for international character sets Fortran 95 introduced the possibility of multi-byte character sets, which provides a foundation for supporting ISO 10646 (2000). This is a standard for 4-byte characters, which is wide enough to support all the world's languages. A new intrinsic function has been introduced: SELECTED_CHAR_KIND(NAME) NAME is a scalar of type default character. If it has the value DEFAULT, the kind value for default character type is returned. If it has the value ASCII and ASCII (1991) is supported, its kind value is returned. If it has the value ISO_10646 and ISO 10646 (2000) is supported, its kind value is returned. If another character kind is supported, its name may be given and its kind will be returned. In all other cases, the value -1 is returned. 3.9. Number of continuation lines Up to 99 continuation lines are allowed. 3.10. Binary, octal and hex constants A binary, octal and hex constant is permitted for a principal argument in a call of the intrinsic function INT, REAL, CMPLX, or DBLE, that is, not for the optional argument that specifies the kind of the result. For INT, it is treated as if it were an integer constant of the kind with the largest decimal exponent range supported by the processor. For the others, it is treated as having the value that a variable of the same type and kind type parameters as the result would have if its value was the bit pattern specified. The interpretation of the value of the bit pattern is processor dependent. If the kind is not specified, it is the default kind. 3.11 Array constructor syntax Square brackets are permitted as an alternative to '(/' and '/)' for delimiters for array constructors. 3.12 Specification and initialization expressions The rules on what may appear in a specification or an initialization expression have been relaxed, but remain very complicated. I will not attempt to summarize them here. For details, see 7.1.6 and 7.1.7 of J3 (2002). 4. INPUT/OUTPUT ENHANCEMENTS 4.1 Derived type input/output It may be arranged that when a derived-type object is encountered in an input- output list, a Fortran subroutine is called. This reads some characters from the file and constructs a value of the derived type or accepts a value of the derived type and writes some characters to the file. For formatted io, the DT edit descriptor passes a character string and an integer array to control the action. An example is DT 'linked-list' (10, -4, 2) The character string may be omitted, in which case a string of length zero is passed. The bracketed list of integers may be omitted, in which case an array of length zero is passed. The subroutines must be bound to the type as generic bindings (see sections 2.4 and 2.6) of the form GENERIC :: READ(FORMATTED) => r1, r2 GENERIC :: READ(UNFORMATTED) => r3, r4, r5 GENERIC :: WRITE(FORMATTED) => w1 GENERIC :: WRITE(UNFORMATTED) => w2, w3 which makes them accessible wherever the type is accessible. The form of such a subroutine depends on whether it is for formatted or unformatted input or output: SUBROUTINE formatted_io (unit,dtv,iotype,v_list,iostat,iomsg) SUBROUTINE unformatted_io(unit,dtv, iostat,iomsg) unit is a scalar of intent(in) and type default integer. Its value is the unit on which input-output is taking place or zero if on an internal file. dtv is a scalar of the derived type. It must be polymorphic if and only if the object in the io list is polymorphic. Any nonkind type parameters must be assumed. For output, it is of intent(in) and holds the value to be written. For input, it is of intent(out) and must be set to the value read. iotype is a scalar of intent(in) and type CHARACTER(*). Its value is the character string from the edit descriptor. v_list is a rank-one assumed-shape array of type default integer. Its value comes from the bracketed list of the edit descriptor. iostat is a scalar of intent(out) and type default integer. If an error condition occurs, it must be given a positive value. Otherwise, if an end-of-file or end-of-record condition occurs it must be given the value IOSTAT_END or IOSTAT_EOR (see 3.7), respectively. Otherwise, it must be given the value zero. iomsg is a scalar of intent(inout) and type CHARACTER(*). If iostat is given a nonzero value, iomsg must be set to an explanatory message. Otherwise, it must not be altered. Input-output within the subroutine to external files is limited to the specified unit and in the specified direction. However, io to an internal file is permitted. The file position on entry is treated as a left tab limit and there is no record termination on return. 4.2 Asynchronous input/output Input/output may be asynchronous, that is, other statements may execute while an i/o statement is in execution. It is permitted only for external files opened with ASYNCHRONOUS = 'YES' in the OPEN statement and is indicated by ASYNCHRONOUS = 'YES' in the READ or WRITE statement. Execution of an asynchronous i/o statement initiates a 'pending' i/o operation, which is terminated by a wait operation for the file. This may be performed by an explicit wait statement WAIT(10) or implicitly by an INQUIRE, CLOSE, or file positioning statement for the file. The compiler is permitted to treat each asynchronous i/o statement as an ordinary i/o statement; this, after all, is just the limiting case of the i/o being fast. The compiler is, of course, required to recognize all the new syntax. Further asynchronous i/o statements may be executed for the file before the wait statement is reached. The i/o statements are performed in the same order as if they were synchronous. An execution of an asynchronous i/o statement may be identified by a scalar integer variable in an ID= specifier. Successful execution of the statement causes the variable to be given a processor-dependent value which can be passed to a subsequent WAIT or INQUIRE statement as a scalar integer variable in an ID= specifier. A wait statement may have END=, EOR=, ERR= and IOSTAT= specifiers. These have the same meanings as for an i/o statement and refer to situations that occur while the i/o operation is pending. If there is an ID= specifier, too, only the identified pending operation is terminated and the other specifiers refer to this; otherwise, all pending operations for the file are terminated in turn. An INQUIRE statement is permitted to have a PENDING= specifier for a scalar default logical variable. If an ID= specifier is present, the variable is given the value true if the particular i/o operation is still pending and false otherwise. If no ID= specifier is present, the variable is given the value true if all i/o operations for the unit are still pending and false otherwise. In the 'false' case, wait operations are performed for the file or files. Wait operations are not performed in the 'true' case, even if some of the i/o operations are complete. A file positioning statement (BACKSPACE, ENDFILE, REWIND) performs wait operations for all pending i/o operations for the file. Asynchronous i/o is not permitted in conjunction with user-defined derived type i/o (section 4.1). A variable in a scoping unit is said to be an 'affector' of a pending i/o operation if any part of it is associated with any part of an item in the i/o list, namelist, or SIZE= specifier. While an i/o operation is pending, an affector is not permitted to be redefined, become undefined, or have its pointer association status changed. While an input i/o operation is pending, an affector is also not permitted to be referenced or associated with a dummy argument with the VALUE attribute (section 5.6). The ASYNCHRONOUS attribute has been introduced to warn the compiler that some code motions across wait statements might lead to incorrect results. If a variable appears in an executable statement or a specification expression in a scoping unit and any statement of the scoping unit is executed while the variable is an affector, it must have the ASYNCHRONOUS attribute in the scoping unit. A variable is automatically given the attribute if it or a subobject of it is an item in the i/o list, namelist, or SIZE= specifier of an asynchronous i/o statement. A named variable may be declared with this attribute: INTEGER, ASYNCHRONOUS :: int_array(10) or given it by the ASYNCHRONOUS statement ASYNCHRONOUS :: int_array, another This statement may be used to give the attribute to a variable that is accessed by use or host association. All subobjects of a variable with the ASYNCHRONOUS attribute have the attribute. An actual argument that is a data object and the corresponding dummy argument must both have the ASYNCHRONOUS attribute or both not have it. 4.3 FLUSH statement Execution of a FLUSH statement for an external file causes data written to it to be available to other processes, or causes data placed in it by means other than Fortran to be available to a read statement. The syntax is just like that of the file positioning statements. 4.4 IOMSG specifier Any of the IO statements that have ERR= and IOSTAT= specifiers are permitted to have an IOMSG= specifier. This identifies a scalar variable of type default character into which the processor places a message if an error, end-of-file, or end-of-record condition occurs during execution of the statement. 4.5 Stream access input/output Stream access is a new method of accessing an external file. It is established by specifying ACCESS='STREAM' on the OPEN statement may be formatted or unformatted. The file is positioned by 'file storage units', normally bytes, starting at position 1. The current position may be determined from a scalar integer variable is a POS= specifier of an INQUIRE statement for the unit. A required position may be indicated in a READ or WRITE statement by the POS= specifier which accepts a scalar integer expression. For formatted i/o, the value must be 1 or one previously returned in an INQUIRE statement for the file. In the absence of a POS= specifier, the file position is left unchanged. The standard permits a processor to prohibit the use of POS= for particular files that do not have the properties necessary to support random positioning or its use for forward positioning if the file does not have the properties necessary to support this. 4.6 ROUND= specifier Rounding during formatted i/o may be controlled by the ROUND= specifier on the OPEN statement, which takes one of the values UP, DOWN, ZERO, NEAREST, COMPATIBLE, or PROCESSOR_DEFINED. It may be overridden by a ROUND= specifier in a READ or WRITE statement with one of these values. The meanings are obvious except for the difference between NEAREST and COMPATIBLE. Both refer to a closest representable value. If two are equidistant, which is taken is processor dependent for NEAREST and the value away from zero for COMPATIBLE. The rounding mode may also be temporarily changed within a READ or WRITE statement by the RU, RD, RZ, RN, RC, and RP edit descriptors. 4.7 DECIMAL= specifier The character that separates the parts of a decimal number in formatted i/o may be controlled by the DECIMAL= specifier on the OPEN statement, which takes one of the values COMMA or POINT. It may be overridden by a DECIMAL= specifier in a READ or WRITE statement with one of these values. The meanings are obvious. The mode may also be tempoprarily changed within a READ or WRITE statement by the DC and DP edit descriptors. 4.8 SIGN= specifier The SIGN= specifier has been added to the OPEN statement. It can take the value SUPPRESS, PLUS, or PROCESSOR_DEFINED and controls the optional plus characters in formatted numeric output. It may be overridden by a ROUND= specifier in a WRITE statement with one of these values. The rounding mode may also be tempoprarily changed within a WRITE statement by the SS, SP, and S edit descriptors, which were part of Fortran 95. 5 INTEROPERABILITY WITH C 5.1 Introduction Fortran 2000 provides a standardized mechanism for interoperating with C. Clearly, any entity involved must be such that equivalent declarations of it may be made in the two languages. This is enforced within the Fortran program by requiring all such entities to be 'interoperable'. We will explain in turn what this requires for types, variables, and procedures. They are all requirements on the syntax so that the compiler knows at compile time whether an entity is interoperable. We finish with two examples. 5.2 Interoperability of intrinsic types There is an intrinsic module called ISO_C_BINDING that contains named constants holding kind type parameter values for intrinsic types. Their names are shown in Table 1, together with the corresponding C types. The processor is not required to support all of them. Lack of support is indicated with a negative value. Table 1. Interoperability between Fortran and C types Type Named constant C type or types INTEGER C_INT int C_SHORT short int C_LONG long int C_LONG_LONG long long int C_SIGNED_CHAR signed char, unsigned char C_SIZE_T size_t C_INT_LEAST8_T int_least8_t C_INT_LEAST16_T int_least16_t C_INT_LEAST32_T int_least32_t C_INT_LEAST64_T int_least64_t C_INT_FAST8_T int_fast8_t C_INT_FAST16_T int_fast16_t C_INT_FAST32_T int_fast32_t C_INT_FAST64_T int_fast64_t C_INTMAX_T c intmax_t REAL C_FLOAT float C_DOUBLE double C_LONG_DOUBLE long double COMPLEX C_FLOAT_COMPLEX float _Complex C_DOUBLE_COMPLEX double _Complex C_LONG_DOUBLE_COMPLEX long double _Complex LOGICAL C_BOOL _Bool CHARACTER C_CHAR char For character, interoperability also requires that the length type parameter be omitted or be specified by an initialization expression whose value is one. The following named constants (with the obvious meanings) are provided: C_NULL_CHAR, C_ALERT, C_BACKSPACE, C_FORM_FEED, C_NEW_LINE, C_CARRIAGE_RETURN, C_HORIZONTAL_TAB, C_VERTICAL_TAB. 5.3 Interoperability with C pointers For interoperating with C pointers (which are just addresses), the module contains a derived type C_PTR that is interoperable with any C pointer type and a named constant C_NULL_PTR with the value NULL of C. The module also contains the following procedures: C_LOC (X) is an inquiry function that returns the C address of X. X is permitted to be a procedure that is interoperable (see para. 5) or a variable that has the TARGET attribute and is either interoperable or is an allocated allocatable variable that has interoperable type and type parameters. C_ASSOCIATED (C_PTR1[, C_PTR2]) is an inquiry function that returns a default logical scalar. It has the value false if C_PTR1 is a C null pointer or if C_PTR2 is present with a different value; otherwise, it has the value true. C_F_POINTER (CPTR, FPTR [, SHAPE])) is a subroutine with arguments CPTR is a scalar of type C_PTR with intent IN. Its value is the C address of an entity that is is interoperable with variables of the type and type parameters of FPTR. It shall not be the C address of a Fortran variable that does not have the TARGET attribute. FPTR is a pointer that becomes pointer associated with the target of CPTR. If it is an array, its shape is specified by SHAPE. SHAPE (optional) is a rank-one array of type integer with intent IN. If present, its size is equal to the rank of FPTR. If FPTR is an array, it must be present. This is the mechanism for passing dynamic arrays between the languages. A Fortran pointer or assumed-shape array cannot be passed to C since its elements need not be contiguous in memory. However, an allocated allocatable array may be passed to C and an array allocated in C may be associated with a Fortran pointer. 5.4 Interoperability of derived types For a derived type to be interoperable, it must be given the BIND attribute explicitly: TYPE, BIND(C) :: MYTYPE : END TYPE MYTYPE Each component must have interoperable type and type parameters, must not be a pointer, and must not be allocatable. This allows Fortran and C types to correspond, for example typedef struct { int m, n; float r; } myctype is interoperable with USE ISO_C_BINDING TYPE, BIND(C) :: MYFTYPE INTEGER(C_INT) :: I, J REAL(C_FLOAT) :: S END TYPE MYFTYPE The name of the type and the names of the components are not significant for interoperability. No Fortran type is interoperable with a C union type, struct type that contains a bit field, or struct type that contains a flexible array member. 5.5 Interoperability of variables A scalar Fortran variable is interoperable if it is of interoperable type and type parameters, and is neither a pointer nor allocatable. An array Fortran variable is interoperable if it is of interoperable type and type parameters, and is of explicit shape or assumed size. It interoperates with a C array of the same type types parameters and shape, but with reversal of subscripts. For example, a Fortran array declared as INTEGER :: A(18, 3:7, *) is interoperable with a C array declared as int b[][5][18] 5.6 Interoperability of procedures For the sake of interoperability, a new attribute, VALUE, has been introduced for scalar dummy arguments. When the procedure is called, a copy of the actual argument is made. The dummy argument is a variable that may be altered during execution of the procedure, but on return no copy back takes place. If the type is character, the character length must be one. A Fortran procedure is interoperable if it has an explicit interface and is declared with the BIND attribute: FUNCTION FUNC(I, J, K, L, M), BIND(C) All the dummy arguments must be interoperable. For a function, the result must be scalar and interoperable. The procedure has a 'binding label', which has global scope and is the name by which it is known to the C processor. By default, it is the lower-case version of the Fortran name. For example, the above function has the binding label 'func'. Another binding label may be specied: FUNCTION FUNC(I, J, K, L, M), BIND(C, NAME='C_Func') Such a procedure corresponds to a C function prototype with the same binding label. For a function, the result must be interoperable. For a subroutine, the prototype must have a void result. A dummy argument with the VALUE attribute must correspond to formal parameter of the prototype that is not of a pointer type. A dummy argument without the VALUE attribute must correspond to formal parameter of the prototype that is of a pointer type. 5.7 Interoperability of global data An interoperable module variable or a common block with interoperable members may be given the BIND attribute: USE ISO_C_BINDING INTEGER(C_INT), BIND(C) :: C_EXTERN INTEGER(C_LONG) :: C2 BIND(C, NAME='myVariable') :: C2 COMMON /COM/ R, S REAL(C_FLOAT) :: R, S BIND(C) :: /COM/ It has a binding label defined by the same rules as for procedures and interoperate with a C variable of a corresponding struct type. 5.8 Example of Fortran calling C C Function Prototype: int C_Library_Function(void* sendbuf, int sendcount, int *recvcounts) Fortran Module: MODULE FTN_C INTERFACE INTEGER (C_INT) FUNCTION C_LIBRARY_FUNCTION & (SENDBUF, SENDCOUNT, RECVCOUNTS), & BIND(C, NAME='C_Library_Function') USE ISO_C_BINDING IMPLICIT NONE TYPE (C_PTR), VALUE :: SENDBUF INTEGER (C_INT), VALUE :: SENDCOUNT TYPE (C_PTR), VALUE :: RECVCOUNTS END FUNCTION C_LIBRARY_FUNCTION END INTERFACE END MODULE FTN_C Fortran Calling Sequence: USE ISO_C_BINDING, ONLY: C_INT, C_FLOAT, C_LOC USE FTN_C ... REAL (C_FLOAT), TARGET :: SEND(100) INTEGER (C_INT) :: SENDCOUNT INTEGER (C_INT), ALLOCATABLE, TARGET :: RECVCOUNTS(:) ... ALLOCATE( RECVCOUNTS(100) ) ... CALL C_LIBRARY_FUNCTION(C_LOC(SEND), SENDCOUNT, & C_LOC(RECVCOUNTS)) ... 5.9 Example of C calling Fortran Fortran Code: SUBROUTINE SIMULATION(ALPHA, BETA, GAMMA, DELTA, ARRAYS), BIND(C) USE ISO_C_BINDING IMPLICIT NONE INTEGER (C_LONG), VALUE :: ALPHA REAL (C_DOUBLE), INTENT(INOUT) :: BETA INTEGER (C_LONG), INTENT(OUT) :: GAMMA REAL (C_DOUBLE),DIMENSION(*),INTENT(IN) :: DELTA TYPE, BIND(C) :: PASS INTEGER (C_INT) :: LENC, LENF TYPE (C_PTR) :: C, F END TYPE PASS TYPE (PASS), INTENT(INOUT) :: ARRAYS REAL (C_FLOAT), ALLOCATABLE, TARGET, SAVE :: ETA(:) REAL (C_FLOAT), POINTER :: C_ARRAY(:) ... ! Associate C_ARRAY with an array allocated in C CALL C_F_POINTER (ARRAYS%C, C_ARRAY, (/ARRAYS%LENC/) ) ... ! Allocate an array and make it available in C ARRAYS%LENF = 100 ALLOCATE (ETA(ARRAYS%LENF)) ARRAYS%F = C_LOC(ETA) ... END SUBROUTINE SIMULATION C Struct Declaration struct pass {int lenc, lenf; float* f, *c} C Function Prototype: void simulation(long alpha, double *beta, long *gamma, double delta[], struct pass *arrays) C Calling Sequence: simulation(alpha, &beta, &gamma, delta, &arrays); REFERENCES ASCII (1991) ISO/IEC 646:1991, Information technology - ISO 7-bit coded character set for information interchange. ISO, Geneva. Cohen, Malcolm (ed.) (2001) ISO/IEC TR 15581(E) Technical Report: Information technology - Programming languages - Fortran - Enhanced data type facilities (second edition). ISO, Geneva. ISO 10646 (2000) ISO/IEC 10646-1:2000, Information technology - Universal multiple-octet coded character set (UCS) - Part 1: Architecture and basic multilingual plane. ISO, Geneva. J3 (2002). J3/02-007R3 - Draft Fortran standard. Also known as ISO/IEC JTC1/SC22/WG5 N14xx. Available as PS, PDF, or text from ftp://ftp.j3-fortran.org/j3/doc/standing/007/ Metcalf, Michael and Reid, John (1999). Fortran 90/95 explained (second edition). Oxford University Press. Reid, John (ed.) (2001) ISO/IEC TR 15580(E) Technical Report: Information technology - Programming languages - Fortran - Floating-point exception handling (second edition). ISO, Geneva.