Section 4: Data types Fortran provides an abstract means whereby data may be categorized without relying on a particular physical representation. This abstract means is the concept of data type. An intrinsic type is one that is defined by the language. The intrinsic types are integer, real, complex, character, and logical. A derived type is one that is derived by composition of other types. Objects of derived type have components. Each component is of an intrinsic type or of a derived type. A type definition (4.5.1) is required to supply the name of the type and the names and types of its components. For example, if the complex type were not intrinsic but had to be derived, a type definition would be required to supply the name "complex" and declare two components, each of type real. In addition, arithmetic operators would have to be defined. A derived type may be used only where its definition is accessible (4.5.1). An intrinsic type is always accessible. 4.1 The concept of data type A data type has a name, a set of valid values, a means to denote such values (constants), and a set of operations to manipulate the values. NOTE 4.2 For example, the logical data type has a set of two values, denoted by the lexical tokens .TRUE. and .FALSE., which are manipulated by logical operations. An example of a less restricted data type is the integer data type. This data type has a processor-dependent set of integer numeric values, each of which is denoted by an optional sign followed by a string of digits, and which may be manipulated by integer arithmetic operations and relational operations. 4.1.1 Set of values For each data type, there is a set of valid values. The set of valid values may be completely determined, as is the case for logical, or may be determined by a processor-dependent method, as is the case for integer and real. For complex or derived types, the set of valid values consists of the set of all the combinations of the values of the individual components. 4.1.2 Constants For each of the intrinsic data types, the syntax for literal constants of that type is specified in this standard. These literal constants are described in 4.4 for each intrinsic type. The syntax for denoting a value indicates both the type and the particular value. A constant value may be given a name (5.1.2.1, 5.2.9). A structure constructor (4.5.8) may be used to construct a constant value of derived type from an appropriate sequence of initialization expressions (7.1.7). Such a constant value is considered to be a scalar even though the value may have components that are arrays. 4.1.3 Operations For each of the intrinsic data types, a set of operations and corresponding operators are defined intrinsically. These are described in Section 7. The intrinsic set may be augmented with operations and operators defined by functions with the OPERATOR interface (12.3.2.1). Operator definitions are described in Sections 7 and 12. For derived types, the only intrinsic operation is assignment with agreement of type and type parameters. All other operations shall be defined by the program (4.5.9). 4.2 Type parameters A data type may be parameterized. In this case, the set of values, the syntax for denoting the values, and the set of operations on the values of the type depend on the values of the parameters. The intrinsic data types are all parameterized. Derived types may be defined to be parameterized. A type parameter is either a kind type parameter or a nonkind type parameter. A kind type parameter may be used in initialization and specification expressions within the derived type definition (4.5.1) for the type; it participates in generic resolution (14.1.2.3). Each of the intrinsic types has a kind type parameter named KIND, which is used to distinguish multiple representations of the intrinsic type. By design, the value of a kind type parameter is known at compile time. Some parameterizations that involve multiple representation forms need to be distinguished at compile time for practical implementation and performance. Examples include the multiple precisions of the intrinsic real type and the possible multiple character sets of the intrinsic character type. A type parameter of a derived type may be specified to be a kind type parameter in order to allow generic resolution based on the parameter; that is to allow a single generic to include two specific procedures that have interfaces distinguished only by the value of a kind type parameter of a dummy argument. Generics are designed to be resolvable at compile time. A nonkind type parameter may be used in specification expressions within the derived type definition for the type, but it may not be used in initialization expressions. The intrinsic character type has a nonkind type parameter named LEN, which is the length of the string. A typical use of a nonkind type parameter is to specify a size. An example is the length of an entity of intrinsic character type. A type parameter value may be specified with a type specification (5.1, 4.5.7). R401 type-param-value is scalar-int-expr or * or : Constraint: The type-param-value for a kind type parameter shall be an initialization expression. Constraint: A colon may be used as a type-param-value only in the declaration of an entity or component that has the POINTER or ALLOCATABLE attribute. A deferred type parameter is a nonkind type parameter whose value can change during execution of the program. A colon as a type-param-value specifies a deferred type parameter. The values of the deferred type parameters of an object are determined by sucessful execution of an ALLOCATE statement (6.3.1), execution of a derived-type intrinsic assignment statement (7.5.1.2), execution of a pointer assignment statement (7.5.2), or by argument association (12.4.1.2). An assumed type parameter is a nonkind type parameter for a dummy argument that assumes the type parameter value from the corresponding actual argument. An asterisk as a type-param-value specifies an assumed type parameter. 4.3 Relationship of types and values to objects The name of a data type serves as a type specifier and may be used to declare objects of that type. A declaration specifies the type of a named object. A data object may be declared explicitly or implicitly. Data objects may have attributes in addition to their types. Section 5 describes the way in which a data object is declared and how its type and other attributes are specified. Scalar data of any intrinsic or derived type may be shaped in a rectangular pattern to compose an array of the same type and type parameters. An array object has a type and type parameters just as a scalar object does. A scalar object of derived type is referred to as a structure. Variables may be objects or subobjects. The data type and type parameters of a variable determine which values that variable may take. Assignment provides one means of defining or redefining the value of a variable of any type. Assignment is defined intrinsically for all types when the type, type parameters, and shape of both the variable and the value to be assigned to it are identical. Assignment between objects of certain differing intrinsic types, type parameters, and shapes is described in Section 7. A subroutine (7.5.1.3) and an ASSIGNMENT interface block (12.3.2.1) define an assignment that is not defined intrinsically or redefine an intrinsic derived-type assignment. For example, assignment of a real value to an integer variable is defined intrinsically. The data type of a variable determines the operations that may be used to manipulate the variable. 4.4 Intrinsic data types The intrinsic data types are: numeric types: integer, real, and complex nonnumeric types: character and logical The numeric types are provided for numerical computation. The normal operations of arithmetic, addition (+), subtraction (-), multiplication (*), division (/), exponentiation (**), negation (unary - ), and identity (unary +), are defined intrinsically for this set of types. 4.4.1 Integer type The set of values for the integer type is a subset of the mathematical integers. A processor shall provide one or more representation methods that define sets of values for data of type integer. Each such method is characterized by a value for a type parameter called the kind type parameter. The kind type parameter of a representation method is returned by the intrinsic inquiry function KIND (13.17.57). The decimal exponent range of a representation method is returned by the intrinsic function RANGE (13.17.92). The intrinsic function SELECTED_INT_KIND (13.17.101) returns a kind value based on a specified decimal range requirement. The integer type includes a zero value, which is considered neither negative nor positive. The value of a signed integer zero is the same as the value of an unsigned integer zero. The type specifier for the integer type uses the keyword INTEGER (R503). If the kind type parameter is not specified, the default kind value is KIND (0) and the data entity is of type default integer. Any integer value may be represented as a signed-int-literal-constant. R402 signed-digit-string is [ sign ] digit-string R403 digit-string is digit [ digit ] ... R404 signed-int-literal-constant is [ sign ] int-literal-constant R405 int-literal-constant is digit-string [ _ kind-param ] R406 kind-param is digit-string or scalar-int-constant-name R407 sign is + or - Constraint: The value of kind-param shall be nonnegative. Constraint: The value of kind-param shall specify a representation method that exists on the processor. The optional kind type parameter following digit-string specifies the kind type parameter of the integer constant; if it is not present, the constant is of type default integer. An integer constant is interpreted as a decimal value. Examples of signed integer literal constants are: 473 +56 -101 21_2 21_SHORT 1976354279568241_8 where SHORT is a scalar integer named constant. R408 boz-literal-constant is binary-constant or octal-constant or hex-constant R409 binary-constant is B ' digit [ digit ] ... ' or B " digit [ digit ] ... " Constraint: digit shall have one of the values 0 or 1. R410 octal-constant is O ' digit [ digit ] ... ' or O " digit [ digit ] ... " Constraint: digit shall have one of the values 0 through 7. R411 hex-constant is Z ' hex-digit [ hex-digit ] ... ' or Z " hex-digit [ hex-digit ] ... " R412 hex-digit is digit or A or B or C or D or E or F In these constants, the binary, octal, and hexadecimal digits are interpreted according to their respective number systems. The hex-digits A through F may be represented by their lower-case equivalents. A boz-literal-constant is treated as if the constant were an int-literal-constant with a kind-param that specifies the representation method with the largest decimal exponent range supported by the processor. 4.4.2 Real type The real type has values that approximate the mathematical real numbers. A processor shall provide two or more approximation methods that define sets of values for data of type real. Each such method has a representation method and is characterized by a value for a type parameter called the kind type parameter. The kind type parameter of an approximation method is returned by the intrinsic inquiry function KIND (13.17.57). The decimal precision and decimal exponent range of an approximation method are returned by the intrinsic functions PRECISION (13.17.86) and RANGE (13.17.92). The intrinsic function SELECTED_REAL_KIND (13.17.102) returns a kind value based on specified precision and decimal range requirements. See C.1.2 for remarks concerning selection of approximation methods. The real type includes a zero value. Processors that distinguish between positive and negative zeros shall treat them as equivalent (1) in all relational operations, (2) as actual arguments to intrinsic procedures other than SIGN, and (3) as the scalar-numeric-expr in an arithmetic IF. On a processor that can distinguish between 0.0 and -0.0, ( X .GE. 0.0 ) evaluates to true if X = 0.0 or if X = -0.0, ( X .LT. 0.0 ) evaluates to false for X = -0.0, and IF (X) 1,2,3 causes a transfer of control to the branch target statement with the statement label "2" for both X = 0.0 and X = -0.0. In order to distinguish between 0.0 and -0.0, a program should use the SIGN function. SIGN(1.0,X) will return -1.0 if X < 0.0 or if the processor distinguishes between 0.0 and -0.0 and X has the value -0.0. Historically some systems had a distinct negative zero value that presented some difficulties. Fortran standards were specified such that these difficulties had to be handled by the processor and not the user. The IEEE standard introduced a negative zero with specific properties. For example when the exact result of an operation is negative but rounding produces a zero, the value specified by the IEEE standard is -0.0. This standard includes adjustments intended to permit IEEE-compliant processors to behave in accordance with that standard without violating this standard. The type specifier for the real type uses the keyword REAL and the type specifier for the double precision real type uses the keyword DOUBLE PRECISION (R503). If the type keyword REAL is specified and the kind type parameter is not specified, the default kind value is KIND (0.0) and the data entity is of type default real. If the type keyword DOUBLE PRECISION is specified, a kind type parameter shall not be specified and the data entity is of type double precision real. The kind type parameter of such an entity has the value KIND (0.0D0). The decimal precision of the double precision real approximation method shall be greater than that of the default real method. R413 signed-real-literal-constant is [ sign ] real-literal-constant R414 real-literal-constant is significand [ exponent-letter exponent ] [ _ kind-param ] or digit-string exponent-letter exponent [ _ kind-param ] R415 significand is digit-string . [ digit-string ] or . digit-string R416 exponent-letter is E or D R417 exponent is signed-digit-string Constraint: If both kind-param and exponent-letter are present, exponent-letter shall be E. Constraint: The value of kind-param shall specify an approximation method that exists on the processor. A real literal constant without a kind type parameter is a default real constant if it is without an exponent part or has exponent letter E, and is a double precision real constant if it has exponent letter D. A real literal constant written with a kind type parameter is a real constant with the specified kind type parameter. The exponent represents the power of ten scaling to be applied to the significand or digit string. The meaning of these constants is as in decimal scientific notation. The significand may be written with more digits than a processor will use to approximate the value of the constant. Examples of signed real literal constants are: -12.78 +1.6E3 2.1 -16.E4_8 0.45E-4 10.93E7_QUAD .123 3E4 where QUAD is a scalar integer named constant. 4.4.3 Complex type The complex type has values that approximate the mathematical complex numbers. The values of a complex type are ordered pairs of real values. The first real value is called the real part, and the second real value is called the imaginary part. Each approximation method used to represent data entities of type real shall be available for both the real and imaginary parts of a data entity of type complex. A kind type parameter may be specified for a complex entity and selects for both parts the real approximation method characterized by this kind type parameter value. The kind type parameter of an approximation method is returned by the intrinsic inquiry function KIND (13.17.57). The type specifier for the complex type uses the keyword COMPLEX (R503). There is no keyword for double precision complex. If the type keyword COMPLEX is specified and the kind type parameter is not specified, the default kind value is the same as that for default real, the type of both parts is default real, and the data entity is of type default complex. R418 complex-literal-constant is ( real-part , imag-part ) R419 real-part is signed-int-literal-constant or signed-real-literal-constant or named-constant R420 imag-part is signed-int-literal-constant or signed-real-literal-constant or named-constant Constraint: Each named constant in a complex literal constant shall be of type integer or real. If the real part and the imaginary part of a complex literal constant are both real, the kind type parameter value of the complex literal constant is the kind type parameter value of the part with the greater decimal precision; if the precisions are the same, it is the kind type parameter value of one of the parts as determined by the processor. If a part has a kind type parameter value different from that of the complex literal constant, the part is converted to the approximation method of the complex literal constant. If both the real and imaginary parts are integer, they are converted to the default real approximation method and the constant is of type default complex. If only one of the parts is an integer, it is converted to the approximation method selected for the part that is real and the kind type parameter value of the complex literal constant is that of the part that is real. Examples of complex literal constants are: (1.0, -1.0) (3, 3.1E6) (4.0_4, 3.6E7_8) ( 0., PI) where PI is a previously declared named real constant. 4.4.4 Character type The character type has a set of values composed of character strings. A character string is a sequence of characters, numbered from left to right 1, 2, 3, ... up to the number of characters in the string. The number of characters in the string is called the length of the string. The length is a type parameter; its value is greater than or equal to zero. Strings of different lengths are all of type character. A processor shall provide one or more representation methods that define sets of values for data of type character. Each such method is characterized by a value for a type parameter called the kind type parameter. The kind type parameter of a representation method is returned by the intrinsic inquiry function KIND (13.17.57). The intrinsic function SELECTED_CHAR_KIND (13.17.100) returns a kind value based on the name of a character type. Any character of a particular representation method representable in the processor may occur in a character string of that representation method. The character set defined by ISO/IEC 646:1991 is referred to as the ASCII character set or the ASCII character data type. The character set defined by ISO/IEC 10646-1:1993 UCS-4 is referred to as the ISO 10646 character set of the ISO 10646 character data type. The type specifier for the character type uses the keyword CHARACTER (R503). If the kind type parameter is not specified, the default kind value is KIND ('A') and the data entity is of type default character. A character literal constant is written as a sequence of characters, delimited by either apostrophes or quotation marks. R421 char-literal-constant is [ kind-param _ ] ' [ rep-char ] ... ' or [ kind-param _ ] " [ rep-char ] ... " Constraint: The value of kind-param shall specify a representation method that exists on the processor. The optional kind type parameter preceding the leading delimiter specifies the kind type parameter of the character constant; if it is not present, the constant is of type default character. For the type character with kind kind-param, if present, and for type default character otherwise, a representable character, rep-char, is one of the following: (1) Any character in the processor-dependent character set in fixed source form. A processor may restrict the occurrence of some or all of the control characters. (2) Any graphic character in the processor-dependent character set in free source form. FORTRAN 77 allowed any character to occur in a character context. This standard allows a source program to contain characters of more than one kind. Some processors may identify characters of nondefault kinds by control characters (called "escape" or "shift" characters). It is difficult, if not impossible, to process, edit, and print files where some instances of control characters have their intended meaning and some instances may not. Almost all control characters have uses or effects that effectively preclude their use in character contexts and this is why free source form allows only graphic characters as representable characters. Nevertheless, for compatibility with FORTRAN 77, control characters remain permitted in principle in fixed source form. The delimiting apostrophes or quotation marks are not part of the value of the character literal constant. An apostrophe character within a character constant delimited by apostrophes is represented by two consecutive apostrophes (without intervening blanks); in this case, the two apostrophes are counted as one character. Similarly, a quotation mark character within a character constant delimited by quotation marks is represented by two consecutive quotation marks (without intervening blanks) and the two quotation marks are counted as one character. A zero-length character literal constant is represented by two consecutive apostrophes (without intervening blanks) or two consecutive quotation marks (without intervening blanks) outside of a character context. The intrinsic operation concatenation (//) is defined between two data entities of type character (7.2.2) with the same kind type parameter. Examples of character literal constants are: "DON'T" 'DON''T' both of which have the value DON'T and '' which has the zero-length character string as its value. Examples of nondefault character literal constants, where the processor supports the corresponding character sets, are: BOLD_FACE_'This is in bold face ' ITALICS_'This is in italics ' where BOLD_FACE and ITALICS are named constants whose values are the kind type parameters for bold face and italic characters, respectively. 4.4.4.1 Collating sequence Each implementation defines a collating sequence for the character set of each kind of character. A collating sequence is a one-to-one mapping of the characters into the nonnegative integers such that each character corresponds to a different nonnegative integer. The intrinsic functions CHAR (13.17.19) and ICHAR (13.17.50) provide conversions between the characters and the integers according to this mapping. For example: ICHAR ( 'X' ) returns the integer value of the character 'X' according to the collating sequence of the processor. For the default character type, the only constraints on the collating sequence are the following: (1) ICHAR ('A') < ICHAR ('B') < ... < ICHAR ('Z') for the twenty-six letters. (2) ICHAR ('0') < ICHAR ('1') < ... < ICHAR ('9') for the ten digits. (3) ICHAR (' ') < ICHAR ('0') < ICHAR ('9') < ICHAR ('A') or ICHAR (' ') < ICHAR ('A') < ICHAR ('Z') < ICHAR ('0'). (4) ICHAR ('a') < ICHAR ('b') < ... < ICHAR ('z'). (5) ICHAR (' ') < ICHAR ('0') < ICHAR ('9') < ICHAR ('a') or ICHAR (' ') < ICHAR ('a') < ICHAR ('z') < ICHAR ('0'). Except for blank, there are no constraints on the location of the special characters and underscore in the collating sequence, nor is there any specified collating sequence relationship between the upper-case and lower-case letters. The sequence of numerical codes defined by the ASCII standard is called the ASCII collating sequence in this standard. The intrinsic functions ACHAR (13.17.2) and IACHAR (13.17.45) provide conversions between these characters and the integers of the ASCII collating sequence. The intrinsic functions LGT, LGE, LLE, and LLT (13.17.61-13.17.64) provide comparisons between strings based on the ASCII collating sequence. International portability is guaranteed if the set of characters used is limited to the letters, digits, underscore, and special characters. 4.4.5 Logical type The logical type has two values which represent true and false. A processor shall provide one or more representation methods for data of type logical. Each such method is characterized by a value for a type parameter called the kind type parameter. The kind type parameter of a representation method is returned by the intrinsic inquiry function KIND (13.17.57). The type specifier for the logical type uses the keyword LOGICAL (R503). If the kind type parameter is not specified, the default kind value is KIND (.FALSE.) and the data entity is of type default logical. R422 logical-literal-constant is .TRUE. [ _ kind-param ] or .FALSE. [ _ kind-param ] Constraint: The value of kind-param shall specify a representation method that exists on the processor. The optional kind type parameter following the trailing delimiter specifies the kind type parameter of the logical constant; if it is not present, the constant is of type default logical. The intrinsic operations defined for data entities of logical type are: negation (.NOT.), conjunction (.AND.), inclusive disjunction (.OR.), logical equivalence (.EQV.), and logical nonequivalence (.NEQV.) as described in 7.2.4. There is also a set of intrinsically defined relational operators that compare the values of data entities of other types and yield a value of type default logical. These operations are described in 7.2.3. 4.5 Derived types Additional data types may be derived from the intrinsic data types. A type definition is required to define the name of the type and the names and attributes of its components. The type specifier for a derived type uses the keyword TYPE followed by the name of the type in parentheses (R503). A derived type may be parameterized by multiple type parameters, each of which is defined to be either a kind or nonkind type parameter. There is no concept of a default value for a type parameter of a derived type; it is required to explicitly specify, assume, or defer the values of all type parameters of a derived-type entity. The direct components of a derived type are (1) The components of that type and (2) For any component that is of derived type and is not allocatable or a pointer, the direct components of that derived type. Unresolved issue 5 The glossary entries for direct and ultimate components are out of date. Also it has been suggested that the term "direct component" might now be superfluous, replacable by the "subobject" concept. Ultimately, a derived type is resolved into ultimate components that are either of intrinsic type or are allocatable or pointers. See C.1.1 for an example By default, no storage sequence is implied by the order of the component definitions. However, if the definition of a derived type contains a SEQUENCE statement, the type is a sequence type. The order of the component definitions in a sequence type specifies a storage sequence for objects of that type. If the definition of a derived type specifies BIND(C), the storage sequence is that required by the companion processor (2.5.10) for an entity of a C struct type with which an entity of the derived type is interoperable (16.2.4). 4.5.1 Derived-type definition R423 derived-type-def is derived-type-stmt [ type-param-def-stmt ] ... [ data-component-part ] [ type-bound-procedure-part ] end-type-stmt R424 derived-type-stmt is TYPE [ [ , type-attr-spec-list ] :: ] type-name n n[ ( type-param-name-list ) ] R425 type-attr-spec is access-spec or EXTENSIBLE or EXTENDS ( [ access-spec :: ] parent-type-name n n [ = initialization-expr ] ) or BIND (C) Constraint: An access-spec (5.1.2.2) or a PRIVATE statement within the type definition is permitted only if the type definition is within the specification part of a module. This constraint applies throughout the type definition, including in component-def- stmts and in the type-bound-procedure-part. Constraint: A derived type type-name shall not be the same as the name of any intrinsic type defined in this standard. Constraint: A derived type shall not have both the EXTENSIBLE and the EXTENDS attributes. Constraint: A parent-type-name shall be the name of an accessible extensible type (4.5.3) or of an accessible type alias for an extensible type. Constraint: If EXTENDS or EXTENSIBLE is present, neither BIND(C) nor SEQUENCE shall be present. Constraint: If BIND(C) is present, neither SEQUENCE, a type-bound-procedure-part, nor a type- param-name-list shall be present. Constraint: If BIND(C) is present, any derived type specified in a component definition shall be defined with the BIND(C) type-attr-spec. Constraint: If BIND(C) is present, neither POINTER nor ALLOCATABLE shall be specified for any component definition in the type. Constraint: If BIND(C) is present, there shall be no proc-component-def-stmts in the type definition. R426 type-param-def-stmt is INTEGER [ kind-selector ] [ [, type-param-attr-spec ] :: ] n n type-param-name-list Constraint: A type-param-name in a type-param-def-stmt in a derived-type-def shall be one of the type-param-names in the derived-type-stmt of that derived-type-def. R427 type-param-attr-spec is KIND or NONKIND R428 data-component-part is [ private-sequence-stmt ] ... [ component-def-stmt ] ... R429 private-sequence-stmt is PRIVATE or SEQUENCE Constraint: The same private-sequence-stmt shall not appear more than once in a given derived-type-def. Constraint: If SEQUENCE is present, all derived types specified in component definitions shall be sequence types. Constraint: If SEQUENCE is present, a type-bound-procedure-part shall not be present. R430 component-def-stmt is data-component-def-stmt or proc-component-def-stmt R431 data-component-def-stmt is declaration-type-spec [ [ , component-attr-spec-list ] :: ] n n component-decl-list R432 component-attr-spec is POINTER or DIMENSION ( component-array-spec ) or ALLOCATABLE or access-spec R433 component-decl is component-name [ ( component-array-spec ) ] n n [ * char-length ] [ component-initialization ] R434 component-array-spec is explicit-shape-spec-list or deferred-shape-spec-list R435 component-initialization is = initialization-expr or => NULL ( ) Constraint: No component-attr-spec shall appear more than once in a given component-def-stmt. Constraint: A component declared with the CLASS keyword (5.1.1.8) shall have the ALLOCATABLE or POINTER attribute. Constraint: If the POINTER attribute is not specified for a component, a declaration-type-spec in the component-def-stmt shall specify an intrinsic type or a previously defined derived type. Constraint: If the POINTER attribute is specified for a component, a declaration-type-spec in the component-def-stmt shall specify an intrinsic type or any accessible derived type including the type being defined. Constraint: If the POINTER or ALLOCATABLE attribute is specified, each component-array-spec shall be a deferred-shape-spec-list. Constraint: If neither the POINTER attribute nor the ALLOCATABLE attribute is specified, each component-array-spec shall be an explicit-shape-spec-list. Constraint: Each bound in the explicit-shape-spec shall not contain references to specification functions or any object designators other than named constants or subobjects thereof. Constraint: POINTER and ALLOCATABLE shall not both appear in the same component-def-stmt. Constraint: The * char-length option is permitted only if the type specified is character. Constraint: Each type-param-value within a component-def-stmt shall either be a colon or a specification expression that does not contain references to specification functions or any object designators other than named constants or subobjects thereof. Constraint: If component-initialization appears, a double-colon separator shall appear before the component-decl-list. The double-colon separator in a component-def-stmt is required only if a component-attr-spec or component-initialization is specified; otherwise, it is optional. Constraint: If => appears in component-initialization, the POINTER attribute shall appear in the component-attr-spec-list. If = appears in component-initialization, the POINTER attribute shall not appear in the component-attr-spec-list. Constraint: If the ALLOCATABLE attribute appears in the component-attr-spec-list, component- initialization shall not appear. R436 proc-component-def-stmt is PROCEDURE ( [ proc-interface ] ) , n n proc-component-attr-spec-list :: proc-decl-list See 12.3.2.3 for definitions of proc-interface and proc-decl. R437 proc-component-attr-spec is POINTER or PASS_OBJ or access-spec Constraint: The same proc-component-attr-spec shall not appear more than once in a given proc- component-def-stmt. Constraint: The proc-component-attr-spec-list shall include the POINTER attribute. Constraint: If PASS_OBJ is specified, the procedure component shall have an explicit interface that has a scalar, nonpointer, nonallocatable dummy variable of type type-name. The first such dummy argument shall be polymorphic if and only if type-name is extensible. Constraint: All of the nonkind type parameters of a passed-object dummy argument shall be assumed. R438 type-bound-procedure-part is contains-stmt [ binding-private-stmt ] proc-binding-construct [ proc-binding-construct ] ... R439 binding-private-stmt is PRIVATE R440 proc-binding-construct is proc-binding-stmt or select-kind-construct R441 proc-binding-stmt is PROCEDURE [ ( proc-interface-name ) ] n n [ [ , binding-attr-list ] :: ] binding-name [ => binding ] or GENERIC [ ( proc-interface-name ) ] n n [, NON_OVERRIDABLE ] :: n n dtio-generic-spec => binding-list or FINAL [ :: ] final-subroutine-name-list Unresolved issue 287 It seems anomalous that the GENERIC form of proc-binding-stmt is allowed (indeed required) for dtio, but is not allowed for other bindings. I suspect there might be intent to change this in the future. But for now, it looks anomalous and almost bound to provoke questions and confusions. It is an inconsistency with no obvious (to me, and I suspect to most users) reason. Constraint: If => binding appears, the double-colon separator shall appear. Constraint: If PROCEDURE is specified, the proc-interface-name shall be specified if and only if the binding is to NULL() and is not overriding (4.5.3.2) an inherited (4.5.3.1) binding. Constraint: If GENERIC is specified, the proc-interface-name shall be specified if and only if the binding is to NULL(). Unresolved issue 288 My initial thought about the above two constraints on proc-binding-stmts was to wonder why they were different. Doesn't the first one (without the condition on PROCEDURE being specified) cover both cases? As written this implies that the GENERIC form requires the proc- interface-name when a NULL is overriding, even though the PROCEDURE form prohibits it there. I suppose that might indeed be the intent, though it's confusing. Is a user actually supposed to remember all these distinctions or are we assuming that he will be coding with the standard document open? I then noticed a difference that isn't there and needs to be. The GENERIC form does not have a unique binding that can be referred to with a definite article. It has a binding-list. Constraint: The proc-interface-name shall be the name of an accessible abstract explicit interface. If proc-interface-name and PASS_OBJ are both specified, the interface shall have a scalar, nonpointer, nonallocatable dummy argument of type type-name. The first such dummy argument shall be polymorphic if and only if type-name is extensible. Constraint: If dtio-generic-spec is specified, the interface of each binding shall be as specified in 9.5.4.4.3. The type specified for the dtv argument shall be the type being defined. Constraint: A final-subroutine-name shall be the name of a module procedure with exactly one dummy argument. That argument shall be nonoptional and shall be a nonpointer, nonallocatable, nonpolymorphic variable of the derived type being defined. All nonkind type parameters of the dummy argument shall be assumed. The dummy argument shall not be INTENT(OUT). Constraint: A final-subroutine-name shall not be one that previously had been specified as a final subroutine in that type. Constraint: A final subroutine shall not have a dummy argument of the same kind type parameters and rank as the dummy argument of another final subroutine of that derived type. If => binding is not specified, it is as though it were specified with a procedure name the same as the binding name. R442 binding-attr is PASS_OBJ or NON_OVERRIDABLE or access-spec Constraint: The same binding-attr shall not appear more than once in a given binding-attr-list. R443 binding is procedure-name or NULL() Constraint: The procedure-name shall be the name of an accessible module procedure or external procedure that has an explicit interface. If PASS_OBJ is specified, the procedure shall have a scalar, nonpointer, nonallocatable dummy argument of type type-name. The first such dummy argument shall be polymorphic if and only if type-name is extensible. Constraint: All of the nonkind type parameters of a passed-object dummy argument shall be assumed. Constraint: If several bindings are specified in a single dtio-generic-spec, their interfaces shall differ as specified in 14.1.2.3. Unresolved issue 289 The above constraint about multiple bindings in a dtio-generic-spec is likely to confuse people by being a lot more complicated than is needed. Unless I'm confused (quite possible), this constraint just means that the dtv arguments are required to have different kind type parameters. The constraint referencing 9.5.4.4.3 already tied down everything else pertinent, making most of 14.1.2.3 moot for this. And it's a strangely narrow constraint anyway. It constrains only against duplication in a single proc-binding-stmt, but allows the same duplication if we use two separate statements. Was it intended for the constraint to cover that case? I wouldn't interpret it as doing so as written. Same comment about the new constraint (last one) on dtio-generic-spec (R1208). It took me multiple readings to figure out what it was saying, which turned out to be pretty simple. Wht is there a constraint on the dtio-generic interface block when there is no corresponding constraint for the same issue in other generic blocks? If we are going to phrase the constraint this broadly, complete with subtle issues about disambiguation by keyword and position, then why don't we go ahead and apply it broadly? And the R1208 constraint is similarly and strangely narrow. It constraints against an interface body that conflicts with a generic binding, but doesn't constrain against two interface bodies conflicting. R444 select-kind-construct is select-kind-stmt [ case-stmt [ proc-binding-construct ] ... ] ... end-select-kind-stmt R445 select-kind-stmt is SELECT CASE ( scalar-initialization-expr ) Constraint: The scalar-initialization-expr shall be of type integer. R446 end-select-kind-stmt is END SELECT R447 end-type-stmt is END TYPE [ type-name ] Constraint: If END TYPE is followed by a type-name, the type-name shall be the same as that in the corresponding derived-type-stmt. NOTE 4.20 An example of a derived-type definition is: TYPE PERSON INTEGER AGE CHARACTER (LEN = 50) NAME END TYPE PERSON An example of declaring a variable CHAIRMAN of type PERSON is: TYPE (PERSON) :: CHAIRMAN 4.5.1.1 Derived-type parameters The derived type is parameterized if the derived-type-stmt has any type-param-names. Each type parameter is itself of type integer. This may be confirmed by a type-param-def-stmt. A type parameter is default integer unless its kind is explicitly specified in a type-param-def-stmt. A type parameter is either a kind type parameter or a nonkind type parameter (4.2). If it is a kind parameter it is said to have the KIND attribute. A type-param-attr-spec explicitly specifies whether a type parameter is kind or nonkind. The KIND attribute may also be implicitly conferred as described below. If a type parameter is not given the KIND attribute, either explicitly or implicitly, it is a nonkind type parameter. It is not required to explicitly specify a type parameter to be a nonkind parameter, but such specification is allowed. A type parameter may be used as a primary in a specification expression (7.1.6) in the derived-type- def. A kind type parameter may also be used as a primary in an initialization expression (7.1.7) in the derived-type-def. With the exception stated below, a type parameter is implicitly given the KIND attribute if it appears in the derived-type-def as a primary in an expression that is required to be an initialization expression. NOTE 4.21 In most cases, it is not necessary to explicitly declare anything about a type parameter; it is implicitly of type default integer and will implicitly get the KIND attribute if needed. For example, consider TYPE matrix(k, d) REAL(k) :: element(d,d) END TYPE Both k and d are default integer. The parameter k implicitly has the KIND attribute because it is used in a context that requires it to. The following example uses explicit type parameter declarations. TYPE humongous_matrix(k, d) INTEGER, KIND :: k INTEGER(selected_int_kind(12)), NONKIND :: d !-- Specify a nondefault kind for d. REAL(k) :: element(d,d) END TYPE In the following example, dim is explicitly declared to be a kind parameter, even though it is not required by anything shown here. This would allow generic overloading of procedures distinguished only by dim. TYPE general_point(dim) INTEGER, KIND :: dim REAL :: coordinates(dim) END TYPE If a derived type has a component that is a pointer to a (possibly different) derived type, the appearance of a type parameter of the containing type in an expression for a kind type parameter of the component implicitly declares it to be a kind type parameter of the containing type only if the type definition for the component preceded that of the containing type. This rule is to avoid indeterminacy caused by mutually recursive derived type definitions. For example TYPE type_1(a) INTEGER, KIND :: a !-- required because we don't yet know whether !-- type_2 has a kind type parameter. TYPE(type_2(a)), POINTER :: comp END TYPE TYPE type_2(b) !-- No explicit declaration of b needed here. TYPE(type_1(b)), POINTER :: comp END TYPE This is not at issue except with pointer components because a nonpointer component is required to be of a previously defined type. 4.5.1.2 Default initialization for components If initialization-expr appears for a nonpointer component, that component in any object of the type is initially defined (14.7.3) or becomes defined as specified in 14.7.5 with the value determined from initialization-expr. An initialization-expr in the EXTENDS type-attr-spec is for the parent component. The initialization-expr is evaluated in the scoping unit of the type definition. The evaluation rules are those that would be in effect for intrinsic assignment (7.5.1.5) if that component were a variable assigned the value of initialization-expr. If the component is of a type for which default initialization is specified for a component, the default initialization specified by initialization-expr overrides the default initialization specified for that component. When one initialization overrides another it is as if only the overriding initialization were specified (see Note 4.24). Explicit initialization in a type declaration statement (5.1) overrides default initialization (see Note 4.23). Unlike explicit initialization, default initialization does not imply that the object has the SAVE attribute. NOTE 4.23 It is not required that initialization be specified for each component of a derived type. For example: TYPE DATE INTEGER DAY CHARACTER (LEN = 5) MONTH INTEGER :: YEAR = 1994 ! Partial default initialization END TYPE DATE In the following example, the default initial value for the YEAR component of TODAY is overridden by explicit initialization in the type declaration statement: TYPE (DATE), PARAMETER :: TODAY = DATE (21, "Feb.", 1995) NOTE 4.24 The default initial value of a component of derived type may be overridden by default initialization specified in the definition of the type. TYPE SINGLE_SCORE TYPE(DATE) :: PLAY_DAY = TODAY INTEGER SCORE TYPE(SINGLE_SCORE), POINTER :: NEXT => NULL ( ) END TYPE SINGLE_SCORE TYPE(SINGLE_SCORE) SETUP The PLAY_DAY component of SETUP receives its initial value from TODAY overriding the initialization for the YEAR component. NOTE 4.25 Arrays of structures may be declared with elements that are partially or totally initialized by default. For example: TYPE MEMBER CHARACTER (LEN = 20) NAME INTEGER :: TEAM_NO, HANDICAP = 0 TYPE (SINGLE_SCORE), POINTER :: HISTORY => NULL ( ) END TYPE MEMBER TYPE (MEMBER) LEAGUE (36) ! Array of partially initialized elements TYPE (MEMBER) :: ORGANIZER=MEMBER ("I. Manage",1,5,NULL ( )) ORGANIZER is explicitly initialized, overriding the default initialization for an object of type MEMBER. Allocated objects may also be initialized partially or totally. For example: ALLOCATE (ORGANIZER % HISTORY) ! A partially initialized object of type ! SINGLE_SCORE is created. 4.5.1.3 Array components A component is an array if its component-decl contains a component-array-spec or its component-def-stmt contains the DIMENSION attribute. If the component-decl contains a component-array-spec, it specifies the array rank, and if the array is explicit shape, the array bounds; otherwise, the component-array-spec in the DIMENSION attribute specifies the array rank, and if the array is explicit shape, the array bounds. NOTE 4.26 A type definition may have a component that is an array. For example: TYPE LINE REAL, DIMENSION (2, 2) :: COORD ! ! COORD(:,1) has the value of (/X1, Y1/) ! COORD(:,2) has the value of (/X2, Y2/) REAL :: WIDTH ! Line width in centimeters INTEGER :: PATTERN ! 1 for solid, 2 for dash, 3 for dot END TYPE LINE An example of declaring a variable LINE_SEGMENT to be of the type LINE is: TYPE (LINE) :: LINE_SEGMENT The scalar variable LINE_SEGMENT has a component that is an array. In this case, the array is a subobject of a scalar. The double colon in the definition for COORD is required; the double colon in the definition for WIDTH and PATTERN is optional. A derived type may have a component that is allocatable. For example: TYPE STACK INTEGER :: INDEX INTEGER, ALLOCATABLE :: CONTENTS (:) END TYPE STACK For each scalar variable of type STACK, the shape of the component CONTENTS is determined by execution of an ALLOCATE statement or assignment statement, or by argument association. Default initialization of an array component may be specified by an initialization expression consisting of an array constructor (4.8), or of a single scalar that becomes the value of each array element. 4.5.1.4 Pointer components A component is a pointer if its component-attr-spec-list contains the POINTER attribute. Pointers have an association status of associated, disassociated, or undefined. If no default initialization is specified, the initial status is undefined. To specify that the default initial status of a pointer component is to be disassociated, the pointer assignment symbol (=>) shall be followed by a reference to the intrinsic function NULL ( ) with no argument. No mechanism is provided to specify a default initial status of associated. NOTE 4.29 A derived type may have a component that is a pointer. For example: TYPE REFERENCE INTEGER :: VOLUME, YEAR, PAGE CHARACTER (LEN = 50) :: TITLE CHARACTER, DIMENSION (:), POINTER :: ABSTRACT END TYPE REFERENCE Any object of type REFERENCE will have the four components VOLUME, YEAR, PAGE, and TITLE, plus a pointer to an array of characters holding ABSTRACT. The size of this target array will be determined by the length of the abstract. The space for the target may be allocated (6.3.1) or the pointer component may be associated with a target in a pointer assignment statement (7.5.2). NOTE 4.30 A pointer component of a derived type may have as its target an object of that derived type. The type definition may specify that in objects declared to be of this type, such a pointer is default initialized to disassociated. For example: TYPE NODE INTEGER :: VALUE TYPE (NODE), POINTER :: NEXT_NODE => NULL ( ) END TYPE A type such as this may be used to construct linked lists of objects of type NODE. See C.1.4 for an example. 4.5.1.5 Type-bound procedures Each binding in a proc-binding-construct specifies a type-bound procedure. NOTE 4.31 An example of a type and a type-bound procedure is: TYPE, EXTENSIBLE :: POINT REAL :: X, Y CONTAINS PROCEDURE, PASS_OBJ :: LENGTH => POINT_LENGTH END TYPE POINT ... and in the module-subprogram-part of the same module: REAL FUNCTION POINT_LENGTH (A, B) CLASS (POINT), INTENT (IN) :: A, B POINT_LENGTH = SQRT ( (A%X - B%X)**2 + (A%Y - B%Y)**2 ) END FUNCTION POINT_LENGTH A binding that specifies the NULL intrinsic instead of a procedure name is said to be deferred. If a type has a deferred procedure binding then any extension of the type shall specify a procedure binding for each inherited deferred binding. This new binding may supply a specific procedure or may confirm that the binding is still deferred. It is permissible to override (4.5.3.2) an inherited binding with a deferred binding. 4.5.1.6 User-defined derived-type input/output bindings A binding with a dtio-generic-spec specifies a user-defined derived-type input/output binding. The use of the binding for each dtio-generic-spec is described in 9.5.4.4.3. The set of user-defined derived-type input/output bindings for a particular type and dtio-generic-spec, including those that are explicitly specified and those that are inherited (4.5.3.1) into that type and not overridden (4.5.3.2), defines a type-bound generic interface in exact analogy to generic procedure names. A binding may be to a procedure or may be deferred. If a deferred binding is selected for use during data transfer (14.1.2.4.3), an error condition occurs. 4.5.1.7 The passed-object dummy argument If PASS_OBJ is specified for a procedure pointer component or a type-bound procedure, the first dummy argument that has the same type as the derived type being defined is called the passed- object dummy argument. It affects type-bound procedure overriding (4.5.3.2) and argument association (12.4.1.1). Unresolved issue 291 What does it mean for the passed object dummy argument to "have the same type" as the type being defined? Consider that in many of the "interesting" cases the dummy argument will be polymorphic. IN fact, I can't come up with any way of using PASS_OBJ unless the dummy is polymorphic; should that perhaps be a requirement? 4.5.1.8 Accessibility By default, derived types defined in the specification part of a module are accessible (5.1.2.2, 5.2.3) in any scoping unit that accesses the module. This default may be changed to restrict the accessibility of such types to the host module itself. A particular type definition may be declared to be public or private regardless of the default accessibility declared for the module. In addition, a type may be accessible while some or all of its components are private. The accessibility of a derived type may be declared explicitly by an access-spec in its derived-type-stmt or in an access-stmt (5.2.3). The accessibility is the default if it is not declared explicitly. If a type definition is private, then the type name, and thus the structure constructor (4.5.8) for the type, is accessible only within the module containing the definition. The default accessibility for the components of a type is private if the data-component-part contains a PRIVATE statement, and public otherwise. The default acessibility for the procedure bindings of a type is private if the type-bound-procedure-part contains a PRIVATE statement, and public otherwise. The accessibility of a component is the default if it is not explicitly declared by an access-spec for that component. If a component is private, that component name is accessible only within the module containing the definition. Unresolved issue 284 The above material in 4.5.1.7 about accessibility of components is not correct for inherited components. I asked about this general question on the floor and was told that it was covered. On more leisurely study, I conclude that the coverage is inadequate. It is true that 4.5.3.1 says that inherited components retain their attributes. But hat just means we have two contradictory sections; having it right in one section isn't good enough. The above para doesn't allow for any exceptions. It won't work, by the way, to claim that the explicit declaration for the inherited component is in the declaration of the parent type - the inherited component might be using the default accessibility for the components of the parent type. Although it appears to me that we need to say something here about different treatment for inherited components, the following para on the parent component seems largely redundant. The parent component *DOES* seem to be covered by the para above this note - its accessibility is the default unless explicitly declared by an access-spec for the component. The only difference is in the syntax of where the access-spec goes. I guess that syntax needs to be mentioned somewhere, but I don't see that it merits repeating the rest of the para. This area may have suffered in coherence because of two different papers having edits in the same area - one that added new material, and another that attempted to re-ornagize the presentation of the old material. The accessibility of the parent component (4.5.3.1) may be explicitly specified by an access-spec within the EXTENDS type-attr-spec. Otherwise its accessibility is the same as the default accessibility for the additional components of the extended type. Type parameters are not components. They may be used in a derived-type-spec (4.5.7) anywhere that the type name is accessible. They may be used in a type-param-inquiry for any accessible data object of the type. The accessibility of a procedure binding is the default if it is not explicitly declared by an access- spec for that binding. A public type-bound procedure is accessible via any accessible object of the type. A private type-bound procedure is accessible only within the module containing the type definition. The accessibility of a type-bound procedure is not affected by a PRIVATE statement in the data-component-part; the accessibility of a data component is not affected by a PRIVATE statement in the type-bound-procedure-part. The accessibility of a type name is independent of the accessibility of the components of the type. It is possible to have all four combinations: a public name with a public component, a private name with a private component, a public name with a private component, and a private name with a public component. An example of a type with private components is: MODULE DEFINITIONS TYPE POINT PRIVATE REAL :: X, Y END TYPE POINT END MODULE DEFINITIONS Such a type definition is accessible in any scoping unit accessing the module via a USE statement; however, the components, X and Y, are accessible only within the module. A derived-type definition may have a component that is of a derived type. For example: TYPE TRIANGLE TYPE (POINT) :: A, B, C END TYPE TRIANGLE An example of declaring a variable T to be of type TRIANGLE is: TYPE (TRIANGLE) :: T An example of a private type is: TYPE, PRIVATE :: AUXILIARY LOGICAL :: DIAGNOSTIC CHARACTER (LEN = 20) :: MESSAGE END TYPE AUXILIARY Such a type would be accessible only within the module in which it is defined. The following example illustrates the use of an individual component access-spec to override the default accessibity: TYPE MIXED PRIVATE INTEGER :: I INTEGER, PUBLIC :: J END TYPE MIXED TYPE (MIXED) :: M The component M%J is accessible in any scoping unit where M is accessible; M%I is not. 4.5.1.9 Sequence type If the SEQUENCE statement is present, the type is a sequence type. If there are no type parameters and all of the ultimate components are of type default integer, default real, double precision real, default complex, or default logical and are not pointers or allocatable, the type is a numeric sequence type. If there are no type parameters and all of the ultimate components are of type default character and are not pointers or allocatable, the type is a character sequence type. An example of a numeric sequence type is: TYPE NUMERIC_SEQ SEQUENCE INTEGER :: INT_VAL REAL :: REAL_VAL LOGICAL :: LOG_VAL END TYPE NUMERIC_SEQ A structure resolves into a sequence of components. Unless the structure includes a SEQUENCE statement, the use of this terminology in no way implies that these components are stored in this, or any other, order. Nor is there any requirement that contiguous storage be used. The sequence merely refers to the fact that in writing the definitions there will necessarily be an order in which the components appear, and this will define a sequence of components. This order is of limited significance since a component of an object of derived type will always be accessed by a component name except in the following contexts: the sequence of expressions in a derived-type value constructor, the data values in namelist input data, and the inclusion of the structure in an input/output list of a formatted data transfer, where it is expanded to this sequence of components. Provided the processor adheres to the defined order in these cases, it is otherwise free to organize the storage of the components for any nonsequence structure in memory as best suited to the particular architecture. 4.5.1.10 Final subroutines The FINAL keyword specifies a list of final subroutines. These subroutines may be executed when an object of that type is finalized (4.5.10). Unresolved issue 300 "May" implies permission for the programmer to do something. It seems unlikely that this is the intended meaning here (4.5.1.10). I also doubt that more than one of them is executed for a single object. I am also surprised that we restrict finalization to data objects; I thought that the most important need for this feature was for entities other than objects. Perhaps our definition of "object" is bad and should be broader - I can't offhand recall why we define it so narrowly, and people keep forgetting the narrow definition and using the term more broadly. Perhaps it should be defined the way we keep wanting to use it. The "object" issue applies throughout the whole of 00-277r2; I'm not going to list each place. A derived type is finalizable if it has any final subroutines or if it has any nonpointer, nonallocatable component whose type is finalizable. An object is finalizable if its type is finalizable. Final subroutines are effectively always "accessible". They are called for object finalization regardless of the accessibility of the type, its other type-bound procedure bindings, or the subroutine name itself. Final subroutines are not inherited through type extension and cannot be overridden. The final subroutines of the parent type are called after calling any additional final subroutines of an extended type. 4.5.2 Determination of derived types A particular type name shall be defined at most once in a scoping unit. Derived-type definitions with the same type name may appear in different scoping units, in which case they may be independent and describe different derived types or they may describe the same type. Two data entities have the same type if they are declared with reference to the same derived-type definition. The definition may be accessed from a module or from a host scoping unit. Data entities in different scoping units also have the same type if they are declared with reference to different derived-type definitions that specify the same type name, all have the SEQUENCE property or all have the BIND(C) attribute, have no components with PRIVATE accessibility, and have type parameters and components that agree in order, name, and attributes. Otherwise, they are of different derived types. A data entity declared using a type with the SEQUENCE property or with the BIND(C) attribute is not of the same type as an entity of a type declared to be PRIVATE or which has any components that are PRIVATE. NOTE 4.42 An example of declaring two entities with reference to the same derived-type definition is: TYPE POINT REAL X, Y END TYPE POINT TYPE (POINT) :: X1 CALL SUB (X1) ... CONTAINS SUBROUTINE SUB (A) TYPE (POINT) :: A ... END SUBROUTINE SUB The definition of derived type POINT is known in subroutine SUB by host association. Because the declarations of X1 and A both reference the same derived-type definition, X1 and A have the same type. X1 and A also would have the same type if the derived-type definition were in a module and both SUB and its containing program unit accessed the module. An example of data entities in different scoping units having the same type is: PROGRAM PGM TYPE EMPLOYEE SEQUENCE INTEGER ID_NUMBER CHARACTER (50) NAME END TYPE EMPLOYEE TYPE (EMPLOYEE) PROGRAMMER CALL SUB (PROGRAMMER) ... END PROGRAM PGM SUBROUTINE SUB (POSITION) TYPE EMPLOYEE SEQUENCE INTEGER ID_NUMBER CHARACTER (50) NAME END TYPE EMPLOYEE TYPE (EMPLOYEE) POSITION ... END SUBROUTINE SUB The actual argument PROGRAMMER and the dummy argument POSITION have the same type because they are declared with reference to a derived-type definition with the same name, the SEQUENCE property, and components that agree in order, name, and attributes. Suppose the component name ID_NUMBER was ID_NUM in the subroutine. Because all the component names are not identical to the component names in derived type EMPLOYEE in the main program, the actual argument PROGRAMMER would not be of the same type as the dummy argument POSITION. Thus, the program would not be standard conforming. The requirement that the two types have the same name applies to the type-names of the respective derived-type-stmts, not to type-alias names or to local names introduced via renaming in USE statements. 4.5.3 Extensible types A derived type that has the EXTENSIBLE or EXTENDS attribute is an extensible type. A type that has the EXTENSIBLE attribute is a base type. A type that has the EXTENDS attribute is an extended type. The parent type of an extended type is the type named in the EXTENDS attribute specification. The name of the parent type is the name that appears in the EXTENDS attribute specification. This might be a type-alias name or a local name introduced via renaming in a USE statement. A base type is an extension type of itself only. An extended type is an extension of itself and of all types for which its parent type is an extension. 4.5.3.1 Inheritance An extended type includes all of the type parameters, components, type-bound generic interfaces, and nonfinal procedure bindings of its parent type. These are said to be inherited by the extended type from the parent type. They retain all of the attributes that they had in the parent type. Additional type parameters, components, type-bound generic interfaces, and procedure bindings may be declared in the derived type definition of the extended type. Unresolved issue 292 We defined a type-bound generic interface to be a set of procedure bindings. Why then is it listed above as though it were a distinct inheritable thing different from the bindings? Inaccessible components and bindings of the parent type are also inherited, but they remain inaccessible in the extended type. Inaccessible entities occur if the type being extended is accessed via USE association and has a private entity. A base type is not required to have any components, and an extended type is not required to have more components than its parent type. An object of extended type has a scalar, nonpointer, nonallocatable, parent component with the type and type parameters of the parent type. The name of this component is the parent type name. Components of the parent component are inheritance associated (14.6.4) with the corresponding components inherited from the parent type. A component or type parameter declared in an extended type shall not have the same name as any accessible component or type parameter of its parent type. NOTE 4.49 Examples: TYPE, EXTENSIBLE :: POINT ! A base type REAL :: X, Y END TYPE POINT TYPE, EXTENDS(POINT) :: COLOR_POINT ! An extension of TYPE(POINT) ! Components X and Y, and component name POINT, inherited from parent INTEGER :: COLOR END TYPE COLOR_POINT 4.5.3.2 Type-bound procedure overriding If a nongeneric binding specified in a type definition has the same binding name as a binding inherited from the parent type then the binding specified in the type definition overrides the one inherited from the parent type. It is not allowed to override a binding that has the NON_OVERRIDABLE attribute in the parent type. If a binding overrides an inherited one then either both bindings shall specify PASS_OBJ or neither binding shall specify it. In addition, the two type-bound procedures or abstract interfaces shall match in the following ways: (1) If the procedure of the inherited binding is pure then that of the overriding binding shall also be pure. (2) Either both shall be elemental or neither shall. (3) They shall have the same number of dummy arguments. (4) Except for the passed-object dummy argument, the corresponding dummy arguments shall have the same characteristics (12.2.1) and names. (5) Either both shall be subroutines or both shall be functions having the same result characteristics (12.2.2). (6) If the inherited binding is PUBLIC then the overriding binding shall not be PRIVATE. If a binding is deferred and does not specify an abstract interface then it inherits the interface from the binding in the parent type. The following is an example of procedure overriding expanding on the example in Note 4.31. TYPE, EXTENDS (POINT) :: POINT_3D REAL :: Z CONTAINS PROCEDURE, PASS_OBJ :: LENGTH => POINT_3D_LENGTH END TYPE POINT_3D ... and in the module-subprogram-part of the same module: REAL FUNCTION POINT_3D_LENGTH ( A, B ) CLASS (POINT_3D), INTENT (IN) :: A CLASS (POINT), INTENT (IN) :: B IF ( EXTENDS_TYPE_OF(B, A) ) THEN POINT_3D_LENGTH = SQRT( (A%X-B%X)**2 + (A%Y-B%Y)**2 + (A%Z-B%Z)**2 ) RETURN END IF PRINT *, 'In POINT_3D_LENGTH, dynamic type of argument is incorrect.' STOP END FUNCTION POINT_3D If a generic binding specified in a type definition has the same dtio-generic-spec and the same kind type parameters for the derived type argument as one inherited from the parent type, then the binding specified in the type overrides the one inherited from the parent type. Otherwise, it extends the type-bound generic interface for the type being defined and the specified dtio-binding- spec. Unresolved issue 293 Multiple issues here, but I'll just assign one number. The way the first para of 4.5.3.2 has been edited, it now explicitly excludes generics. And this appears to be the only place where we say what non_overridable means. It would be good if it meant something for generics, since we do have it in the syntax for them. While I'm looking here I'll note the unrelated issue that the last para of 4.5.3.2 talks about the kind type parameters of the derived type argument of a binding. I don't think a binding has arguments - it's the procedure bound to that has argumentst. And "the derived type argument" is an awfully "fragile" specification. It won't generalize well at all to generics other than dtio...in fact, it doesn't even generalize enough to cover dtio changes made earlier in this same meeting (there are now 2 derived type args). This same problem occurs twice in 14.1.2.4.3. I'd note that the first sentence of the last para of 4.5.3.2 parses oddly (we aren't meaning to imply that the derived type arguments are inherited from the parent type are we?), but the other parts of this issue are unlikely to leave that phrasing as is. 4.5.4 Component order Component order is an ordering of the components of a derived type; it is used for intrinsic formatted input/output and structure constructors (when component name keywords are not used). The component order of a nonextended type is the order of the declarations of the components in the derived-type definition. The component order of an extended type consists of the component order of its parent type followed by any additional components in the order of their declarations in the extended derived-type definition. 4.5.5 Type parameter order Type parameter order is an ordering of the type parameters of a derived type; it is used for derived type specifiers. The type parameter order of a nonextended type is the order of the type parameter list in the derived-type definition. The type parameter order of an extended type consists of the type parameter order of its parent type followed by any additional type parameters in the order of the type parameter list in the derived-type definition. 4.5.6 Derived-type values The set of values of a specific derived type consists of all possible sequences of component values consistent with the definition of that derived type and the type parameters. 4.5.7 Derived-type specifier A derived-type specifier is used in several contexts to specify a particular derived type and type parameters. R448 derived-type-spec is type-name [ ( type-param-spec-list ) ] or type-alias-name R449 type-param-spec is [ keyword = ] type-param-value Constraint: type-name shall be the name of an accessible derived type. Constraint: type-alias-name shall be the name of an accessible type alias that is an alias for a derived type. Constraint: type-param-spec-list shall appear if and only if the type is parameterized. Constraint: There shall be exactly one type-param-spec corresponding to each parameter of the type. Constraint: the keyword = may be omitted from a type-param-spec only if the keyword = has been omitted from each preceding type-param-spec in the type-param-spec-list. Constraint: Each keyword shall be the name of a parameter of the type. Constraint: An asterisk may be used as a type-param-value in a type-param-spec only in the declaration of a dummy argument. Type parameter values that do not have type parameter keywords specified correspond to type parameters in type parameter order (4.5.5). If a type parameter keyword is present, the value is assigned to the type parameter named by the keyword. A type parameter value expression is not required to be of the same integer kind as the corresponding type parameter. 4.5.8 Construction of derived-type values A derived-type definition implicitly defines a corresponding structure constructor that allows construction of values of that derived type. The type and type parameters of a constructed value are specified by a derived type specifier. R450 structure-constructor is derived-type-spec ( [ component-spec-list ] ) R451 component-spec is [ keyword = ] expr Constraint: There shall be at most one component-spec corresponding to each component of the type. Constraint: There shall be exactly one component-spec corresponding to each component that does not have a default initialization. Constraint: The keyword = may be omitted from a component-spec only if the keyword = has been omitted from each preceding component-spec in the constructor. Constraint: Each keyword shall be the name of a component of the type. Constraint: The type name and all components of the type for which a component-spec appears shall be accessible in the scoping unit containing the structure constructor. Constraint: If derived-type-spec is a type name that is the same as a generic name, the component- spec-list shall not be a valid actual-arg-spec-list for a function reference that is resolvable as a generic reference (14.1.2.4.1). The form 'name(...)' is interpreted as a generic function-reference if possible; it is interpreted as a structure-constructor only if it cannot be interpreted as a generic function-reference. In the absence of a component name keyword, each expr is assigned to the corresponding component in component order (4.5.4). If a component name keyword is present, the expr is assigned to the component named by the keyword. If necessary, each value is converted according to the rules of intrinsic assignment (7.5.1.4) to a value that agrees in type and type parameters with the corresponding component of the derived type. For nonpointer components, the shape of the expression shall conform with the shape of the component. If a component with default initialization has no corresponding expr, then the default initialization is applied to that component. A component-spec-list of a structure-constructor for an extended type may use a nested form or a flattened form. In the nested form a single value is provided for the parent component. Unresolved issue 211 The term "flattened form" is used in 4.5.6.1, but it is nowhere defined. The closest thing to a definition is an example in note 4.46, but an example does not constitute a definition, even if the note were normative. The flattened form shall not be used if any components of the parent type are inaccessible in the scoping unit in which the structure-constructor appears (4.5.1). Examples of equivalent values using types defined in Note 4.49: ! Create values with components x = 1.0, y = 2.0, color = 3. TYPE(POINT) :: PV = POINT(1.0, 2.0) ! Assume components of TYPE(POINT) ! are accessible here. ... COLOR_POINT( PV, 3) ! Nested form, available even if ! TYPE(POINT) has private components. COLOR_POINT( POINT(1.0, 2.0), 3) ! Nested form, all components of ! TYPE(POINT) need to be accessible. COLOR_POINT( 1.0, 2.0, 3) ! Flattened form, all components of ! TYPE(POINT) need to be accessible. A structure constructor shall not appear before the referenced type is defined. This example illustrates a derived-type constant expression using a derived type defined in Note 4.20: PERSON (21, 'JOHN SMITH') This could also be written as PERSON (NAME = 'JOHN SMITH', AGE = 21) An example constructor using the derived type GENERAL_POINT defined in Note 4.21 is point(dim=3) ( (/ 1., 2., 3. /) ) A derived-type definition may have a component that is an array. Also, an object may be an array of derived type. Such arrays may be constructed using an array constructor (4.8). Where a component in the derived type is a pointer, the corresponding constructor expression shall evaluate to an object that would be an allowable target for such a pointer in a pointer assignment statement (7.5.2). For example, if the variable TEXT were declared (5.1) to be CHARACTER, DIMENSION (1:400), TARGET :: TEXT and BIBLIO were declared using the derived-type definition REFERENCE in Note 4.29 TYPE (REFERENCE) :: BIBLIO the statement BIBLIO = REFERENCE (1, 1987, 1, "This is the title of the referenced & &paper", TEXT) is valid and associates the pointer component ABSTRACT of the object BIBLIO with the target object TEXT. If a component of a derived type is allocatable, the corresponding constructor expression shall either be a reference to the intrinsic function NULL() with no arguments, an allocatable entity, or shall evaluate to an entity of the same rank. If the expression is a reference to the intrinsic function NULL(), the corresponding component of the constructor has a status of not currently allocated. If the expression is an allocatable entity, the corresponding component of the constructor has the same allocation status as that allocatable entity and, if it is allocated, the same bounds and value. With any other expression that evaluates to an array the corresponding component of the constructor has an allocation status of currently allocated and has the same bounds and value as the expression. When the constructor is an actual argument, the allocation status of the allocatable component is available through the associated dummy argument. 4.5.9 Derived-type operations and assignment Any operation on derived-type entities or nonintrinsic assignment for derived-type entities shall be defined explicitly by a function or a subroutine and an interface block (12.3.2.1). Arguments and function values may be of any derived or intrinsic type. 4.5.10 The finalization process When a finalizable object is finalized, the following steps are carried out in sequence: (1) If the dynamic type of the object has a final subroutine whose dummy argument has the same kind type parameters and rank as the object being finalized, it is called with the object as an actual argument. If there is no such subroutine, but there is an elemental final subroutine with the same kind type parameters as the object being finalized, it is called with the object as an actual argument. If no final subroutine fulfills these requirements, no subroutine is called at this point. (2) Each finalizable component that appears in the type definition is finalized. If the object is an array, the components of each element are finalized separately. (3) If the object is of extended type and the parent type is finalizable, the parent component is finalized. If several objects are to be finalized at the same time, the order in which they are finalized is processor-dependent. A final subroutine shall not reference or define an object that has already been finalized. 4.5.11 When finalization occurs A pointer or allocatable object is finalized when it is deallocated. A nonpointer, nonallocatable object that is not a dummy argument or function result is finalized immediately before it would become undefined due to execution of a RETURN or END statement (14.7.6, item (3)). If the object is defined in a module and there are no longer any active procedures referencing the module, it is processor-dependent whether it is finalized. If the object is not finalized, it retains its definition status and does not become undefined. If an executable construct references a function whose result is finalizable, the result is finalized after execution of the innermost executable construct containing the reference. If an executable construct references a structure constructor for a finalizable type, the object created by the structure constructor is finalized after execution of the innermost executable construct containing the reference. If a specification expression in a scoping unit references a function whose result is finalizable, the result is finalized before execution of the first executable statement in the scoping unit. Unresolved issue 301 Is there an issue here with scoping units that aren't executable? That would include modules, interface bodies, and block data. I haven't carefully thought about it, but the casual way that the above sentence ignores the question makes me wonder. Unresolved issue 303 Don't we need something somewhere to require that finalization be pure in specification expressions? The text added to 12.6 doesn't cover finalizations of the above para (in 4.5.11) because they aren't references *in* a pure subprogram; they finalize the reult some time after tje procedure has completed. I can't offhand think of any other places where final procedures might violate purity in ways not restricted against, but I could have missed something. When a procedure is invoked, a nonpointer, nonallocatable object that is an actual argument associated with an INTENT(OUT) dummy argument is finalized. When an intrinsic assignment statement is executed, variable is finalized after evaluation of expr and before the definition of variable. The semantics of intrinsic assignment are such that finalization has very limited usefulness. Defined assignment will almost always be necessary for finalization to be useful. If an object is allocated via pointer allocation and later becomes unreachable due to all pointers to that object having their pointer association status changed, it is processor dependent whether it is finalized. If it is finalized, it is processor dependent as to when the final subroutines are called. 4.5.12 Objects that are not finalized If program execution is terminated, either by an error (e.g. an allocation failure) or by execution of a STOP or END PROGRAM statement, objects existing immediately prior to termination are not finalized. A nonpointer, nonallocatable object that has the SAVE attribute or which occurs in the main program is never finalized as a direct consequence of the execution of a RETURN or END statement. A variable in a module is not finalized if it retains its definition status and value, even when there is no active procedure referencing the module. 4.6 Type aliases Type aliasing provides a method of data abstraction. A type alias statement does not define a new data type in the way that a derived type definition does. Instead, it defines a name that may be used to define entities of a particular type. A type alias name that is an alias for a derived type may also be used in the derived-type-spec of a structure-constructor. R452 type-alias-stmt is TYPEALIAS :: type-alias-list R453 type-alias is type-alias-name => declaration-type-spec Constraint: A type-alias-name shall not be the same as the name of any intrinsic type defined in this standard. Constraint: A declaration-type-spec in a type-alias shall not use the CLASS keyword. Constraint: A declaration-type-spec in a type-alias shall not have any deferred or assumed type parameters. Explicit or implicit declaration of an entity or component using a type alias name has the same effect as using the type-spec for which it is an alias. The declarations for X, Y, and S TYPEALIAS :: DOUBLECOMPLEX => COMPLEX(KIND(1.0D0)), & NEWTYPE => TYPE(DERIVED), & ANOTHERTYPE => TYPE(NEWTYPE) TYPE(DOUBLECOMPLEX) :: X, Y TYPE(NEWTYPE) :: S TYPE(ANOTHERTYPE) :: T are equivalent to the declarations COMPLEX(KIND(1.0D0)) :: X, Y TYPE(DERIVED) :: S, T 4.7 Enumerations and enumerators An enumeration is a type alias name for an integer type. An enumerator is a named integer constant. An enumeration definition specifies the enumeration and a set of enumerators of the corresponding integer kind. An entity of an enumeration type is interoperable (16.2) with an entity of a corresponding enumeration type of the companion processor (2.5.10). R454 enum-alias-def is enum-def-stmt enumerator-def-stmt [ enumerator-def-stmt ] ... end-enum-stmt R455 enum-def-stmt is ENUM, BIND(C) :: type-alias-name or ENUM [ kind-selector ] [ :: ] type-alias-name R456 enumerator-def-stmt is ENUMERATOR [ :: ] enumerator-list R457 enumerator is named-constant [ = scalar-int-initialization-expr ] R458 end-enum-stmt is END ENUM [ type-alias-name ] Constraint: If = appears for an enumerator in an ENUMERATOR statement, a double-colon separator shall appear before the enumerator-list. Constraint: If END ENUM is followed by a type-alias-name, the type-alias-name shall be the same as that in the corresponding enum-def-stmt. The type-alias-name is an enumeration, which is treated as if it were explicitly declared in a type alias statement as a type alias for an integer whose kind parameter is determined as follows: (1) If BIND(C) is specified, the kind is selected such that an entity of type integer with that kind is interoperable with an entity of the corresponding C enumeration type. The corresponding C enumeration type is the type that would be declared by a C enumeration specifier (6.7.2.2 of the C standard) that specified C enumeration constants with the same values as those specified by the enum-alias-def, in the same order as specified by the enum-alias-def. The companion processor shall be one that uses the same representation for the types declared by all C enumeration specifiers that specify the same values in the same order. If a companion processor uses an unsigned type to represent a given enumeration type, the Fortran processor will use the signed integer type of the same width for the enumeration, even though some of the values of the enumerators cannot be represented in this signed integer type. The values of any such enumerators will be interoperable with the values declared in the C enumeration. C guarantees the enumeration constants fit in a C int (6.7.2.2 of the C standard). Therefore, the Fortran processor can evaluate all enumerator values using the integer type with kind parameter C_INT, and then determine the kind parameter of the integer type that is interoperable with the corresponding C enumerated type. (2) If kind-selector is specified, the kind is that specified by the kind-selector. (3) If neither BIND(C) nor kind-selector is specified, the kind is that of default integer. The C standard requires a processor to make two enumeration types compatible only if they specify enumeration constants with the same names and same values in the same order. This standard further requires that a C processor that is to be a companion processor of a Fortran processor use the same representation for two enumeration types if they both specify enumeration constants with the same values in the same order, even if names are different. Unresolved issue 264 I'm not confident of my C standard-speak, so I didn't just fix the first sentence of the above note in 4.7, but it looks wrong to me. Is type-compatibility something defined by the C standard or by a C processor? I would have thought that it was defined by the standard. In that case, you wouldn't say that the C standard requires that a processor make types compatible under certain conditions. You would just say that the C standard specifies that the types *ARE* compatible under those conditions. That this compatability implies the use of the same representation is a separate matter. An enumerator is treated as if it were explicitly declared with type type-alias-name and with the PARAMETER attribute. The enumerator is defined in accordance with the rules of intrinsic assignment (7.5) with the value determined as follows: (1) If scalar-int-initialization-expr is specified, the value of the enumerator is the result of scalar-int-initialization-expr. (2) If scalar-int-initialization-expr is not specified and the enumerator is the first enumerator in enum-alias-def, the enumerator has the value 0. (3) If scalar-int-initialization-expr is not present and the enumerator is not the first enumerator in enum-alias-def, its value is the result of adding 1 to the value of the enumerator that immediately precedes it in the enum-alias-def. The declarations ENUM (SELECTED_INT_KIND (1)) :: DIGITS ENUMERATOR :: ZERO, ONE, TWO END ENUM DIGITS ENUM :: PRIMARY_COLORS ENUMERATOR :: RED = 4, BLUE = 9 ENUMERATOR YELLOW END ENUM TYPE (DIGITS) :: X are equivalent to the declarations TYPEALIAS :: DIGITS => INTEGER (SELECTED_INT_KIND(1)) TYPE (DIGITS), PARAMETER :: ZERO = 0, ONE = 1, TWO = 2 TYPE (DIGITS) :: X ! The kind type parameter for PRIMARY_COLORS is processor dependent, but the ! processor is required to select a kind sufficient to represent the values ! 4, 9, and 10, which are the values of its enumerators. ! The following declaration is one possibility for PRIMARY_COLORS. TYPEALIAS :: PRIMARY_COLORS => INTEGER (SELECTED_INT_KIND (2)) TYPE (PRIMARY_COLORS), PARAMETER :: RED = 4, BLUE = 9, YELLOW = 10 There is no difference in the effect of declaring the enumerators in multiple ENUMERATOR statements or in a single ENUMERATOR statement. The order in which the enumerators in an enumeration definition are declared is significant, but the number of ENUMERATOR statements is not. 4.8 Construction of array values An array constructor is defined as a sequence of scalar values and is interpreted as a rank-one array where the element values are those specified in the sequence. Unresolved issue 119 Now that we have square brackets in the character set, are we going to use them as an alternative form for array constructors? It is conventional math notation, a common Fortran extension, also used in other languages (Matlab for example), and a lot easier for the human to read than the 2-character form with slashes and parens. It would also answer a common user question..plus some questions that keep comming up about places in the standard where we use the [] mathematical notation. As far as I'm aware, the only reason array constructors weren't like this all along is that the brackets weren't in the character set. The specs and edits papers for adding the brackets to the character set say that "No semantics are assigned to these characters." It has been (somewhat emphatically) pointed out to me that this could be interpreted as resolving this issue by saying that we aren't going to do it. It is unclear to me whether this is the intention or not. I had been interpreting that statement more as a separation of the question than as a resolution. Given the apparent differences in opinion, I'd like specific J3 direction on whether to remove this issue. In general, if papers are meant to resolve issues, please say so explicitly in the paper. R459 array-constructor is (/ [ type-spec :: ] [ ac-value-list ] /) Constraint: if ac-value-list is absent, type-spec shall appear. R460 ac-value is expr or ac-implied-do R461 ac-implied-do is ( ac-value-list , ac-implied-do-control ) R462 ac-implied-do-control is ac-do-variable = scalar-int-expr , scalar-int-expr n n [ , scalar-int-expr ] R463 ac-do-variable is scalar-int-variable Constraint: ac-do-variable shall be a named variable. Constraint: If type-spec is omitted, each ac-value expression in the array-constructor shall have the same type and kind type parameters. Constraint: If type-spec specifies an intrinsic type, each ac-value expression in the array-constructor shall be of an intrinsic type that is compatible with intrinsic assignment to a variable of type type-spec as specified in Table 7.9. Constraint: If type-spec specifies a derived type, each ac-value expression in the array-constructor shall be of the same derived type and shall have the same kind type parameter values. If type-spec is omitted, each ac-value expression in the array-constructor shall have the same type and type parameters. The type and type parameters of the array constructor are those of the ac-value expressions. If type-spec appears, it specifies the type and type parameters of the array constructor. Each ac- value expression in the array-constructor shall be compatible with intrinsic assignment to a variable of this type and type parameters. Each value is converted to the type parameters of the array- constructor in accordance with the rules of intrinsic assignment (7.5.1.5). If an ac-value is a scalar expression, its value specifies an element of the array constructor. If an ac-value is an array expression, the values of the elements of the expression, in array element order (6.2.2.2), specify the corresponding sequence of elements of the array constructor. If an ac-value is an ac-implied-do, it is expanded to form an ac-value sequence under the control of the ac-do-variable, as in the DO construct (8.1.5.4). For an ac-implied-do, the loop initialization and execution is the same as for a DO construct. The ac-do-variable of an ac-implied-do that is in another ac-implied-do shall not appear as the ac-do-variable of the containing ac-implied-do. An empty sequence forms a zero-sized rank-one array. A one-dimensional array may be reshaped into any allowable array shape using the RESHAPE intrinsic function (13.17.95). An example is: X = (/ 3.2, 4.01, 6.5 /) Y = RESHAPE (SOURCE = (/ 2.0, (/ 4.5, 4.5 /), X /), SHAPE = (/ 3, 2 /)) This results in Y having the 3 ¥ 2 array of values: 2.0 3.2 4.5 4.01 4.5 6.5 Examples of array constructors containing an implied-DO are: (/ (I, I = 1, 1075) /) and (/ 3.6, (3.6 / I, I = 1, N) /) Using the type definition for PERSON in Note 4.20, an example of the construction of a derived-type array value is: (/ PERSON (40, 'SMITH'), PERSON (20, 'JONES') /) Using the type definition for LINE in Note 4.26, an example of the construction of a derived- type scalar value with a rank-2 array component is: LINE (RESHAPE ( (/ 0.0, 0.0, 1.0, 2.0 /), (/ 2, 2 /) ), 0.1, 1) The RESHAPE intrinsic function is used to construct a value that represents a solid line from (0, 0) to (1, 2) of width 0.1 centimeters.