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

Segfault due to strange interaction of intrinsic and defined assignment

Sean_S_2
Beginner
712 Views

Here is a case where something very strange seems to be happening with ifort 14 and 15, leading to a run-time segfault. First, the code:

module foo_types

implicit none

type :: foo_alloc
   integer, allocatable :: foo(:)
 contains
   procedure, private :: array_assign
   procedure, private :: alloc_assign
   ! This causes an error in array_assign:
   generic :: assignment(=) => array_assign, alloc_assign
   ! This causes an error in alloc_assign:
   ! generic :: assignment(=) => alloc_assign, array_assign
end type foo_alloc

type :: foo_wrapper
   type(foo_alloc) :: wrappee
end type foo_wrapper

interface foo_wrapper
   module procedure new_foo_wrapper
end interface

contains

subroutine array_assign(lhs, array)
  class(foo_alloc), intent(out) :: lhs
  integer, intent(in) :: array(:)
  allocate(lhs%foo(size(array)), source=array)
end subroutine array_assign

subroutine alloc_assign(lhs, rhs)
  class(foo_alloc), intent(out) :: lhs
  type(foo_alloc), intent(in) :: rhs

  if (allocated(rhs%foo)) then
     allocate(lhs%foo(size(rhs%foo)), source=rhs%foo)
  end if

end subroutine alloc_assign

function new_foo_wrapper()
  type(foo_wrapper) :: new_foo_wrapper

  ! These lines do nothing, but if removed there is a pointless warning about
  ! the return value being undefined.
  if (allocated(new_foo_wrapper%wrappee%foo)) then
     deallocate(new_foo_wrapper%wrappee%foo)
  end if

end function new_foo_wrapper

end module foo_types

program test_assign_constructor
  use foo_types
  implicit none

  type(foo_wrapper) :: bar

  bar = foo_wrapper()

end program test_assign_constructor

To summarize, we have a wrapper type around a derived type that has a single allocatable component. The wrapped type has a pair of derived assignments, while the wrapper type only has intrinsic assignment.

The main program performs assignment of the wrapper type, which should cause "alloc_assign" to be used to copy the wrapped component. Since the component on the RHS is never allocated, this should be a no-op, but instead we segfault.

Compiling and running with "-g -traceback" shows some weirdness. Firstly, in the above version, we are entering "array_assign" instead of "alloc_assign". Secondly, if you switch the order of the subroutines in the "generic" statement, we do enter alloc_assign, suggesting that something is wrong with resolving the generic procedure based on type (this resolution should be unambiguous, so order should not matter). Thirdly, if we do enter alloc_assign, we also enter the body of the if block, instead of jumping past it as we should.

So, I think that there is some strange bug here.

0 Kudos
1 Reply
Kevin_D_Intel
Employee
712 Views

I reproduced the seg-fault using both 14.0/15.0 compilers but the code appears to work as expected with the earlier 13.1 compiler. I reported this issue to our Developers (see internal tracking id below) for some further investigation and will let you know what I hear back.

(Internal tracking id: DPD200362028)

0 Kudos
Reply