Fortran and short-circuit logic

Never assume that eager or short-circuit evaluation of logical statements will occur in Fortran.

Fortran standards from Fortran I (1957) through Fortran 2018 do not mandate or prohibit short-circuit logic. That has resulted in some compilers (e.g. Gfortran) sometimes using short-circuit logic, while other compilers (e.g. Intel) do not use short circuit logic. This causes breakage when the programmer tests with one Fortran compiler handles compound logic with eager evaluation, but other compiler uses short-circuit evaluation.

Example code

Compilers not short-circuiting (standard Fortran behavior):

  • Gfortran -O0
  • NAG
  • Intel

Short circuiting (non-standard behavior)

  • Gfortran -O1 or higher

Proper handling of compound logic in Fortran: one should carefully avoid assumptions that either eager or short-circuit evaluation of compound logical statements will occur, because neither is guaranteed by any Fortran standard.

Assuming eager evaluation of Fortran logical statements, this can cause breakage where a function that’s part of the statement has side effects. For example, a function that modifies a module variable, or simply an intent(inout) variable will find those variables unmodified if a compiler uses short-circuit logic.

Fix: break up the compound if statement so that the function is always evaluated (e.g. just before the if statement).

Assumptions that short circuit evaluation occurs commonly causes breakage of present(arg) for optional :: arg optional dummy arguments.

subroutine myfun(a,b)
real, intent(inout) :: a
real, intent(in), optional :: b

! don't do this!
if (present(b) .and. b < 0)  a = b*a

! instead, do this:
if present(b) then
  if (b < 0) a = b*a
endif