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

Bug using an array of derived-type with an polymorphic component

FlyingHermes
New Contributor I
386 Views

Hi,

I've encountered a compiler bug when using an array of derived-type with an polymorphic component.

I'm using ifort version 13.1.1.

There is the code which produce the error:

[fortran]Module MyModule
  implicit none
  private
  public        ::      MyType
 
  Type  ,abstract              ::      Object
  End Type
 
  Type                         ::      MyType
    integer                    ::      Num
    class(Object) ,allocatable ::      Data
  End Type
 
  Interface             MyType
    Module Procedure    Construct_MyType
  End Interface

  contains

Function Construct_MyType( Num ) result(This)
  implicit none
  type(MyType)                                  ::      This
  integer       ,optional       ,intent(in)     ::      Num
  This%Num   =       1
  if ( present(Num) ) This%Num = Num
End Function

End Module

Program Main
  use MyModule   ,only:  MyType
  implicit none

  type(MyType)  ,dimension(:)   ,allocatable    ::      Vars
  type(MyType)                                  ::      Var1, Var2  
  integer                                       ::      iVar
 
  write(*,"(/,'[Main]: Method 1:')")
  Var1          =       MyType( Num = 1 )                               ! Var1 has the correct value for the "Num" component
  Var2          =       MyType( Num = 2 )                               ! Var2 has the correct value for the "Num" component
  write(*,"('[Main]: Var1%Num = ',i3)") Var1%Num
  write(*,"('[Main]: Var2%Num = ',i3)") Var2%Num
 
 
  write(*,"(/,'[Main]: Method 2:')")
  allocate( Vars(2) )
  Vars(1)       =       MyType( Num = 1 )                               ! Vars(1) has the correct value for the "Num" component
  write(*,"('[Main]: Vars(1)%Num = ',i3)") Vars(1)%Num
  Vars(2)       =       MyType( Num = 2 )  
  write(*,"('[Main]: Vars(2)%Num = ',i3)") Vars(2)%Num                  ! Vars(2) has the correct value for the "Num" component BUT VALUE IN VARS(1) HAS BEEN CHANGED !!!
 
  write(*,"('[Main]: Vars(1)%Num = ',i3)") Vars(1)%Num
  write(*,"('[Main]: Vars(2)%Num = ',i3)") Vars(2)%Num
 
 
!   write(*,"(/,'[Main]: Method 3:')")                                    ! Same results than with method 2, ie erroneous
!   Vars(1)    =       Var1                                               
!   write(*,"('[Main]: Vars(1)%Num = ',i3)") Vars(1)%Num
!   Vars(2)    =       Var2
!   write(*,"('[Main]: Vars(2)%Num = ',i3)") Vars(2)%Num
!   write(*,"('[Main]: Vars(1)%Num = ',i3)") Vars(1)%Num
!   write(*,"('[Main]: Vars(2)%Num = ',i3)") Vars(2)%Num

End Program

[/fortran]

the output of the code is:

[Main]: Method 1:
[Main]: Var1%Num =   1
[Main]: Var2%Num =   2

[Main]: Method 2:
[Main]: Vars(1)%Num =   1
[Main]: Vars(2)%Num =   2
[Main]: Vars(1)%Num =   2
[Main]: Vars(2)%Num =   2

As one can see, in Method 2, Vars(1)%Num be equal to 1 which is not the case.

Insead, it has the value of the last element of the array Vars which has been affected.

 

0 Kudos
3 Replies
FlyingHermes
New Contributor I
386 Views

Here is more info on this issue.

I've tried to:

  1. to use an automatic array vs an allocatable arrays
  2. to use a subroutine vs a function constructor

The source code is:

[fortran]

Module MyModule

  implicit none
 
  private
 
  public        ::      MyType
  public        ::      Construct_MyType_Fun
  public        ::      Construct_MyType_Sub
 
  Type  ,abstract              ::      Object
  End Type
 
  Type                         ::      MyType
    integer                    ::      Num
    class(Object) ,allocatable ::      Data
  End Type
 
  Interface             MyType
    Module Procedure    Construct_MyType_Fun
  End Interface

  contains

Function Construct_MyType_Fun( Num ) result(This)
  implicit none
  type(MyType)                                  ::      This
  integer       ,optional       ,intent(in)     ::      Num
  This%Num   =       1
  if ( present(Num) ) This%Num = Num
End Function

Subroutine Construct_MyType_Sub( This, Num )
  implicit none
  type(MyType)                  ,intent(out)    ::      This
  integer       ,optional       ,intent(in)     ::      Num
  This%Num   =       1
  if ( present(Num) ) This%Num = Num
End Subroutine

End Module

Program Main

  use MyModule   ,only:  MyType, Construct_MyType_Fun, Construct_MyType_Sub
 
  implicit none
 
  type(MyType)  ,dimension(2)                   ::      Vars_Auto
  type(MyType)  ,dimension(:)   ,allocatable    ::      Vars_Allo
 
  allocate( Vars_Allo(2) )
 
  write(*,"('[Main]: size(Vars_Auto) = ',i0)") size(Vars_Auto)
  write(*,"('[Main]: size(Vars_Allo) = ',i0)") size(Vars_Allo)
 
 
  write(*,"(/,'[Main]: Constructing Vars_Allo using Construct_MyType_Sub:')")
  call Construct_MyType_Sub( Vars_Allo(1), Num = 1 )
  write(*,"('[Main]: Vars_Allo(1)%Num = ',i3)") Vars_Allo(1)%Num
  call Construct_MyType_Sub( Vars_Allo(2), Num = 2 )
  write(*,"('[Main]: Vars_Allo(2)%Num = ',i3)") Vars_Allo(2)%Num
  write(*,"('[Main]: Vars_Allo(1)%Num = ',i3)") Vars_Allo(1)%Num
  write(*,"('[Main]: Vars_Allo(2)%Num = ',i3)") Vars_Allo(2)%Num
 

  write(*,"(/,'[Main]: Constructing Vars_Auto using Construct_MyType_Sub:')")
  call Construct_MyType_Sub( Vars_Auto(1), Num = 1 )
  write(*,"('[Main]: Vars_Auto(1)%Num = ',i3)") Vars_Auto(1)%Num
  call Construct_MyType_Sub( Vars_Auto(2), Num = 2 )
  write(*,"('[Main]: Vars_Auto(2)%Num = ',i3)") Vars_Auto(2)%Num
  write(*,"('[Main]: Vars_Auto(1)%Num = ',i3)") Vars_Auto(1)%Num
  write(*,"('[Main]: Vars_Auto(2)%Num = ',i3)") Vars_Auto(2)%Num
 
 
  write(*,"(/,'[Main]: Constructing Vars_Allo using Construct_MyType_Fun:')")
  Vars_Allo(1)       =       Construct_MyType_Fun( Num = 1 )
  write(*,"('[Main]: Vars_Allo(1)%Num = ',i3)") Vars_Allo(1)%Num
  Vars_Allo(2)       =       Construct_MyType_Fun( Num = 2 )
  write(*,"('[Main]: Vars_Allo(2)%Num = ',i3)") Vars_Allo(2)%Num
  write(*,"('[Main]: Vars_Allo(1)%Num = ',i3)") Vars_Allo(1)%Num
  write(*,"('[Main]: Vars_Allo(2)%Num = ',i3)") Vars_Allo(2)%Num
 
 
  write(*,"(/,'[Main]: Constructing Vars_Auto using Construct_MyType_Fun:')")
  Vars_Auto(1)       =       Construct_MyType_Fun( Num = 1 )                    ! SIGSEGV, segmentation fault occurred
  write(*,"('[Main]: Vars_Auto(1)%Num = ',i3)") Vars_Auto(1)%Num
  Vars_Auto(2)       =       Construct_MyType_Fun( Num = 2 )
  write(*,"('[Main]: Vars_Auto(2)%Num = ',i3)") Vars_Auto(2)%Num
  write(*,"('[Main]: Vars_Auto(1)%Num = ',i3)") Vars_Auto(1)%Num
  write(*,"('[Main]: Vars_Auto(2)%Num = ',i3)") Vars_Auto(2)%Num
 
End Program

[/fortran]
and the output is

ifort main.f90 ; ./a.out
[Main]: size(Vars_Auto) = 2
[Main]: size(Vars_Allo) = 2

[Main]: Constructing Vars_Allo using Construct_MyType_Sub:
[Main]: Vars_Allo(1)%Num =   1
[Main]: Vars_Allo(2)%Num =   2
[Main]: Vars_Allo(1)%Num =   1
[Main]: Vars_Allo(2)%Num =   2

[Main]: Constructing Vars_Auto using Construct_MyType_Sub:
[Main]: Vars_Auto(1)%Num =   1
[Main]: Vars_Auto(2)%Num =   2
[Main]: Vars_Auto(1)%Num =   1
[Main]: Vars_Auto(2)%Num =   2

[Main]: Constructing Vars_Allo using Construct_MyType_Fun:
[Main]: Vars_Allo(1)%Num =   1
[Main]: Vars_Allo(2)%Num =   2
[Main]: Vars_Allo(1)%Num =   2
[Main]: Vars_Allo(2)%Num =   2

[Main]: Constructing Vars_Auto using Construct_MyType_Fun:
forrtl: severe (174): SIGSEGV, segmentation fault occurred
Image              PC                Routine            Line        Source             
a.out              000000000040555F  Unknown               Unknown  Unknown
a.out              0000000000405499  Unknown               Unknown  Unknown
a.out              0000000000405175  Unknown               Unknown  Unknown
a.out              00000000004036C9  Unknown               Unknown  Unknown
a.out              0000000000402B1C  Unknown               Unknown  Unknown
libc.so.6          000000310F621735  Unknown               Unknown  Unknown
a.out              00000000004029F9  Unknown               Unknown  Unknown

The subroutine constructor constructs the derived-type with a correct value for both the automatic and allocatable cases.

The function constructor constructs the derived-type with an erroneous value for the allocatable case and fails to construct the derived-type in the automatic case (segmentation fault).

So, a temporary work-around would be to use subroutine constructors.

Hope it help.

0 Kudos
Steven_L_Intel1
Employee
386 Views

I believe this is the same problem reported in http://software.intel.com/en-us/forums/topic/388577 and it is escalated as issue DPD200243378. The problem is triggered by a polymorphic component of the derived type - if it is non-polymorphic, you don't get this problem. With it, it assigns to the whole array even though you asked for a single element.

0 Kudos
Steven_L_Intel1
Employee
386 Views

This got fixed in 14.0.

0 Kudos
Reply