@Arjen it’s because an unallocated allocatable or a unassociated pointer can be passed to an optional argument and count as not present.
@awvwgk I initially thought the same; but @Arjen’s solution does seem to work with both gfortran and ifort, even for unallocated arguments.
Simplifying @Arjen’s idea slightly, the code
module test
implicit none
type :: FooType
end type
type :: BarType
end type
interface fun
procedure fun_no_arg, fun_foo, fun_bar
end interface
contains
subroutine fun_no_arg()
write(*,*) 'no arg'
end subroutine
subroutine fun_foo(arg)
type(FooType) :: arg
call fun_foo_(arg)
end subroutine fun_foo
subroutine fun_foo_(arg)
type(FooType), optional :: arg
write(*,*) 'foo', present(arg)
end subroutine
subroutine fun_bar(arg)
type(BarType) :: arg
call fun_bar_(arg)
end subroutine fun_bar
subroutine fun_bar_(arg)
type(BarType), optional :: arg
write(*,*) 'bar', present(arg)
end subroutine
end module
program p
use test
type(FooType), allocatable :: foo ! An unallocated constant
type(BarType), allocatable :: bar ! An unallocated constant
write(*,*) 'fun()'
call fun() ! No argument
write(*,*) 'fun(foo)'
call fun(foo) ! A FooType argument which is not present()
write(*,*) 'fun(FooType())'
call fun(FooType()) ! A FooType argument which is present()
write(*,*) 'fun(bar)'
call fun(bar) ! A BarType argument which is not present()
write(*,*) 'fun(BarType())'
call fun(BarType()) ! A BarType argument which is present()
end program
writes the output
fun()
no arg
fun(foo)
foo F
fun(FooType())
foo T
fun(bar)
bar F
fun(BarType())
bar T
So it seems to be working as intended, although I have no idea if this is standard compliant.