Procedure Pointer Compilation Error

Procedure Pointer Compilation Error

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

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

derived.F90


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

main.F90

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

6 posts / novo 0
Último post
Para obter mais informações sobre otimizações de compiladores, consulte Aviso sobre otimizações.

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.

Steve

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.

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).

Citação:

Steve Lionel (Intel) escreveu:
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).

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.

Steve

Faça login para deixar um comentário.