c++ – Understanding Undefined Behavior in i = i++ and i = foo(i++)

c++undefined-behavior

For example:

int foo(int i) { return i; }

int main()
{
  int i = 0;

  i = i++;      // Undefined
  i = foo(i++); // ?

  return 0;
}

What would the current ISO C++ standard specify for this case?

EDIT:

Here's where I get confused:

Except where noted, evaluations of operands of individual operators and of subexpressions of individual expressions are unsequenced.

If a side effect on a scalar
object is unsequenced relative to either another side effect on the same scalar object or a value computation
using the value of the same scalar object, and they are not potentially concurrent (1.10), the behavior is
undefined.

In all cases, the assignment is sequenced after the value
computation of the right and left operands, and before the value computation of the assignment expression

Every evaluation in the calling function (including other function calls) that is not otherwise specifically
sequenced before or after the execution of the body of the called function is indeterminately sequenced with
respect to the execution of the called function.

So it seems you could have a value computation on the left side of the assignment (just i), and a side effect on the right side (the modification of i from i++) which aren't sequenced with respect to each other.

EDIT2:

For anyone who finds themselves here, there is a really great explanation about sequencing that I found here.

Best Answer

The last sentence in your quote says "that is not otherwise specifically sequenced before or after the execution of the body of the called function" so the question is whether the increment and the assignment are "otherwise specifically sequenced before or after" the function body.

1.9 [intro.execution] p15 has the answer:

When calling a function (whether or not the function is inline), every value computation and side effect associated with any argument expression, or with the postfix expression designating the called function, is sequenced before execution of every expression or statement in the body of the called function. [ Note: Value computations and side effects associated with different argument expressions are unsequenced. — end note ]

So the increment of i happens before the function body, and the assignment to i happens after the function returns, so it is perfectly well-defined.

In pre-C++11 terminology, the function call introduces a sequence point between the increment and the assignment.