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

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

flying_hermes's picture

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:

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
	

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.

 

4 posts / 0 new
Last post
For more complete information about compiler optimizations, see our Optimization Notice.
flying_hermes's picture

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:

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

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.

Steve Lionel (Intel)'s picture

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.

Steve
Steve Lionel (Intel)'s picture

This got fixed in 14.0.

Steve

Login to leave a comment.