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

New bug (or feature) in ifort 17.0.x with procedure pointer: error #6138: An explicit interface is required in this context

Joachim_Herb
Beginner
585 Views

Starting with ifort 17.0.0 code using (a certain definition of) procedure pointers does not compile anymore. It works with ifort <= 16.0.4 (tested e.g. with ifort 16.0.4, 12.1.0). The problem is reproducible for both, Linux and Windows.

module impl_list__
  implicit none

  type, public :: Node_t
    integer :: val
    procedure(), nopass, pointer :: cloneProc_int
  end type

  interface
    subroutine NodeCloner( tgt, src )
      import Node_t
      type(Node_t), pointer, intent(out) :: tgt
      type(Node_t),           intent(in) :: src
    end subroutine
  end interface

  procedure(), pointer :: cloneProc => null()
  type(Node_t) :: node

end module

  subroutine func()
    use impl_list__
    implicit none
    procedure(NodeCloner), pointer :: cloneNode, cloneNode_int

    cloneNode_int => node%cloneProc_int
    cloneNode => cloneProc
  end subroutine

 

Here are my different tests with different compilers:

~/winhpc> gfortran --version
GNU Fortran 5.2.0
Copyright (C) 2015 Free Software Foundation, Inc.
~/winhpc> gcc -c list_test_v2.f90
list_test_v2.f90:29:17:

     cloneNode => cloneProc
                 1
Error: Explicit interface required for ‘cloneproc’ at (1): pointer argument

~/winhpc> ifort --version
ifort (IFORT) 16.0.4 20160811
Copyright (C) 1985-2016 Intel Corporation.  All rights reserved.
~/winhpc> ifort -c list_test_v2.f90
~/winhpc> ifort --version
ifort (IFORT) 17.0.0 20160721
Copyright (C) 1985-2016 Intel Corporation.  All rights reserved.
~/winhpc> ifort -c list_test_v2.f90
list_test_v2.f90(28): error #6138: An explicit interface is required in this context.   [CLONENODE_INT]
    cloneNode_int => node%cloneProc_int
----^
list_test_v2.f90(29): error #6138: An explicit interface is required in this context.   [CLONENODE]
    cloneNode => cloneProc
----^
compilation aborted for list_test_v2.f90 (code 1)
~/winhpc> ifort --version
ifort (IFORT) 12.1.0 20111011
Copyright (C) 1985-2011 Intel Corporation.  All rights reserved.
~/winhpc> ifort -c list_test_v2.f90

The code tests the use of two procedure pointers. One is stored inside a user defined type, the other is defined within the module. gfortran in all version accepts the pointer inside the user defined type but not the one defined directly in the module. Ifort before version 17.0.0 accepts both pointers. The compilation fails for both pointers if the version is 17.0.0 or newer (also tested 17.0.2).

Is this an intended behavior? If so, what would be the correct way to handle such pointers? Otherwise, is this a bug?

 

0 Kudos
6 Replies
Steve_Lionel
Honored Contributor III
585 Views

I would argue that the gfortran you're using has a bug in that it doesn't complain about both pointer assignments. Both of the procedure pointer targets here have implicit interface (that's what PROCEDURE() gets you), and the pointers in question have explicit interface. The standard says:

If the pointer object has an explicit interface, its characteristics shall be the same as the pointer target except that the pointer target may be pure even if the pointer object is not pure and the pointer target may be an elemental intrinsic procedure even if the pointer object is not elemental.

Maybe you can fudge something with C_FUNLOC and C_F_PROCPOINTER, though you're still violating the rule that the interfaces must match.

Or you could use explicit interfaces everywhere (a better approach).

0 Kudos
Zapp_O_
Beginner
585 Views

Same problem here ... which I had to "fix" for ifort 17 with C_F_PROCPOINTER.
Steve, so this means it used to be a bug in earlier ifort versions accepting this assignment and from now it's just illegal to do such casts, right?

But then what is the suggested "Fortran-way" to store a generic procedure pointer and to cast it once before doing the call? Of course it would be the cleaner approach (here I'd say "cleaner", not "better") to use explicit interfaces everywhere. However in reality this is simply not possible without making the number of necessary interface definitions explode - what a nightmare! So in order to avoid that, yes sir, I prefer the fudge-way using C_F_PROCPOINTER, and I think it's kind of strange that I've to apply the C-compatibility module to work around a shortcoming of the language (as I understand it).

Well I see that since Fortran is trying to go the object-oriented way and considering the consequent use of classes it would not be necessary to do such unclean casts, but again, real life is different: honestly, up to now one just can't rely on OOP-features in Fortran since the compilers still have too many bugs or things that are not yet supported. In software projects where it's necessary to share code with others this is a real show-stopper and I can't force others to update their compiler-licenses just to compile my code.
Therefore, for me there's still no choice but to stick with poor-mans OOP - although it appears to be kind of illegal now.

0 Kudos
Steve_Lionel
Honored Contributor III
585 Views

Yes, it was a bug before that this error was not detected.

If you insist on operating with the blade guard removed, then don't use explicit interfaces for the procedure pointer. Just don't come back here complaining when things go awry because you made an argument match error.

Or as I suggested earlier, use C_LOC to store the pointer and C_F_PROCPOINTER to assign it. That's a little better as you'll be able to use an explicit interface for the pointer. I see "OOP" tossed around everywhere, but everybody seems to have a different notion of what it means. It would be better to work within the framework of the language, as fussy as you might think it if you are used to the exposed blade of C and C++.

0 Kudos
Zapp_O_
Beginner
585 Views

Thanks for the clarification! Of course you're right, removing the guards means that I'm responsible for doing the call right and I'd be better off using explicit interfaces. Sorry if it sounded rude! I just wanted to explain the reasons for doing it anyways. Integrating legacy code suitably for multiple compilers can be challenging sometimes!

0 Kudos
IanH
Honored Contributor II
585 Views

I think the relevant restriction in the standard is actually the paragraph following the one that Steve's quoted - "If the characteristics of the pointer object or the pointer target are such that an explicit interface is required, both the pointer object and the pointer target shall have an explicit interface" (F2008 7.2.2.4p4).  As the gfortran error message in the original post identifies, the characteristics of the pointer object include a dummy argument that has the pointer attribute, hence the pointer object requires an explicit interface, hence both sides of the pointer assignment require an explicit interface.

In the absence of a characteristic of a procedure that requires an explicit interface, having an explicit interface for the pointer side of an procedure pointer assignment does not require the target side to also have an explicit interface.  What's required is for the characteristics to match, explicitness of the interface of a procedure is separate to its characteristics.

Its hard to answer "what is the correct way to handle such pointers" without knowing more about what the programmer is trying to do.

Edit to also note that applying C_FUNLOC to procedures that are not interoperable requires Fortran 2015.  If you are concerned about broad support for your code, writing to a standard that has not yet been published is questionable.

0 Kudos
Joachim_Herb
Beginner
585 Views

Thank you for your answers.

0 Kudos
Reply