Bug in nvfortran with -Mchkptr for unallocated optional arguments?

Dear all,

As far as I know, the Fortran standard requires that when an unallocated array, say arr, is passed into a subroutine as an optional argument, present(arr) should be false. The following conforming program, compiled with nvfortran -Mchkptr results in a runtime error,

program test
  implicit none
  real, allocatable :: a(:),b(:)
  allocate(a(5))
  call do_nothing(a,b)
contains
  subroutine do_nothing(var,var_optional)
    real, intent(inout) :: var(:)
    real, intent(inout), optional :: var_optional(:)
    if(.not.present(var_optional)) then
      print*,'Conforming Program'
    end if
  end subroutine
end
nvfortran -Mchkptr prog.f90 && ./a.out
0: Null pointer for b (prog.f90: 5)

So I guess this is a bug in the compiler? I have just been bitten by it in my code.

Hi Pedro,

I talked with a few other engineers and we agree that the behavior is correct. -Mchkptr check if an argument has a NULL pointer as an argument, which is the case for “b”. This check is done at the call site, not the present intrinsic.

If important, we can look at adding a sub-option to -Mchkptr which will disable this feature on optionals, but would want to keep the default behavior for folks who are checking to ensure allocated arrays are being passed in.

-Mat

Hi Mat,

Thank you very much for looking this up.

I found what I was looking for in the Fortran Standard (paragraph 7 of section 15.5.2.4; pg. 315 of the linked document):

  1. Except in references to intrinsic inquiry functions, if the dummy argument is nonoptional and the actual argument is allocatable, the corresponding actual argument shall be allocated.

I guess that, if the desired behavior of the -Mchkptr flag is to be for debugging purposes, perhaps it should not issue a runtime error in this case, else it will hit users who wish to exploit a valid (and at times quite useful) feature of the language, and want to still use this flag to check for actual bugs.

For completeness I checked what other compilers do. See this modified code below:

 program test
   implicit none
   real, allocatable :: a(:),b(:),c(:)
   allocate(a(5),b(5))
   call do_nothing(a,b,var_optional=c)
   deallocate(b)
   call do_nothing(a,b,var_optional=c)
 contains
   subroutine do_nothing(var,var_not_optional,var_optional)
     real, intent(in) :: var(:),var_not_optional(:)
     real, intent(in), optional :: var_optional(:)
     if(.not.present(var_optional)) then
       print*,'Conforming Program'
     end if
   end subroutine
 end

With gfortran or crayftn I could not get any runtime error (not good, in my view). With ifort, the program only errors out when the allocated array is passed as a non-optional argument:

$ ifort -g -check all test.f90 && ./a.out
 Conforming Program
forrtl: severe (408): fort: (8): Attempt to fetch from allocatable variable B when it is not allocated

Edit: So perhaps a sub-option for -Mchkptr, or a change in its behavior would be useful.

Pedro