Intel® Fortran Compiler
Build applications that can scale for the future with optimized code designed for Intel® Xeon® and compatible processors.

SELECT TYPE confusion

OP1
New Contributor II
499 Views

The confusion is either the compiler's or mine...

The following code produces two different outputs for the lines 23 and 24, and I am not sure I understand why. Anybody cares to chime in? This is with ifort classic 2021.5.0 on Windows, x64.

MODULE M
IMPLICIT NONE
TYPE :: T
    CONTAINS
        PROCEDURE P
END TYPE T
TYPE, EXTENDS(T) :: TT
    CONTAINS
        PROCEDURE PP
END TYPE TT
CONTAINS
SUBROUTINE P(SELF)
CLASS(T) :: SELF
SELECT TYPE (SELF)
    TYPE IS (T)
        WRITE(*, *) 'T'
    TYPE IS (TT)
        WRITE(*, *) 'TT'
END SELECT
END SUBROUTINE P
SUBROUTINE PP(SELF)
CLASS(TT) :: SELF
CALL SELF%T%P ! This produces 'T'
CALL SELF%P   ! This produces 'TT'
END SUBROUTINE PP
END MODULE M

PROGRAM P
USE M
IMPLICIT NONE
TYPE(TT) :: VAR
CALL VAR%PP
END PROGRAM P
0 Kudos
4 Replies
FortranFan
Honored Contributor II
470 Views

Can you elaborate on your confusion?

The standard explains it is the dynamic type of the object in question that governs the branching in the `SELECT TYPE` construct: "The selection is based on the dynamic type of an expression."

As such, the program using IFORT indeed appears conformant with the standard.

0 Kudos
OP1
New Contributor II
446 Views

ok, so it seems that (in pseudo-code) what happens on line 23 is akin to CALL (SELF%T)%P, that is, the dynamic type of the passed object in P is T.

My expectation was that, instead, the call was doing something akin to CALL SELF%(T%P), that is, pass an object of dynamic type TT to the procedure P that is type-bound to T.

I have to admit that this feels a bit strange!

0 Kudos
IanH
Honored Contributor II
410 Views

@OP1 wrote:

...

My expectation was that, instead, the call was doing something akin to CALL SELF%(T%P), that is, pass an object of dynamic type TT to the procedure P that is type-bound to T.


Syntax for that is simply:

CALL P(SELF)

You can statically identify the procedure that you want to invoke, so there's no need to reference it through a dynamically dispatched binding (namespace management aspects of bindings aside).

0 Kudos
FortranFan
Honored Contributor II
387 Views

When the parent type component of an extended type can be referenced e.g., when the parent type is not an abstract type, you can view the parent type reference - such as with SELF%T in your code snippet - as having the dynamic type to be the same as its declared type which in your case is 'T'.

 

So, in effect, whether your instruction is `CALL SELF%T%P` or `CALL P( SELF%T )`, the effective argument to the procedure P will be of TYPE of 'T'.

0 Kudos
Reply