Incorrect behavior with inheritance when using submodules?

Incorrect behavior with inheritance when using submodules?

Hello,

 

 

I have a test program which I believe is producing correct answers when compiled with ifort Version 18.0.0.128 Build 20170811 and incorrect answers when compiled with the newer ifort Version 18.0.1.163 Build 20171018.  In both cases, the code compiles with no warnings or errors.

I believe the code is valid, although it is certainly possible I am misunderstanding how these features work.  The problem occurs when I use a submodule to separate the implementation from the interfaces, and I have a type which extends another, and both types have a procedure with the same name.  If I don't use a submodule, and put all declarations in the "contains" section, it works fine.  Here is a reproducer:

!-------------------------------------------------------------------------------
! Module Model
!-------------------------------------------------------------------------------
module Model

  implicit none

  private

  !-------------------------------------------------------------------------------
  ! parent_model_type
  !-------------------------------------------------------------------------------
  public :: parent_model_type

  type :: parent_model_type
    private
  contains
    procedure :: go
  end type parent_model_type

  !-------------------------------------------------------------------------------
  ! child_model_type
  !-------------------------------------------------------------------------------
  public :: child_model_type

  type, extends(parent_model_type) :: child_model_type
    private
  contains
    procedure :: go => go_child
  end type child_model_type

  interface
    module subroutine go_child(this)
      class(child_model_type) :: this
    end subroutine go_child
  end interface

contains

  !-----------------------------------------------------------------------
  ! go
  !-----------------------------------------------------------------------
  subroutine go(this)

    class(parent_model_type) :: this

    print *, "Parent model is going"

  end subroutine go

end module Model


!-------------------------------------------------------------------------------
! Submodule Child_Model
!-------------------------------------------------------------------------------
submodule(Model) Child_Model

  implicit none

contains

  !-----------------------------------------------------------------------
  ! go_child
  !-----------------------------------------------------------------------
  module subroutine go_child(this)

    class(child_model_type) :: this

    print *,"Child model is going"

  end subroutine go_child

end submodule Child_Model


!-------------------------------------------------------------------------------
! Program test
!-------------------------------------------------------------------------------
program Test

  use Model, only : parent_model_type, child_model_type

  implicit none

  type(parent_model_type) :: parent
  type(child_model_type)  :: child

  call parent%go()
  call child%go()

end program Test

When I run this code compiled with ifort Version 18.0.1.163 Build 20171018 I get the wrong answer:

$ ./test.exe
 Parent model is going
 Parent model is going
$

When I run this code compiled with ifort Version 18.0.0.128 Build 20170811 I get the correct answer:

$ ./test.exe
 Parent model is going
 Child model is going
$

Is this a bug in the newer 18.1.163 compiler?  Or am I doing something wrong?

Thank you for your time,

Chris

7 posts / 0 new
Last post
For more complete information about compiler optimizations, see our Optimization Notice.

Quote:

Christopher H. wrote:

.. I believe the code is valid, ..

Is this a bug in the newer 18.1.163 compiler? ..

I agree your code is valid.  So I firmly believe this is a bug in update 1 to Intel Fortran compiler version 18.0, an unfortunate regression.

I suggest you submit an incident at the Intel Online Service Center (OSC):

https://supporttickets.intel.com/?lang=en-US

 

Thank you very much for the quick feedback.  There is variation of this that produces a link error.  I think it's very closely related to what I submitted above.  If you have a child type that has a procedure which the parent does not have, the code won't link with version 18.0.1.163 Build 20171018:

!-------------------------------------------------------------------------------
! Module Model
!-------------------------------------------------------------------------------
module Model

  implicit none

  private

  !-------------------------------------------------------------------------------
  ! parent_model_type
  !-------------------------------------------------------------------------------
  public :: parent_model_type

  type :: parent_model_type
    private
  contains
  end type parent_model_type

  !-------------------------------------------------------------------------------
  ! child1_model_type
  !-------------------------------------------------------------------------------
  public :: child1_model_type

  type, extends(parent_model_type) :: child1_model_type
    private
  contains
    procedure :: go => go_child1
  end type child1_model_type

  interface
    module subroutine go_child1(this)
      class(child1_model_type) :: this
    end subroutine go_child1
  end interface

  !-------------------------------------------------------------------------------
  ! child2_model_type
  !-------------------------------------------------------------------------------
  public :: child2_model_type

  type, extends(parent_model_type) :: child2_model_type
    private
  contains
    procedure :: go => go_child2
  end type child2_model_type

  interface
    module subroutine go_child2(this)
      class(child2_model_type) :: this
    end subroutine go_child2
  end interface

contains

end module Model


!-------------------------------------------------------------------------------
! Submodule Child1_Model
!-------------------------------------------------------------------------------
submodule(Model) Child1_Model

  implicit none

contains

  !-----------------------------------------------------------------------
  ! go_child1
  !-----------------------------------------------------------------------
  module subroutine go_child1(this)

    class(child1_model_type) :: this

    print *,"Child1 model is going"

  end subroutine go_child1

end submodule Child1_Model


!-------------------------------------------------------------------------------
! Submodule Child2_Model
!-------------------------------------------------------------------------------
submodule(Model) Child2_Model

  implicit none

contains

  !-----------------------------------------------------------------------
  ! go_child2
  !-----------------------------------------------------------------------
  module subroutine go_child2(this)

    class(child2_model_type) :: this

    print *,"Child2 model is going"

  end subroutine go_child2

end submodule Child2_Model


!-------------------------------------------------------------------------------
! Program test
!-------------------------------------------------------------------------------
program Test

  use Model, only : child1_model_type, child2_model_type

  implicit none

  type(child1_model_type)  :: child1
  type(child2_model_type)  :: child2

  call child1%go()
  call child2%go()

end program Test

ifort version 18.0.1.163 Build 20171018 produces this link error:

$ make
ifort -g -traceback -O2 -o test.exe test.f90
/tmp/ifortDczkUi.o: In function `MAIN__':
/home/Christopher.W.Harrop/test/intel_bugs/bug_2/test.f90:117: undefined reference to `model_mp_go_'
/home/Christopher.W.Harrop/test/intel_bugs/bug_2/test.f90:118: undefined reference to `model_mp_go_'

ifort version 18.0.0.128 Build 20170811 builds and runs the code correctly:

$ make
ifort -g -traceback -O2 -o test.exe test.f90
$ ./test.exe
 Child1 model is going
 Child2 model is going
$

Although this is a very similar scenario, the behavior is a bit different.

 

@Christopher H.,

I suggest you include both the cases in your incident submission at the OSC or submit two different incidents to ensure the Intel Fortran team's attention to both the issues.

Btw your second case appears similar to this other issue reported with SUBMODULEs at the Windows forum:

https://software.intel.com/en-us/node/740567#new

Sitting afar I get the impression Intel Fortran team has major difficulties developing reliable test suites with adequate coverage of features introduced in the Fortran standard since the age-old Fortran 90/95 revision.  Their regression testing of new compiler versions suffers significantly as a result.  SUBMODULE facility that got added starting with Fortran 2008 is but one latest example of this casualty.

Thank you again for helping verify I'm not going crazy.  Much appreciated.  I will proceed with reporting both cases.

I have similar problems with submodules using ifort 18.0.1 as well. Things compile and work just fine with 18.0. The amount and severity of regressions in the 2017 and 2018 versions is simply ridiculous.

Hi same for me.

As FortranFan said a test case would have shown this. And my OSD filed ticket for an ICE error in PSXE2018 contains such a test case... (https://software.intel.com/en-us/node/740567). There are many more here, I suggest.

 

Leave a Comment

Please sign in to add a comment. Not a member? Join today