The code at the end of this post shows a very specific case where PGI seems to have a bug causing a segfault. The “FooContainer” type has an allocatable component of abstract type (FooBase). If you use an init method to allocate that component based on some input, and then call a type-bound procedure on that component, you get a segfault.
When I was mucking about trying to find a workaround, I found three more things:
It seems to be impossible to use a “select type” construct to get information about the type of my_foo, since you instead get information about “self” (the FooContainer object).
If you copy my_foo, the copy doesn’t seem to have any dynamic type information. If you put it in a select type construct, it will always fall through to the “class default” clause.
If you don’t use the FooContainer_init function to set my_foo, and instead allocate my_foo directly, there didn’t seem to be a problem. Using a type-bound “init” subroutine also seems to do the trick, which ended up being the workaround that I use. This suggests that the real problem here is the assignment from the output of the FooContainer_init function.
(One of my test cases found a different issue, which is that pgfortran doesn’t allow you to allocate “empty” types with no components. I’m not sure why, since this seems explicitly allowed in Fortran; maybe just an unimplemented feature?)
module foo_mod
implicit none
type, abstract :: FooBase
integer :: a
contains
procedure(do_proc), pass(self), deferred :: do_stuff
end type FooBase
abstract interface
subroutine do_proc(self)
import
class(FooBase), intent(in) :: self
end subroutine do_proc
end interface
type, extends(FooBase) :: Foo
integer :: b
contains
procedure, pass(self) :: do_stuff => really_do_stuff
end type Foo
type :: FooContainer
class(FooBase), allocatable :: my_foo
contains
procedure, pass(self) :: do_stuff_wrap
end type FooContainer
contains
subroutine really_do_stuff(self)
class(Foo), intent(in) :: self
print *, "Hi!"
end subroutine really_do_stuff
function FooContainer_init(foo_in) result(res)
class(FooBase), intent(in) :: foo_in
type(FooContainer) :: res
allocate(res%my_foo, source=foo_in)
end function FooContainer_init
subroutine do_stuff_wrap(self)
class(FooContainer), intent(in) :: self
call self%my_foo%do_stuff()
end subroutine do_stuff_wrap
end module foo_mod
program test_poly
use foo_mod
implicit none
type(Foo) :: local_foo
type(FooContainer) :: foo_wrap
foo_wrap = FooContainer_init(local_foo)
call foo_wrap%do_stuff_wrap()
end program test_poly
Thanks for the update; the bugs fixed in versions 13.9 and 13.10 have been quite helpful!
Could you also file a TPR for the other issue I encountered? I specifically mean allocating an empty type:
type foo
end type foo
type(foo), allocatable :: x
allocate(x)
end
This causes the following compilation error:
PGF90-S-0151-Empty TYPE, STRUCTURE, UNION, or MAP (test_empty_type.F90: 8)
0 inform, 0 warnings, 1 severes, 0 fatal for MAIN
The main case where you would want to allocate an empty type is to leverage polymorphism, in which case you would declare “class(foo)”; the error actually goes away in that case. But it seems a little inconsistent; I don’t see a reason why the above shouldn’t work.
Not sure why but it looks like this one did not get in 13.10. The error does not occur in the pre-release 14.1 compiler, which will be available in January.
Original case seems OK, but I found one case where an empty type can still cause a segfault in PGI 14.1.
program test_select_type_component
type :: foo
end type foo
type(foo) :: test_foo
! Produces an ICE.
allocate(test_foo, source=foo())
end program test_select_type_component
Oops. I meant to post this valid code (which has the same issue):
program test_select_type_component
type :: foo
end type foo
type(foo), allocatable :: test_foo
! Produces an ICE.
allocate(test_foo, source=foo())
end program test_select_type_component