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

constructor assigment problem in ifort 19.04

may_ka
Beginner
315 Views

Hi,

the following code produces a segfault in ifort 19.04 but runs fin in gfortran 9.1

Module mod_m1
  Type :: parent
    real, allocatable :: a(:,:)
  contains
    private
    procedure, pass(this) :: copy => subcopy
    generic, public :: assignment(=) => copy
  end type parent
  Type, extends(parent) :: child
    real, allocatable :: x(:,:)
  end type child
  interface parent
    module procedure new_parent
  end interface parent
  interface child
    module procedure new_child_1
    module procedure new_child_2
  end interface child
contains
  Subroutine subcopy(ot,this)
    implicit none
    Class(parent), intent(in) :: this
    class(parent), intent(out), allocatable :: ot
    write(*,*) "copy"
    allocate(ot,source=this)
  end Subroutine subcopy
  Function new_parent(dim)
    integer, intent(in) :: dim
    type(parent), allocatable :: new_parent
    write(*,*) "new_parent"
    allocate(new_parent)
    allocate(new_parent%a(dim,dim))
  end Function new_parent
  Function new_child_1()
    type(child), allocatable :: new_child_1
    write(*,*) "new_child_1"
    allocate(new_child_1)
  end Function new_child_1
  Function new_child_2(dim1,dim2)
    integer, intent(in) :: dim1, dim2
    type(child), allocatable :: new_child_2
    write(*,*) "new_child_2"
    allocate(new_child_2)
    allocate(new_child_2%a(dim1,dim1))
    allocate(new_child_2%x(dim2,dim2))
  end Function new_child_2
end Module mod_m1
Program test
  use mod_m1
  implicit none
  class(parent), allocatable :: a,b
  write(*,*) "a"
  allocate(child::a);
  write(*,*) "b"
  b=child(5,5)
  write(*,*) allocated(b)
end Program test

it appears as if "allocate(child::a) is not automatically replaced by constructor new_child_1 ......... which is sort of ok. However, "b=child(5,5)" yields a segfault with message:

a
 b
forrtl: severe (408): fort: (7): Attempt to use pointer B when it is not associated with a target

Image              PC                Routine            Line        Source             
a.out              000000000040D9E6  Unknown               Unknown  Unknown
a.out              00000000004052D6  Unknown               Unknown  Unknown
a.out              00000000004037E2  Unknown               Unknown  Unknown
libc-2.29.so       000014A882A90EE3  __libc_start_main     Unknown  Unknown
a.out              00000000004036EE  Unknown               Unknown  Unknown

whereas when run with gfortran the output is as expected:

 a
 b
 new_child_2
 copy
 T

I am wondering whether this is a bug in ifort or gfortran except is wrong code.

Any idea.

Thanks

0 Kudos
2 Replies
FortranFan
Honored Contributor II
315 Views

I think the code in the original post is non-conformant with respect to the standard given type-bound generic for assignment operation: the standard states an instruction shall not reference an unallocated ALLOCATABLE object whereas the implemented specific procedure for the defined assignment informs the processor to do so.  Something along the lines of the modified code shown below is likely what is called for here, though one has to be very careful with defined operations in situations of type extension (inheritance) and polymorphism (see this: https://groups.google.com/d/msg/comp.lang.fortran/EtGmIRqvF2E/ITrDC4iuCAAJ):

module mod_m1
   implicit none
   type :: parent
      real, allocatable :: a(:,:)
   contains
      private
   end type parent
   type, extends(parent) :: child
      real, allocatable :: x(:,:)
   end type child
   interface parent
      module procedure new_parent
   end interface parent
   interface assignment(=)
      module procedure subcopy
   end interface
   interface child
      module procedure new_child_1
      module procedure new_child_2
   end interface child
contains
   subroutine subcopy(ot,this)
      class(parent), intent(in) :: this
      class(parent), intent(out), allocatable :: ot
      write(*,*) "copy"
      allocate(ot,source=this)
   end subroutine subcopy
   function new_parent(dim)
      integer, intent(in) :: dim
      type(parent), allocatable :: new_parent
      write(*,*) "new_parent"
      allocate(new_parent)
      allocate(new_parent%a(dim,dim))
   end function new_parent
   function new_child_1()
      type(child), allocatable :: new_child_1
      write(*,*) "new_child_1"
      allocate(new_child_1)
   end function new_child_1
   function new_child_2(dim1,dim2)
      integer, intent(in) :: dim1, dim2
      type(child), allocatable :: new_child_2
      write(*,*) "new_child_2"
      allocate(new_child_2)
      allocate(new_child_2%a(dim1,dim1))
      allocate(new_child_2%x(dim2,dim2))
   end function new_child_2
end module mod_m1
program test
   use mod_m1
   implicit none
   class(parent), allocatable :: a,b
   write(*,*) "a"
   allocate(child::a);
   write(*,*) "b"
   b=child(5,5)
   write(*,*) allocated(b)
end program test

Upon execution using Intel Fortran 19.0 update 5 as well as gfortran:

 a
 b
 new_child_2
 copy
 T

 

0 Kudos
may_ka
Beginner
315 Views

Thanks

this implies that

write(*,*) "b"
allocate(b)
b=child(5,5)

would have done the trick as well. At least ifort accepts it. Would you agree?

Cheers

0 Kudos
Reply