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

Procedure Pointer Compilation Error

Matthew_C_5
Beginner
397 Views

I have reproduced an error I am facing in a code with the following three files. The idea is that an abstract class contains a procedure pointer that I want to assign in the derived type. In the derived type the passed argument is changed to the derived type using the CLASS keyword. The program compiles and executes perfectly with gfortran 4.6.3. With ifort 12.1.5 there is the following error when compiling the derived type module with ifort -c derived.F90 (of course, this is after compiling the abstract module with ifort -c abstract.F90):

derived.F90(17): error #8178: The procedure pointer and the procedure target must have matching arguments.
    THIS%procPtr => derived_sub
----^
compilation aborted for derived.F90 (code 1)

The code is contained in the following three files:

abstract.F90

[fortran]

MODULE abstract_m

TYPE,ABSTRACT,PUBLIC :: abstract_t
 
  ! The procedure pointer facing the problems.
  PROCEDURE(abstract_proc),POINTER :: procPtr

  CONTAINS
    PROCEDURE(initX),PUBLIC,DEFERRED :: init

END TYPE abstract_t

ABSTRACT INTERFACE
 
  SUBROUTINE abstract_proc(THIS)
    IMPORT
    CLASS(abstract_t),INTENT(IN) :: THIS
  END SUBROUTINE abstract_proc
 
  SUBROUTINE initX(THIS)
    IMPORT
    CLASS(abstract_t),INTENT(INOUT) :: THIS
  END SUBROUTINE initX

END INTERFACE

END MODULE abstract_m

[/fortran]

derived.F90

[fortran]


MODULE derived_m

USE abstract_m

TYPE,PUBLIC,EXTENDS(abstract_t) :: derived_t
  CONTAINS
    PROCEDURE,PUBLIC :: init => init_sub
END TYPE derived_t

PRIVATE :: init_sub, derived_sub

CONTAINS

  SUBROUTINE init_sub(THIS)
    CLASS(derived_t),INTENT(INOUT) :: THIS
    WRITE (*,*) 'Hello world from the derived object.'
    THIS%procPtr => derived_sub
  END SUBROUTINE init_sub

  SUBROUTINE derived_sub(THIS)
    CLASS(derived_t),INTENT(IN) :: THIS
    WRITE (*,*) 'Hello world from the procedure pointer.'
  END SUBROUTINE derived_sub

END MODULE derived_m

[/fortran]

main.F90

[fortran]

PROGRAM main

USE abstract_m
USE derived_m

IMPLICIT NONE

CLASS(abstract_t),POINTER :: objPtr
ALLOCATE(derived_t::objPtr)
CALL objPtr%init()
CALL objPtr%procPtr()

END PROGRAM main

[/fortran]

0 Kudos
5 Replies
Steven_L_Intel1
Employee
399 Views
My initial research leads me to conclude that the Intel compiler is correct to give an error here. The standard says: "If the pointer object has an explicit interface, its characteristics shall be the same as the pointer target ... [irrelevant text omitted]" F2008 7.2.2.4 (Procedure pointer assignment), line 6 12.3.1 defines the characteristics of procedures, and the part that matters here is "characteristics of its dummy arguments". 12.3.3.3 defines the characteristics of dummy data objects, and this includes "its type". In the code you posted, the type of the dummy argument of the pointer object is CLASS(abstract_t) while the type of the dummy argument of the target is CLASS(derived_t). These are not "the same". This is not like data pointer assignment where the pointer is polymorphic. The standard has no provision to allow "type compatible" dummy arguments - it requires them to have the same type. I know this is not what you want to hear, but unless someone can come up with a convincing argument (with references to the standard) why I'm wrong, I'd say this is a bug in gfortran.
0 Kudos
Matthew_C_5
Beginner
399 Views
Thank you for the reply Steve. I have posted a thread to the gcc mailing list (fortran@gcc.gnu.org) to see if I can get any response from others who are familiar with the fortran standard (as I am not!). Hopefully I can post back in the future with some additional information.
0 Kudos
Matthew_C_5
Beginner
399 Views
It looks like the code should not compile, according to a post on my thread with the gcc fortran mailing list. A question for you Steve: do you know of another way to do what I am trying to do? The reason why I wanted to use a procedure pointer was because in our code there might be 5 options that could be used for the procedure, and the one for the job is selected at runtime. I can't use a type-bound procedure with an abstract interface because I don't have the flexibility to change that procedure in the derived type at runtime (at least I don't think I do). I originally thought what I was doing should be allowed given the fact that an abstract type object cannot even be constructed, and that the derived type extends the abstract type (along the lines of polymorphism).
0 Kudos
IanH
Honored Contributor II
399 Views
Steve Lionel (Intel) wrote:
I know this is not what you want to hear, but unless someone can come up with a convincing argument (with references to the standard) why I'm wrong, I'd say this is a bug in gfortran.
It has to be the way you describe, otherwise you'd be able to dynamically (run time) bind a procedure to an object where the passed argument was of the wrong type and the compiler would have to diagnose that (C456 in F2008) at compile time. (Imagine a different extension Xxx of abstract_t, create an object of it, pointer assign derived_sub to procPtr, call the pointer component - object of type Xxx being passed to a procedure that wants object of type derived_t).
0 Kudos
Steven_L_Intel1
Employee
399 Views
Perhaps I haven't had enough coffee yet, but I am not completely certain of what you want to do. Perhaps you need to step outside the comfort zone of Fortran pointers and have a component of type C_FUNPTR that gets assigned the C_FUNLOC of various procedures. Then you can, based on some selector you have, convert it to a Fortran procedure pointer with C_F_PROCPOINTER and call it that way.
0 Kudos
Reply