Intel® Fortran Compiler Classic and Intel® Fortran Compiler Developer Guide and Reference

ID 767251
Date 3/22/2024
Public
Document Table of Contents

TYPE Statement for Derived Types)

Statement: Declares a variable to be of derived type. It specifies the name of the user-defined type and the types of its components.

TYPE [[,attr-list] :: ] name [(type-param-name-list)]

   [type-param-def-stmts]

   [PRIVATE statement or SEQUENCE statement]. . .

   [component-definition]. . .

   [type-bound-procedure-part]

END TYPE [name]

attr-list

Is one of the following:

  • access-spec

    Is the PUBLIC or PRIVATE attribute. The attribute can only be specified if the derived-type definition is in the specification part of a module.

  • BIND(C)

  • EXTENDS (parent-type-name)

    where parent-type-name is the name of a previously defined extensible type.

  • ABSTRACT

The same attr must not appear more than once in any given derived-type statement.

If the type definition contains or inherits a deferred binding, ABSTRACT must appear.

The EXTENDS and ABSTRACT attributes apply to type extension and extended types. If ABSTRACT is specified, the type is an abstract type and it must be extensible.

A derived type that does not have the SEQUENCE or BIND(C) attribute is extensible. Conversely, a derived type that has the SEQUENCE or BIND(C) attribute is not extensible.

name

Is the name of the derived data type. It must not be the same as the name of any intrinsic type, or the same as the name of a derived type that can be accessed from a module.

type-param-name-list

Is a list of type parameter names separated by commas. For more information, see Parameterized Derived-Type Declarations.

type-param-def-stmts

Is one or more INTEGER declarations of the type parameters named in the type-param-name-list. For more information, see Parameterized Derived-Type Declarations.

component-definition

Is one or more type declaration statements or procedure pointer statements defining the component of derived type.

The first component definition can be preceded by an optional PRIVATE or SEQUENCE statement. (Only one PRIVATE and only one SEQUENCE statement can appear in a given derived-type definition.)

If SEQUENCE is present, all derived types specified in component definitions must be sequence types.

Procedure pointer component definitions are described in Procedure Pointers as Derived-Type Components.

The syntax for a type declaration component definition is described below.

type-bound-procedure-part

Is a CONTAINS statement, optionally followed by a PRIVATE statement, and one or more procedure binding statements (specific, generic, or final). For more information, see Type-Bound Procedures.

A type declaration component definition takes the following form:

type[ [, attr] :: ] component[( a-spec)] [[ coarray-spec ]] [ *char-len] [ init-ex]

type

Is a type specifier. It can be an intrinsic type or a previously defined derived type.

If the POINTER or the ALLOCATABLE attribute follows this specifier, the type can also be the type being defined or any accessible derived type, whether previously defined or not.

attr

Is at most one of the following:

  • An optional POINTER attribute for a pointer component

  • An optional ALLOCATABLE attribute for a scalar component

  • An optional DIMENSION or ALLOCATABLE attribute for an array component

    You cannot specify both the ALLOCATABLE and POINTER attribute.

  • An optional access specifier, PUBLIC or PRIVATE

  • An optional CODIMENSION [coarray-spec] to specify a coarray

  • An optional CONTIGUOUS attribute if the object is contiguous

Each attribute can only appear once in a given component definition.

If neither the POINTER nor the ALLOCATABLE attribute is specified, type must specify an intrinsic type or a previously defined derived type.

If neither the POINTER nor the ALLOCATABLE attribute is specified, each a-spec must be an explicit-shape specification.

If the POINTER or ALLOCATABLE attribute is specified, each component array specification a-spec must be a deferred shape specification (d-spec).

If a coarray-spec appears, it must be a deferred specification list consisting of one or more colons (:), the component must have the ALLOCATABLE attribute, and the component must not be of type C_PTR or C_FUNPTR from the intrinsic module ISO_C_BINDING or of type TEAM_TYPE from the intrinsic module ISO_FORTRAN_ENV.

A data component whose type has a coarray ultimate component must be a nonpointer nonallocatable scalar and must not be a coarray.

If the CONTIGUOUS attribute is specified, the component must be an array with the POINTER attribute.

component

Is the name of the component being defined.

a-spec

Is an optional array specification, enclosed in parentheses. If POINTER or ALLOCATABLE is specified, the array is deferred shape; otherwise, it is explicit shape. In an explicit-shape specification, each bound must be a constant scalar integer expression.

If component is an array and the array bounds are not specified here, they must be specified following the DIMENSION attribute.

coarray-spec

Is a deferred-coshape specification. The left bracket and right bracket are required.

char-len

Is an optional scalar integer literal constant; it must be preceded by an asterisk (*). This parameter can only be specified if the component is of type CHARACTER.

init-ex

Is one of the following:

  • = constant expression for nonpointer components

  • => NULL( ) for pointer components

If init-ex is specified, a double colon must appear in the component definition. The equals assignment symbol (=) can only be specified for nonpointer components.

The constant expression is evaluated in the scoping unit of the type definition.

Description

If a name is specified following the END TYPE statement, it must be the same name that follows TYPE in the derived type statement.

A derived type can be defined only once in a scoping unit. If the same derived-type name appears in a derived-type definition in another scoping unit, it is treated independently.

A component name has the scope of the derived-type definition only. Therefore, the same name can be used in another derived-type definition in the same scoping unit.

The default accessibility attribute for a module is PUBLIC unless it has been changed by a PRIVATE statement with no entity-list.

A PUBLIC or PRIVATE keyword can only appear on the TYPE statement of a derived-type definition, or on a component or type-bound procedure declaration of the type if the derived-type definition is in the specification part of a module.

The PRIVATE statement can only be specified in the component-definition or type-bound-procedure-part if the derived-type definition is in the specification part of a module. A PRIVATE statement inside a component-definition part specifies that the default accessibility of all components of the derived type are PRIVATE. Similarly, a PRIVATE statement inside a type-bound-procedure-part specifies that the default accessibility of the type bound procedures of the derived type are PRIVATE. If the default accessibility of components or type-bound procedures is PRIVATE, individual components or type-bound procedures can be declared PUBLIC, overriding the default accessibility attribute.

If a type definition is PRIVATE, the type name and the structure constructor for the type are accessible only within the module containing the definition and in the descendants of that module.

Two data entities have the same type if they are both declared to be of the same derived type; the derived-type definition can be accessed from a module or a host scoping unit.

If EXTENDS appears and the type being defined has a coarray ultimate component, its parent type must have a coarray ultimate component.

Data entities in different scoping units also have the same type if the following is true:

  • They are declared with reference to different derived-type definitions that specify the same type name.

  • All have the SEQUENCE property.

  • All have the BIND attribute.

  • They have no components with PRIVATE accessibility.

  • They have type parameters and components that agree in order, name, and attributes.

Otherwise, they are of different derived types.

A data component is a coarray if the component declaration contains a coarray specification. If the component declaration contains a coarray specification, it specifies the corank.

If BIND (C) is specified, the following rules apply:

  • The derived type cannot be a SEQUENCE type.

  • The derived type must not have type parameters.

  • The derived type must not have the EXTENDS attribute.

  • The derived type must not have a type-bound-procedure-part.

  • Each component of the derived type must be a nonpointer, nonallocatable data component with interoperable type and type parameters.

Example

 !   DERIVED.F90
 !   Define a derived-type structure,
 !   type variables, and assign values

     TYPE member
       INTEGER age
       CHARACTER (LEN = 20) name
     END TYPE member

     TYPE (member) :: george
     TYPE (member) :: ernie

     george     = member( 33, 'George Brown' )
     ernie%age  = 56
     ernie%name = 'Ernie Brown'

     WRITE (*,*) george
     WRITE (*,*) ernie
     END

The following shows another example of a derived type:

TYPE mem_name
  SEQUENCE
  CHARACTER (LEN = 20) lastn
  CHARACTER (LEN = 20) firstn
  CHARACTER (len = 3) cos   ! this works because COS is a component name
END TYPE mem_name
TYPE member
    SEQUENCE
    TYPE (mem_name) :: name
    INTEGER age
    CHARACTER (LEN = 20) specialty
END TYPE member

In the following example, a and b are both variable arrays of derived type pair:

 USE, INTRINSIC :: ISO_C_BINDING
 TYPE, BIND(C) :: pair
   INTEGER(C_INT) :: i, j
 END TYPE
 TYPE (pair) :: a, b(3)

The following example shows how you can use derived-type objects as components of other derived-type objects:

 TYPE employee_name
   CHARACTER(25) last_name
   CHARACTER(15) first_name
 END TYPE
 TYPE employee_addr
   CHARACTER(20) street_name
   INTEGER(2) street_number
   INTEGER(2) apt_number
   CHARACTER(20) city
   CHARACTER(2) state
   INTEGER(4) zip
 END TYPE

Objects of these derived types can then be used within a third derived-type specification, such as:

 TYPE employee_data
   TYPE (employee_name) :: name
   TYPE (employee_addr) :: addr
   INTEGER(4) telephone
   INTEGER(2) date_of_birth
   INTEGER(2) date_of_hire
   INTEGER(2) social_security(3)
   LOGICAL(2) married
   INTEGER(2) dependents
 END TYPE

The following program shows how you initialize components of a derived-type object:

TYPE list_node
   CHARACTER(20)                :: street_name = " "
   INTEGER(2)                   :: street_number = 0
   INTEGER(2)                   :: apt_number = -1
   CHARACTER(20)                :: city = " "
   CHARACTER(2)                 :: state = "NH"
   INTEGER(4)                   :: zip = 0
   TYPE (list_node), POINTER    :: next => NULL()
END TYPE

TYPE (list_node) :: x = list_node (zip = 03054)
PRINT *, x%state, x%zip
END

The above prints the following:

        NH 3054

Coarrays were introduced as a Fortran 2008 feature. The following example shows a derived-type definition with a coarray component:

TYPE NEW_TYPE
   REAL,ALLOCATABLE,CODIMENSION[:,:,:] :: NEW(:,:,:)
END TYPE NEW_TYPE

An object of type NEW_TYPE must be a scalar and it cannot be a pointer, allocatable, or a coarray.

The following example shows a derived-type definition containing a coarray-spec:

type t
   integer :: k
   real, allocatable :: x (:,:)[:,:]
end type t

In the following example, when the assignment to DEST occurs, DEST%TA is unallocated: it is first allocated with the size of SOURCE%TA and then the value of SOURCE%TA is assigned into DEST%TA:

TYPE T 
  INTEGER I
END TYPE T
TYPE T2
  TYPE (T), ALLOCATABLE :: TA
END TYPE T2

TYPE (T2) SOURCE, DEST

ALLOCATE(SOURCE%TA)
DEST = SOURCE

The use of allocatable components of recursive type can involve direct recursion, in which the type has a component that is the same type as its parent. The following example creates a five-element linked list using allocatable components of recursive type:

TYPE T
INTEGER I
TYPE(T), ALLOCATABLE :: NEXT
END TYPE

TYPE (T), ALLOCATABLE, TARGET :: ORIG, COPY
TYPE (T), POINTER :: TA

ALLOCATE(ORIG)
TA => ORIG

DO I=1,5
  TA%I = I
  ALLOCATE(TA%NEXT)
  TA => TA%NEXT
END DO

By using allocatable components rather than pointer components, there is no need to explicitly nullify component NEXT - it is set to an unallocated state automatically by the compiler. Because the semantics of ALLOCATE(SOURCE=) require the allocation and copying of all allocated allocatable components from ORIG into COPY, we can create a complete, unique copy of the entire linked list in one easy statement:

ALLOCATE(COPY, SOURCE=ORIG)

In addition to direct recursion, indirect recursion or forward referencing can also be used. In the following example, component A of type T is of type T2, a forward reference to a type not yet defined, while component B of type T2 is of type T:

TYPE T
TYPE(T2), ALLOCATABLE :: A
END TYPE

TYPE T2
TYPE(T), ALLOCATABLE :: B
END TYPE

TYPE(T2) TY