Intel® Fortran Compiler
Build applications that can scale for the future with optimized code designed for Intel® Xeon® and compatible processors.
Announcements
The Intel sign-in experience is changing in February to support enhanced security controls. If you sign in, click here for more information.

SELECT TYPE confusion

OP1
New Contributor II
297 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
268 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.

OP1
New Contributor II
244 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!

IanH
Black Belt
208 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).

FortranFan
Honored Contributor II
185 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'.

Reply