Function evaluation conflicting with other effects in statement

I would like to clarify my understanding of evaluation order in Fortran.

Let's say I have a Stack type with methods pop and push_back. If I execute the following code:

call stack%push_back(1)
call stack%push_back(3)
call stack%push_back(stack%pop() - stack%pop())
write(*, *) stack%pop()    ! could print 2, or -2

the last element on the Stack depends on the evaluation order and as this answer explains, the Compiler is free to change the evaluation order.

But even if I have a commutative operation, there are still problems. The Fortran 2008 standard says (7.1.4):

The evaluation of a function reference shall neither affect nor be affected by the evaluation of any other entity within the statement.

So even this code:

call stack%push_back(1)
call stack%push_back(3)
call stack%push_back(stack%pop() + stack%pop())

is not standard conforming?

This means that I always have to write it like this:

call stack%push_back(1)
call stack%push_back(3)
    integer :: A, B
    A = stack%pop()
    B = stack%pop()
    call stack%push_back(A - B)
end block
write(*, *) stack%pop()    ! is guaranteed to print 2

Is this true?


  • (Here we assume reasonable and intuitive definitions of things in the question and imply similar in the answer.)

    The statement

    call stack%push_back(stack%pop() - stack%pop())

    would indeed be invalid, for the reason stated in the question. However, it may be easier to see this in terms of the other restriction in the pair, not quoted (Fortran 2018 10.1.4, but similar in F2008):

    if a function reference causes definition or undefinition of an actual argument of the function, that argument or any associated entities shall not appear elsewhere in the same statement.

    The statement of concern is the same as

    call stack%push_back(pop(stack) - pop(stack))

    where it's quite clear that stack is an actual argument and it appears more than once in the statement; stack is defined by the function pop.

    Yes you will need to use different statements to have the desired effect. The approach given in the question is reasonable.