This is an unofficial snapshot of the ISO/IEC JTC1 SC22 WG21 Core Issues List revision 114b. See http://www.open-std.org/jtc1/sc22/wg21/ for the official list.

2024-05-06


2855. Undefined behavior in postfix increment

Section: 7.6.1.6  [expr.post.incr]     Status: DR     Submitter: Lénárd Szolnoki     Date: 2023-12-12

[Accepted as a DR at the March, 2024 meeting.]

(From submission #479.)

Consider:

  int8_t x = 127;
  x++;

This has undefined behavior, because the resulting value is not representable as an int8_t. In contrast,

  int8_t x = 127;
  ++x;

is well-defined, because it is equivalent to x += 1, which is equivalent to x = (int)x + 1 after the usual arithmetic conversions (7.4 [expr.arith.conv]). No arithmetic overflow occurs. The presence or absence of undefined behavior is detectable in constant evaluation.

Proposed resolution (approved by CWG 2024-02-16):

  1. Change in 7.6.1.6 [expr.post.incr] paragraph 1 as follows:

    The value of a postfix ++ expression is the value of its operand. [Note 1: 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. An operand with volatile-qualified type is deprecated; see D.4 [depr.volatile.type]. The value of the operand object is modified (3.1 [defns.access]) by adding 1 to it as if it were the operand of the prefix ++ operator (7.6.2.3 [expr.pre.incr]). 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 2: Therefore, a function call cannot 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 7.6.6 [expr.add] and 7.6.19 [expr.ass].
  2. Change in 7.6.2.3 [expr.pre.incr] as follows:

    The operand of prefix ++ or -- is modified (3.1 [defns.access]) by adding 1. The operand shall be a modifiable lvalue. The type of the operand shall not be an arithmetic type other than of type cv bool, or a pointer to a completely-defined object type. An operand with volatile-qualified type is deprecated; see D.4 [depr.volatile.type]. The result is the updated operand; it is an lvalue, and it is a bit-field if the operand is a bit-field. The expression ++x is otherwise equivalent to x+=1 and the expression --x is otherwise equivalent to x-=1 . [Note 1: See the discussions of addition (7.6.6 [expr.add]) and assignment operators (7.6.19 [expr.ass]) for information on conversions. end note]

    The operand of prefix -- is modified (3.1 [defns.access]) by subtracting 1. The requirements on the operand of prefix -- and the properties of its result are otherwise the same as those of prefix ++. [Note 2: For postfix increment and decrement, see 7.6.1.6 [expr.post.incr]. —end note]