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

Still about generic interface from external procedures

rudi-gaelzer
New Contributor I
692 Views

I would like to put a question to those that work with the J3 and other committees that determine the standard.

Related to this thread:

https://software.intel.com/en-us/forums/intel-fortran-compiler-for-linux-and-mac-os-x/topic/593516

If I define a generic interface such as below:

module create_gen_int
implicit none
interface fun_gen
   real function fun_int(n)
   integer, intent(in) :: n
   end function fun_int
!***
   real function fun_real(x)
   real, intent(in) :: x
   end function fun_real
end interface fun_gen
end module create_gen_int

The code compiles without any problems.

However, if I move the interfaces to a separate block inside the same module and use "module procedure" in the generic, such as:

module create_gen_int2
implicit none
interface 
   real function fun_int(n)
   integer, intent(in) :: n
   end function fun_int
!***
   real function fun_real(x)
   real, intent(in) :: x
   end function fun_real
end interface
!
interface fun_gen
   module procedure fun_int
   module procedure fun_real
end interface fun_gen
end module create_gen_int2

This is not accepted by the standard.  Ifort V. 16.0.3.210 generates the error:

create_gen_int2.f90(4): error #7950: Procedure name in MODULE PROCEDURE statement must be the name of accessible module procedure.   [FUN_INT]
   real function fun_int(n)

Gfortran also complains with an error message.

OTOH, if I move the interfaces to a separate module, such as:

module create_ints
implicit none
interface 
   real function fun_int(n)
   integer, intent(in) :: n
   end function fun_int
!***
   real function fun_real(x)
   real, intent(in) :: x
   end function fun_real
end interface
end module create_ints
!*********************************
module create_gen_int3
use create_ints
implicit none
interface fun_gen
   module procedure fun_int
   module procedure fun_real
end interface fun_gen
end module create_gen_int3

This is also not valid according to the standard.  Ifort now issues the error:

create_gen_int3.f90(18): error #7950: Procedure name in MODULE PROCEDURE statement must be the name of accessible module procedure.   [FUN_INT]
   module procedure fun_int

My question is, why don't the standard accept the last two examples?  Since all of them do essentially the same thing?

 

0 Kudos
1 Solution
IanH
Honored Contributor II
692 Views

In the cases where you are getting an error - the compiler wants the procedures to be module procedures ... because that's what the code specifies!

Just delete the module keyword...

module create_gen_int2
implicit none
interface 
   real function fun_int(n)
   integer, intent(in) :: n
   end function fun_int
!***
   real function fun_real(x)
   real, intent(in) :: x
   end function fun_real
end interface
!
interface fun_gen
   procedure fun_int     !<--- No module keyword.
   procedure fun_real    !<--- No module keyword.
end interface fun_gen
end module create_gen_int2

 

View solution in original post

0 Kudos
6 Replies
FortranFan
Honored Contributor II
692 Views

Note the standard says in "C1507 (R1506) If MODULE appears in a procedure-stmt, each procedure-name in that statement shall denote a module procedure."

And module procedure is "3.112.4 module procedure: procedure defined by a module subprogram, or a procedure provided by an intrinsic module (R1408)"

Then for module subprogram it says "3.142.3 module subprogram subprogram that is contained in a module or submodule but is not an internal subprogram"

Note per your code snippet in the original post, subprograms such as fun_int and fun_real are not contained in any module or submodule, nor are they part of any intrinsic module.  Hence the compiler error.

Now say you had code like so:

module some_implementation

   implicit none

   private

   public :: fun_int
   public :: fun_real

contains

   real function fun_int(n)
      integer, intent(in) :: n
      ! actual code elided; arbitrary intruction below
      fun_int = real(n)
   end function fun_int

   real function fun_real(x)
      real, intent(in) :: x
      ! actual code elided; arbitrary intruction below
      fun_real = x + 1.0
   end function fun_real

end module

module create_gen_int2

   use some_implementation, only : fun_int, fun_real

   implicit none

   interface fun_gen
      module procedure fun_int
      module procedure fun_real
   end interface fun_gen

end module create_gen_int2

Then the compilation will complete without errors on account of the processor being able to recognize the module subprograms of fun_int and fun_real from the module, some_implementation.  But of course, a convenient coding practice is to define the generic interface in the same module as the implementation.

For situations where subprogram implementations need to be elsewhere, meaning not in the module where the generic interface is established, for whatever reason (large files, compilation cascades, etc.), it is worth considering the SUBMODULEs feature introduced starting with Fortran 2008 in one's code design:

https://software.intel.com/en-us/blogs/2015/07/07/doctor-fortran-in-we-all-live-in-a-yellow-submodule

0 Kudos
rudi-gaelzer
New Contributor I
692 Views

Dear FortranFan,

your code will certainly work because in the module some_implementation you're not only defining the interfaces to fun_int and fun_real but actually defining the procedures.

My question is why on my first example it is acceptable for the standard to define a generic interface that contains only the (explicit) interfaces of these routines in its body, whereas in the other two examples, although the very same interfaces are accessible to the module containing the generic, the standard considers the code wrong.

Perhaps I'm not reading with sufficient care the snippets of the standard you mentioned:

FortranFan wrote:

Note the standard says in "C1507 (R1506) If MODULE appears in a procedure-stmt, each procedure-name in that statement shall denote a module procedure."

And module procedure is "3.112.4 module procedure: procedure defined by a module subprogram, or a procedure provided by an intrinsic module (R1408)"

Then for module subprogram it says "3.142.3 module subprogram subprogram that is contained in a module or submodule but is not an internal subprogram"

But according to these regulations, even the first example should not be accepted by the standard, or am I wrong?

About your other suggestion:

FortranFan wrote:

For situations where subprogram implementations need to be elsewhere, meaning not in the module where the generic interface is established, for whatever reason (large files, compilation cascades, etc.), it is worth considering the SUBMODULEs feature introduced starting with Fortran 2008 in one's code design:

https://software.intel.com/en-us/blogs/2015/07/07/doctor-fortran-in-we-a...

I'm fully aware of SUBMODULES and use them whenever possible.  I think they're a terrific (and necessary) improvement to the language.

Alas, for my specific application they won't work because I want to define a generic interface to C functions (via the iso_c_binding module).  I wanted to create a specific module containing only the interfaces to the C functions and make them accessible to the module containing the generic, in a way similar to my third example.  But it seems that the only way to implement this is doing something similar to my first example.

Anyway, thanks for the input.

0 Kudos
rudi-gaelzer
New Contributor I
692 Views

About my last comment:

rudi-gaelzer wrote:

Perhaps I'm not reading with sufficient care the snippets of the standard you mentioned:

...

But according to these regulations, even the first example should not be accepted by the standard, or am I wrong?

Scratch that.  The first example does not contain the clause "module procedure" (duh...)...

The rest still stands.

0 Kudos
FortranFan
Honored Contributor II
692 Views

rudi-gaelzer wrote:

.. Alas, for my specific application they won't work because I want to define a generic interface to C functions (via the iso_c_binding module).  I wanted to create a specific module containing only the interfaces to the C functions and make them accessible to the module containing the generic, ..

When I mentioned the scenario of "subprogram implementations need to be elsewhere" I was still considering code in "CONTAINS" section of some Fortran MODULE somewhere.  But you are bringing up code defined by means other than Fortran i.e., C functions.  Barring some "clever" programming which I stay from, generic interfaces are not possible unless you wrap those other procedures in Fortran, a seemingly wasted effort.  Besides those C functions would be consumed in C calling programs explicitly, not generically.  It might help to keep it that way in Fortran code also. 

0 Kudos
IanH
Honored Contributor II
693 Views

In the cases where you are getting an error - the compiler wants the procedures to be module procedures ... because that's what the code specifies!

Just delete the module keyword...

module create_gen_int2
implicit none
interface 
   real function fun_int(n)
   integer, intent(in) :: n
   end function fun_int
!***
   real function fun_real(x)
   real, intent(in) :: x
   end function fun_real
end interface
!
interface fun_gen
   procedure fun_int     !<--- No module keyword.
   procedure fun_real    !<--- No module keyword.
end interface fun_gen
end module create_gen_int2

 

0 Kudos
rudi-gaelzer
New Contributor I
692 Views

Indeed that seems to work.

Thanks for the tip.

ianh wrote:

Just delete the module keyword...

module create_gen_int2
implicit none
interface 
   real function fun_int(n)
   integer, intent(in) :: n
   end function fun_int
!***
   real function fun_real(x)
   real, intent(in) :: x
   end function fun_real
end interface
!
interface fun_gen
   procedure fun_int     !<--- No module keyword.
   procedure fun_real    !<--- No module keyword.
end interface fun_gen
end module create_gen_int2

 

0 Kudos
Reply