Quantcast
Channel: Intel® Fortran Compiler
Viewing all articles
Browse latest Browse all 3270

Segfault due to strange interaction of intrinsic and defined assignment

$
0
0

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.


Viewing all articles
Browse latest Browse all 3270

Trending Articles



<script src="https://jsc.adskeeper.com/r/s/rssing.com.1596347.js" async> </script>