In C++17 new sequence point rules were introduced. I thought these changes made int i = 0; i = i++; well defined where as it would have been Undefined Behavior in C++14 or earlier.
However this belief has been brought into question in this comment chain.
I've looked through answers to questions like this one but I could not find this specific case plainly stated.
cppreference.com lists two causes for Undefined Behavior related to sequence points :
- Between the previous and next sequence point a scalar object must have its stored value modified at most once by the evaluation of an expression, otherwise the behavior is undefined.
And :
- If a side effect on a scalar object is unsequenced relative to a value computation using the value of the same scalar object, the behavior is undefined.
What I think are the relevant evaluation order rules for this question :
- The side effect (modification of the left argument) of the built-in assignment operator and of all built-in compound assignment operators is sequenced after the value computation (but not the side effects) of both left and right arguments, and is sequenced before the value computation of the assignment expression (that is, before returning the reference to the modified object)
And since C++17 :
- In every simple assignment expression E1=E2 and every compound assignment expression E1@=E2, every value computation and side-effect of E2 is sequenced before every value computation and side effect of E1
I believe that rule 20 introduces a sequence point between evaluating the right argument (including side effects) and the left argument. Therefore i is only accessed once between any sequence point so it cannot be the cause of the Undefined Behavior cited above.
Is the code int i = 0; i = i++; well defined since C++17 or did I misunderstand the changes to sequence points?