The answer from CoryKramer is absolutely correct, but perhaps not well developed. The clarification in DR 1949 does not matter.
The key is clause 13 of section 1.9, which defines the โsequenced toโ relationship as a partial order and provides four possibilities for two ratings A and B:
A sequenced to B
B sequenced to A
One of (1) or (2) is satisfied, but the standard does not indicate which. In this case, we say that A and B are indefinitely sequenced.
Neither (1) nor (2) is satisfied. In this case, we say that A and B are not affected.
There is a difference between undefined sequencing and illogical, and it is this difference that is considered in paragraph 15. Paragraph 15 begins with a general rule (emphasized by me):
Except where noted, estimates of the operands of individual operators and subexpressions of individual expressions are not affected.
The consequence of this is that in a function call
f(argument1, argument2);
estimates of argument1 and argument2 have no consequences. This makes the following undefined behavior:
f(i++, i++);
But suppose we had:
int incr(int& i) { return i++; }
and instead we wrote:
f(incr(i), incr(i));
If we applied the general rule, it would also be undefined behavior with exactly the same argument: both estimates are not subject to a sequence, therefore the estimates of the bodies of two function calls are not subject, and we end up with two disjoint changes to the same variable.
But this is really undesirable, as it will lead to chaos. [It should be noted that the above example is severely simplified; the two functions can be completely different, and the general variable cannot be named. In particular, as a general case, both functions can send output to std::cout , thus performing a mutable operation on the same common object ( std::cout ).]
Thus, an explicit exception is made for function calls: the function evaluation body is always ordered with respect to the subexpressions of the expression that contains the function call. So in
f(incr1(i), incr2(i));
because these are function calls, the evaluation of the bodies incr1 and incr2 indefinitely sequenced, and has no consequences, and since both orders lead to the fact that i doubles, the value of i at the end of the evaluation of the argument list is clearly defined. Also, the actual arguments passed to f are not defined, not undefined; either the first or second will be larger, but they will not be equal.
This exception does not apply to the evaluation of the calls themselves, but only to the evaluation of the bodies of the called function. So f(g(i++), h(i++)) still exists undefined, because evaluating two i++ subexpressions is not part of evaluating the body of any of the functions.
Two side problems
Section 15 also extends this exception to function calls resulting from language semantics, including operator overrides, with an interesting result that
f(i++, i++);
is undefined, not undefined if i is an instance of an object with operator++(int) overriding. Similarly
f(std::cout << 'a', std::cout << 'b');
will cause ab or ba to be sent to std::cout (unspecified), but not undefined.
The point of DR 1949 is that "sequenced after" was never formally defined. Therefore, instead of saying that โA is sequenced before or after Bโ, the more precise wording โeither A is sequenced before B or B is sequenced to Aโ. You can achieve the same logical effect by formally defining that "A is sequenced after B" because "B is sequenced to A". DR 1949 does both.