Polymorphic Entities#

A polymorphic entity is a data entity that can be of different type during the execution of a program.

This document aims to give insights at the representation of polymorphic entities in FIR and how polymorphic related constructs and features are lowered to FIR.

Fortran standard#

Here is a list of the sections and constraints of the Fortran standard involved for polymorphic entities.

  • 7.3.2.1 - 7.3.2.2: TYPE specifier (TYPE(*))

    • C708

    • C709

    • C710

    • C711

  • 7.3.2.3: CLASS specifier

  • 7.5.4.5: The passed-object dummy argument

    • C760

  • 9.7.1: ALLOCATE statement

    • C933

  • 9.7.2: NULLIFY statement

    • When a NULLIFY statement is applied to a polymorphic pointer (7.3.2.3), its dynamic type becomes the same as its declared type.

  • 10.2.2.3: Data pointer assignment

  • 11.1.3: ASSOCIATE construct

  • 11.1.11: SELECT TYPE construct

    • C1157

    • C1158

    • C1159

    • C1160

    • C1161

    • C1162

    • C1163

    • C1164

    • C1165

  • 16.9.76 EXTENDS_TYPE_OF (A, MOLD)

  • 16.9.165 SAME_TYPE_AS (A, B)

  • 16.9.184 STORAGE_SIZE (A [, KIND])

  • C.10.5 Polymorphic Argument Association (15.5.2.9)


Representation in FIR#

Polymorphic entities CLASS(type1)#

A polymorphic entity is represented as a class type in FIR. In the example below the dummy argument p is passed to the subroutine foo as a polymorphic entity with the extensible type point. The type information captured in the class is the best statically available at compile time. !fir.class is a new type introduced for polymorphic entities. It’s similar to a box type but allows the distinction between a monomorphic and a polymorphic descriptor. !fir.class and !fir.box are based on a same BaseBoxType similar to the BaseMemRefType done for MemRef.

Fortran

type point
  real :: x, y
end type point

type, extends(point) :: point_3d
  real :: z
end type

subroutine foo(p)
  class(point) :: p
  ! code of the subroutine
end subroutine

FIR

func.func @foo(%p : !fir.class<!fir.type<_QTpoint{x:f32,y:f32}>>)

Unlimited polymorphic entities CLASS(*)#

The unlimited polymorphic entity is represented as a class type with none as element type.

Fortran

subroutine bar(x)
  class(*) :: x
  ! code of the subroutine
end subroutine

FIR

func.func @bar(%x : !fir.class<none>)

Assumed-type TYPE(*)#

Assumed type is added in Fortran 2018 and it is available only for dummy arguments. It’s mainly used for interfaces to non-Fortran code and is similar to C’s void. An entity that is declared using the TYPE(*) type specifier is assumed-type and is an unlimited polymorphic entity. It is not declared to have a type, and is not considered to have the same declared type as any other entity, including another unlimited polymorphic entity. Its dynamic type and type parameters are assumed from its effective argument (7.3.2.2 - 3).

Assumed-type is represented in FIR as !fir.box<none>.

SELECT TYPE construct#

The SELECT TYPE construct select for execution at most one of its constituent block. The selection is based on the dynamic type of the selector.

Fortran

type point
  real :: x, y
end type point
type, extends(point) :: point_3d
  real :: z
end type point_3d
type, extends(point) :: color_point
  integer :: color
end type color_point

type(point), target :: p
type(point_3d), target :: p3
type(color_point), target :: c
class(point), pointer :: p_or_c
p_or_c => c
select type ( a => p_or_c