Compiler bug: allocatable polymorphic types with TBPs acting on allocatable array

The following MWE (it is still rather complex, unfortunately) causes a segfault when using the NVIDIA compiler (it works fine with GNU, Intel, FLANG):

!> Minimal standalone example to reproduce the segfault
module wrapper_type_mod
  implicit none
  
  type, abstract :: WriterAbstract
  contains
    procedure(init_interface), deferred :: initialize
    procedure :: write_geo
  end type WriterAbstract
  
  type, extends(WriterAbstract) :: WriterBinary
  contains
    procedure :: initialize => writer_binary_initialize
  end type WriterBinary
  
  type :: SimpleFile
    class(WriterAbstract), allocatable :: xml_writer
  contains
    procedure :: initialize => simple_initialize
  end type SimpleFile
  
  abstract interface
    integer function init_interface(this)
      import WriterAbstract
      class(WriterAbstract), intent(inout) :: this
    end function init_interface
  end interface
  
  ! Wrapper type
  type :: WrapperType
    type(SimpleFile) :: myfile
  contains
    procedure :: write => wrapper_write
  end type WrapperType

contains

  integer function simple_initialize(this) result(ierr)
    class(SimpleFile), intent(inout) :: this
    print*, "simple_initialize"
    allocate(WriterBinary :: this%xml_writer)
    ierr = this%xml_writer%initialize()
  end function simple_initialize

  integer function writer_binary_initialize(this) result(ierr)
    class(WriterBinary), intent(inout) :: this
    print*, "writer_binary_initialize"
    ierr = 0
  end function writer_binary_initialize

  integer function write_geo(this, n, x) result(ierr)
    class(WriterAbstract), intent(inout) :: this
    integer, intent(in) :: n
    real, intent(in) :: x(1:)
    print*, "Writing geo"
    ierr = 0
  end function write_geo

  subroutine wrapper_write(this, val)
    class(WrapperType), intent(inout) :: this
    real, intent(in) :: val
    integer :: ierr

    ! real :: x(2)              ! NOTE: No problem
    real, allocatable :: x(:)   ! NOTE: Causes segfaults
    allocate(x(1:2))
    
    x = 0.0

    print*, "wrapper_write"   ! 89703 lines of:   wrapper_write
                              !                   simple_initialize
                              !                   writer_binary
    ! print*, "wrapper_write with val = ", val ! Instant segfault after writer_binary_initialize
    ierr = this%myfile%initialize()
    if (allocated(this%myfile%xml_writer)) then
      ierr = this%myfile%xml_writer%write_geo(n=size(x), x=x)
    endif
    
    deallocate(x)
  end subroutine wrapper_write

end module wrapper_type_mod

program minimal_test
  use wrapper_type_mod
  implicit none

  type(WrapperType) :: wrapper

  call wrapper%write(val=1.0)

end program minimal_test

on my local machine this causes an infinite recursion of:

 wrapper_write
 simple_initialize
 writer_binary_initialize
 wrapper_write
 simple_initialize
 writer_binary_initialize

untill, after 89703 lines of output, it segfaults. When replacing allocatable, x(:) by a x(2) the segfault disappears.

Hi ronaldremmerswaal,

Thanks for reporting this! I was able to reproduce it and saw that it behaved correctly with GNU and Flang. I opened TPR#38254 with engineering to get them to take a look. We know that nvfortran is struggling to keep up with all the modern Fortran features and abstractions, so we are actively working on migrating to a new LLVM-based Fortran compiler that should resolve all these problems. So, depending on how hard it is to fix in the current nvfortran, engineering may just recommend waiting for the new version. However, I’ll let you know what they suggest! It could always be a very straightforward and easy fix.

Please feel free to let us know any other bugs you run into! They all help make the compiler better!

Cheers,

Seth.

Engineering got back to us, nothing on a fix yet - but a work around. If you introduce a temporary variable to hold the size call, then the code no longer appears to segfault.

So if you introduce an integer tmp1, then it’d look like this:

    if (allocated(this%myfile%xml_writer)) then
      tmp1 = size(x)
      ierr = this%myfile%xml_writer%write_geo(n=tmp1, x=x)
    endif

If they update us on a compiler fix, I’ll let you know.

Dear Seth,

Thanks for the prompt reply and temporary fix. The fix works in the actual code.

Kind regards,

Ronald

Hi! Engineering has let us know that this should be resolved in 26.3. Thanks!