fortran-wringer-tests icon indicating copy to clipboard operation
fortran-wringer-tests copied to clipboard

Optional passed-object dummy arguments

Open ivan-pi opened this issue 9 months ago • 8 comments

Example discussed here: https://fortran-lang.discourse.group/t/what-is-benefit-of-pass-in-type-bound-procedures/9294/8

! Can we use an optional passed-object dummy argument 
! before the dynamic type has been established?
module m
 type :: foo
 contains
  procedure, pass, non_overridable :: check
 end type
contains
 subroutine check(f)
  class(foo), optional :: f
  if (present(f)) then
   print *, "present"
  else
   print *, "not present"
  end if
 end subroutine
end module

use m
type(foo), allocatable :: f
class(foo), allocatable :: g

call f%check
allocate(f)
call f%check

call g%check
allocate(foo :: g)
call g%check
end

ivan-pi avatar Mar 04 '25 20:03 ivan-pi

And what is the problem with that?

klausler avatar Mar 04 '25 21:03 klausler

Never mind, I tried it with all compilers, and only two get it right. What's really weird are the two compilers that print present for every call.

klausler avatar Mar 04 '25 21:03 klausler

I guess I don't have access to those two that think it's always present. But I like the interpretation of the two that get it right. :)

ivan-pi avatar Mar 04 '25 21:03 ivan-pi

I guess I don't have access to those two that think it's always present. But I like the interpretation of the two that get it right. :)

I don't like to name or shame Fortran compilers with bugs -- implementing this language is very difficult and nobody gets it right all of the time. So you'll have to find them yourself. But yes, a bad result from PRESENT seems to be even worse than crashing.

klausler avatar Mar 04 '25 21:03 klausler

I've been pointed to the fact, the program is actually illegal, due to Section 15.5.1, paragraph 2,

The data-ref in a procedure-designator shall not be an unallocated allocatable variable or a pointer that is not associated.

ivan-pi avatar Mar 05 '25 08:03 ivan-pi

That only affects whether the program is conformant with a document.

klausler avatar Mar 05 '25 16:03 klausler

In case it's not clear, the point of this example (at least to me) is that the procedure binding has been declared NON_OVERRIDABLE, so the procedure can be resolved at compilation time without the use of any dynamic procedure table lookup. Compilers that don't do this are missing an easy and significant optimization.

klausler avatar Mar 05 '25 16:03 klausler

That is also how I envisioned it. If the order is changed to:

allocate(f)
call f%check

allocate(foo :: g)
call g%check

the compilers I have access to work as I'd expect. But the Fortran document seems to imply that the data reference (i.e. f and g) must be allocated before it is valid to call any type-bound procedure, even non_overridable ones. The fact the passed-object dummy argument is optional seems to play no role then. There is also the question then if options like -C=pointer (NAG) or -fcheck=pointer (gfortran) are able to detect this fringe case.

ivan-pi avatar Mar 05 '25 17:03 ivan-pi