Compiler bug: passing a procedure with a variable from a local scope as input to a function leads to unexpected behavior

I ran into the following problem when using the NVIDIA Fortran compiler (e.g. nvfortran 26.1):

module my_module
  implicit none

  abstract interface
    pure real function fun_interface()
    end function fun_interface
  end interface
contains
  real function my_wrapper(fun)
    implicit none
    procedure(fun_interface) :: fun

    my_wrapper = wrapper_wrapper()

    ! This always works on GCC and on NVHPC:
    ! my_wrapper = fun()
  contains
    real function wrapper_wrapper()
        wrapper_wrapper = fun()
    end function wrapper_wrapper
  end 
end module my_module

program example
  use my_module
  implicit none

  ! This works on GCC and on NVHPC
  ! real, parameter :: target_value = .5
  
  ! This works on GCC, not on NVHPC
  real :: target_value
  target_value = 0.5

  print*, "Via wrapper (should equal .5): ", my_wrapper(my_fun)
  print*, "Direct call (should equal .5): ", my_fun()          
contains
  pure real function my_fun()
    my_fun = target_value
  end function my_fun

end program example

nvfortran gives as output:

❯ nvfortran test.f90 -o test_nvidia
❯ ./test_nvidia
 Via wrapper (should equal .5):    -2168.705    
 Direct call (should equal .5):    0.5000000  

This problem does not occur using GNU, Intel or NAG Fortran compilers.

Related to this: Man or boy test - Rosetta Code

The nvfortran compiler does not pass this test

Thanks for the report ronaldremmerswall and welcome!

I recreate the issue here and have filed a problem report, TPR #38222. We’ll have engineering investigate.

-Mat

FYI, TPR #38222 was fixed in our 26.3 release.