We have a large code base that works well with Intel 17.x and gfortran. I recently upgraded to Intel 18 and all tests are now broken. For some reason, methods on a polymorphic object are not not being called properly. Instead of calling the method for an extended type, the program is calling the method for the parent type. It would be some work to make a small example, so at this point and am trying to see if this bug has been detected.
A regression is always plausible (see threads such as https://software.intel.com/en-us/forums/intel-fortran-compiler-for-linux-and-mac-os-x/topic/752348#n... but then there is also the possibility your extended types are relying on erroneous implementations of features introduced in Fortran starting with the 2003 standard which might have since been corrected in the compiler(s) to make them conform to the standard.
Good luck but note the chances are you will need a complete reproducer to get to the bottom of the problem.
I seem to have found the issue. I think it is a bug in Intel Fortran 18, thought I can't be sure. The following code is what I was using in a parent class (derived type with type-bound procedures). I also had child classes (extended types) that overrode the read_int_array and read_dbl_array procedures. They also had private tags. And this code has worked fine for a long time and with a variety of compilers. Well it turns out the private tags were causing the problem with Intel Fortran 18. With the private tags, the procedures were not overridden, and instead the parent class procedures were executed. It could be that I was doing it wrong before, but it seems like a bug to me. Thought I would post in case someone else runs into this.
Code that does not work on Intel Fortran 18:
procedure, private :: read_int_array procedure, private :: read_dbl_array generic, public :: read_grid_array => read_int_array, read_dbl_array
Fix is to remove private tags in parent and child classes procedure :: read_int_array procedure :: read_dbl_array generic, public :: read_grid_array => read_int_array, read_dbl_array
The most likely explanation is that you have run afoul of a change to the Fortran 2003 semantics that was introduced as a corrigendum to the standard. It significantly changed the behaviour of PRIVATE type-bound procedures. In effect, it prevents overriding a type-bound procedure outside the module that declares the type and its type-bound procedure.
An attempt to do this effectively only adds a new type-bound procedure to the new type that can only be invoked if the declared type of the object is the extension type.
Intel Fortran implemented this corrigendum to the standard with the 18.0 release. At some point I heard that a compiler option may exist to revert to the old (now non-conforming) behaviour but I wasn't able to find it.
Thank you people. That makes sense. The parent and child types are in different modules. I can see why the PRIVATE attribute can cause problems. Glad I was able to isolate it without too much trouble, and fortunately we didn't use that pattern throughout our code. Thanks again!
So I went ahead and mocked something up to demonstrate this issue, and it does look like there is something wrong. The program below produces:
parent meth1; parent meth2; parent meth1; parent meth2
which suggests that something is not right with the method overloading. Clearly the second two print statements should read child meth1 and child meth2.
When the private attributes are removed for both the parent and child procedures then the statements read ;
parent meth1; parent meth2; child meth1; child meth2
Hopefully I haven't done something obviously wrong here.
module ParentModule implicit none type ParentType contains procedure, private :: meth1 procedure, private :: meth2 generic, public :: meth => meth1, meth2 end type ParentType contains subroutine meth1(this, i) class(ParentType) :: this integer, intent(in) :: i print *, 'parent meth1' end subroutine meth1 subroutine meth2(this, d) class(ParentType) :: this double precision, intent(in) :: d print *, 'parent meth2' end subroutine meth2 end module ParentModule module ChildModule use ParentModule, only: ParentType implicit none type, extends(ParentType) :: ChildType contains procedure, private :: meth1 procedure, private :: meth2 end type ChildType contains subroutine meth1(this, i) class(ChildType) :: this integer, intent(in) :: i print *, 'child meth1' end subroutine meth1 subroutine meth2(this, d) class(ChildType) :: this double precision, intent(in) :: d print *, 'child meth2' end subroutine meth2 end module ChildModule program test use ParentModule, only: ParentType use ChildModule, only: ChildType implicit none type(ParentType) :: p type(ChildType) :: c call p%meth(1) call p%meth(1.d0) call c%meth(1) call c%meth(1.d0) print*, 'done' end
Things are working as expected.
The main program calls the generic binding `meth`, which is defined in the parent type, with specific bindings that are also in the parent type. Those specific bindings are not overridden - the bindings of the same name in the child type are a separate pair, because the child type is being defined in a separate module and the original bindings in the parent type are private as discussed above. Call the generic - get the specific bindings as defined in the parent type.