5

From §5.2.6/1 we have (emphasis is mine):

The value of a postfix ++ expression is the value of its operand. [ Note: the value obtained is a copy of the original value — end note ] The operand shall be a modifiable lvalue. The type of the operand shall be an arithmetic type other than cv bool, or a pointer to a complete object type. The value of the operand object is modified by adding 1 to it. The value computation of the ++ expression is sequenced before the modification of the operand object. With respect to an indeterminately-sequenced function call, the operation of postfix ++ is a single evaluation. [ Note: Therefore, a function call shall not intervene between the lvalue-to-rvalue conversion and the side effect associated with any single postfix ++ operator. — end note ] The result is a prvalue. The type of the result is the cv-unqualified version of the type of the operand. If the operand is a bit-field that cannot represent the incremented value, the resulting value of the bit-field is implementation-defined. See also [expr.add] and [expr.ass].

That is, the modification of the operand object is sequenced after the value computation of the ++ expression.

From §5.18/1 we have (emphasis is mine):

The assignment operator (=) and the compound assignment operators all group right-to-left. All require a modifiable lvalue as their left operand and return an lvalue referring to the left operand. The result in all cases is a bit-field if the left operand is a bit-field. 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. With respect to an indeterminately-sequenced function call, the operation of a compound assignment is a single evaluation. [ Note: Therefore, a function call shall not intervene between the lvalue-to-rvalue conversion and the side effect associated with any single compound assignment operator. — end note ]

assignment-expression:
      conditional-expression
      logical-or-expression assignment-operator initializer-clause
      throw-expression

assignment-operator: one of
      = *= /= %= += -= >>= <<= &= ^= |=

The assignment is also sequenced after the value computation of the right and left operands of the assignment operator.

Thus, if we consider the expression

i = i++;

we know from §5.2.6/1 that the side effect of the expression i++, on the RHS of this assignment expression is sequenced after the value computation of i++. And from §5.18/1 we know that the side effect corresponding to the assignment to i on the LHS of the assignment operator is sequenced after the value computation of the right and left operands of the assignment operator.

But how do I show that these two side effects are unsequenced, in order to prove that the expression i = i++; shows undefined behavior?

Belloc
  • 6,318
  • 3
  • 22
  • 52
  • 1
    Have you read [Undefined behavior and sequence points](http://stackoverflow.com/questions/4176328/undefined-behavior-and-sequence-points)? – NathanOliver Feb 01 '16 at 17:30
  • I did, but couldn't find the answer there. – Belloc Feb 01 '16 at 17:33
  • Start reading at *Now the Standard in §5/4 says* under the section **What is the relation between Undefined Behaviour and Sequence Points?** – NathanOliver Feb 01 '16 at 17:35
  • I tagged the question with `C++1z` – Belloc Feb 01 '16 at 17:38
  • Note that not a word is said about the relative ordering of the incrementation and the assignment – all you know is that they are both sequenced after the value computation of `i++`. – molbdnilo Feb 01 '16 at 18:15
  • @molbdnilo I agree with this. But the absence of a relative ordering doesn't allow me, I think, to conclude that the alluded side effects are unsequenced. – Belloc Feb 01 '16 at 18:24
  • @Belloc That's what unsequenced means. Read [intro.exec](http://eel.is/c++draft/intro.execution#15). – molbdnilo Feb 01 '16 at 19:18
  • @molbdnilo I can't find anything in [intro.execution]/15 (http://eel.is/c++draft/intro.execution#15) that would allow me to verify that the two side effects mentioned above are unsequenced. – Belloc Feb 01 '16 at 19:25
  • Oops, should have been [13](http://eel.is/c++draft/intro.execution#13), not 15. – molbdnilo Feb 01 '16 at 19:32
  • @molbdnilo You were the one who said above `Note that not a word is said about the relative ordering of the incrementation and the assignment`. If I don't know anything about the ordering of those two side effects, how should I use [intro.execution]/13 to certify that these side effects are unsequenced? – Belloc Feb 01 '16 at 19:37
  • What exactly is unclear about "If A is not sequenced before B and B is not sequenced before A, then A and B are unsequenced."? – molbdnilo Feb 01 '16 at 19:42
  • I don't know whether A is sequence before or after B. So I can't say whether A is not sequence before B, nor whether B is not sequenced before A. – Belloc Feb 01 '16 at 19:45

1 Answers1

8

First, if A is not sequenced before B and B is not sequenced before A, then A and B are unsequenced (1.9/13). That's the definition of unsequenced. Second, if two side effects on a scalar object are unsequenced, the behavior is undefined (1.9/15). So unless you can find something that says that the post-increment and the assignment are sequenced (and you won't), the behavior is undefined.

Pete Becker
  • 74,985
  • 8
  • 76
  • 165
  • `So unless you can find something that says that the post-increment and the assignment are sequenced (and you won't), the behavior is undefined` I don't agree with that. Again, the fact that the Standard doesn't say anything about the relative ordering of those side-effects, doesn't allow me, I think, to conclude that they are unsequenced. – Belloc Feb 01 '16 at 18:59
  • 2
    @Belloc - where do you expect to find a statement that they're sequenced if not in the standard? Keep in mind that the definition of undefined behavior applies to constructs for which the standard does not impose any requirements. Unless you can find a requirement that one of these is sequenced before the other, the behavior is undefined. – Pete Becker Feb 01 '16 at 20:32
  • I wasn't expecting any statement in the Standard that they are sequenced, but that they are **unsequenced**. In reference to undefined behavior, [intro.execution]/15 is quite clear: `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 ([intro.multithread]), the behavior is undefined`. That is, first we must prove that the side effects are unsequenced, before we can say anything about UB. – Belloc Feb 01 '16 at 23:51
  • 2
    @Belloc The standard only specifies which operations are sequenced, and how. Which things are *un*sequenced follows from that by the definition above. – molbdnilo Feb 02 '16 at 08:59
  • 2
    @molbdnilo `The standard only specifies which operations are sequenced` Incorrect. [intro.execution/15](http://eel.is/c++draft/intro.execution#15) starts with this `Except where noted, evaluations of operands of individual operators and of subexpressions of individual expressions are unsequenced.` – Belloc Feb 02 '16 at 10:48
  • Re: "the standard does not impose any requirements": not a C++ expert, but I guess that the Standard requires for the side effects to be (eventually) applied. Is that correct? If so, then this is at least one requirement. Hence, it is not "does not impose any requirements". – pmor May 05 '22 at 22:43