Intel® Fortran Compiler
Build applications that can scale for the future with optimized code designed for Intel® Xeon® and compatible processors.
Announcements
Welcome to the Intel Community. If you get an answer you like, please mark it as an Accepted Solution to help others. Thank you!
26729 Discussions

Procedure pointers as an OPTIONAL function argument

Michael_D_11
Beginner
208 Views

I am developing a project where a function makes use of an optional procedure pointer. Since the procedure pointer is OPTIONAL, an explicit interface is required. In other situations where I needed an interface block I typically made use of the auto-generated interface obtained during compilation of the procedure of interest. In my current case, this doesn't work as the compiler gives an error when compiling the interface block (as a module). For example, given the main program foo:

program foo
   use tfunct
   use BAR__genmod
   implicit none

   abstract interface
      function test(a, b, c)
         real                :: test
         integer, intent(IN) :: a
         real, intent(IN)    :: b
         real, intent(IN)    :: c
      end function test
   end interface

   integer a
   real b, c, d
   procedure(test), pointer :: ofunc

   ofunc => aTest

   a = 2; b = 5.0; c = 7.0
   call bar(a,b,c,d,ofunc)
   print *,d

   call bar(a,b,c,d)
   print *,d

end program foo

The function bar is in a separated module with the auto-generated interface BAR__genmod:

!COMPILER-GENERATED INTERFACE MODULE: Tue Nov 14 11:36:38 2017
! This source file is for reference only and may not completely
! represent the generated interface used by the compiler.
MODULE BAR__genmod
   INTERFACE 
   SUBROUTINE BAR(A,B,C,X,OFUNC)
      INTEGER(KIND=4), INTENT(IN) :: A
      REAL(KIND=4), INTENT(IN) :: B
      REAL(KIND=4), INTENT(IN) :: C
      REAL(KIND=4), INTENT(OUT) :: X
      INTERFACE 
         FUNCTION OFUNC(A,B,C)
         INTEGER(KIND=4), INTENT(IN) :: A
         REAL(KIND=4), INTENT(IN) :: B
         REAL(KIND=4), INTENT(IN) :: C
         REAL(KIND=4) ,OPTIONAL :: OFUNC
         END FUNCTION OFUNC
      END INTERFACE 
   END SUBROUTINE BAR
   END INTERFACE 
END MODULE BAR__genmod

and the ofunc points to aTest in the module tfunct, and aTest has the same interface as shown in the two files above.

When compiled, I get the following: error #6413: This global name is invalid in this context.   [OFUNC]

I understand the error, but don't understand how the compiler generated an invalid interface nor what the proper interface would look like. I realize that as a fallback I could always access the function foo through a module and use association, but I rather not use that approach.

Any insight would be appreciated.

 

0 Kudos
1 Solution
JVanB
Valued Contributor II
208 Views

Actually, we need the specification part of subroutine bar to be able to write a proper interface. Assuming dummy argument OFUNC to procedure bar is actually a procedure pointer and not a procedure, the interface body should look something like this:

!COMPILER-GENERATED INTERFACE MODULE: Tue Nov 14 11:36:38 2017
! This source file is for reference only and may not completely
! represent the generated interface used by the compiler.
MODULE BAR__genmod
   INTERFACE 
   SUBROUTINE BAR(A,B,C,X,OFUNC)
      INTEGER(KIND=4), INTENT(IN) :: A
      REAL(KIND=4), INTENT(IN) :: B
      REAL(KIND=4), INTENT(IN) :: C
      REAL(KIND=4), INTENT(OUT) :: X
      ABSTRACT INTERFACE
         FUNCTION OFUNC_PROTOTYPE(A,B,C)
         INTEGER(KIND=4), INTENT(IN) :: A
         REAL(KIND=4), INTENT(IN) :: B
         REAL(KIND=4), INTENT(IN) :: C
         REAL(KIND=4) :: OFUNC_PROTOTYPE
         END FUNCTION OFUNC_PROTOTYPE
      END INTERFACE
      PROCEDURE(OFUNC_PROTOTYPE), OPTIONAL, POINTER :: OFUNC
   END SUBROUTINE BAR
   END INTERFACE 
END MODULE BAR__genmod

 

View solution in original post

4 Replies
JVanB
Valued Contributor II
209 Views

Actually, we need the specification part of subroutine bar to be able to write a proper interface. Assuming dummy argument OFUNC to procedure bar is actually a procedure pointer and not a procedure, the interface body should look something like this:

!COMPILER-GENERATED INTERFACE MODULE: Tue Nov 14 11:36:38 2017
! This source file is for reference only and may not completely
! represent the generated interface used by the compiler.
MODULE BAR__genmod
   INTERFACE 
   SUBROUTINE BAR(A,B,C,X,OFUNC)
      INTEGER(KIND=4), INTENT(IN) :: A
      REAL(KIND=4), INTENT(IN) :: B
      REAL(KIND=4), INTENT(IN) :: C
      REAL(KIND=4), INTENT(OUT) :: X
      ABSTRACT INTERFACE
         FUNCTION OFUNC_PROTOTYPE(A,B,C)
         INTEGER(KIND=4), INTENT(IN) :: A
         REAL(KIND=4), INTENT(IN) :: B
         REAL(KIND=4), INTENT(IN) :: C
         REAL(KIND=4) :: OFUNC_PROTOTYPE
         END FUNCTION OFUNC_PROTOTYPE
      END INTERFACE
      PROCEDURE(OFUNC_PROTOTYPE), OPTIONAL, POINTER :: OFUNC
   END SUBROUTINE BAR
   END INTERFACE 
END MODULE BAR__genmod

 

View solution in original post

Michael_D_11
Beginner
208 Views
OFUNC is a procedure pointer and your suggestion works perfectly. Thanks much for the assistance - I doubt I would have ever stumbled on this way of writing the interface.
JVanB
Valued Contributor II
208 Views

Cool. Another syntax that I think should work is:

!COMPILER-GENERATED INTERFACE MODULE: Tue Nov 14 11:36:38 2017
! This source file is for reference only and may not completely
! represent the generated interface used by the compiler.
MODULE BAR__genmod
   INTERFACE 
   SUBROUTINE BAR(A,B,C,X,OFUNC)
      INTEGER(KIND=4), INTENT(IN) :: A
      REAL(KIND=4), INTENT(IN) :: B
      REAL(KIND=4), INTENT(IN) :: C
      REAL(KIND=4), INTENT(OUT) :: X
      INTERFACE
         FUNCTION OFUNC(A,B,C)
         INTEGER(KIND=4), INTENT(IN) :: A
         REAL(KIND=4), INTENT(IN) :: B
         REAL(KIND=4), INTENT(IN) :: C
         REAL(KIND=4) :: OFUNC
         END FUNCTION OFUNC
      END INTERFACE
      OPTIONAL :: OFUNC
      POINTER :: OFUNC
   END SUBROUTINE BAR
   END INTERFACE 
END MODULE BAR__genmod

The above is accepted by gfortran but ifort 16.0.2 produces the following error message:

bar1.f90(20): error #6429: This name has already been used as a dummy function n
ame.   [OFUNC]
      POINTER :: OFUNC
-----------------^
compilation aborted for bar1.f90 (code 1)

Is this fixed in the latest version of ifort?

 

andrew_4619
Honored Contributor I
208 Views

In answer to #4, No

Compiling with Intel(R) Visual Fortran Compiler 18.0.0.124 [IA-32]...
dbug_parms.f90
C:\Users\...\dbug_parms\dbug_parms.f90(37): error #6429: This name has already 
been used as a dummy function name.   [OFUNC]
compilation aborted for C:\Users\...\dbug_parms\dbug_parms.f90 (code 1)

 

Reply