Title
Acquiring value representations and indeterminate or erroneous values
Status
open
Section
6.9.2 [basic.types.trivial]
Submitter
Hubert Tong

Created on 2026-08-17.00:00:00 last changed 5 days ago

Messages

Date: 2026-10-15.00:00:00

Possible resolution (October, 2026):

This resolution depends on the resolution of issue 3039.

  1. Change in 6.9.2 [basic.types.trivial] paragraph 1 as follows:

    Each trivially copyable type T has an implementation-defined set of discrete values. Each possible value representation of an object of type T corresponds to a distinct implementation-defined subset of this set. The union of these subsets is the set of values; for scalar types other than object pointer types, each such subset contains no more than one value. Certain operations cause an object o to acquire a value representation, in which case the object's value is replaced with an unspecified member of the corresponding subset that would result in the program having defined behavior, if any as follows:
    • Any object has indeterminate value if any of the bits in the value representation are indeterminate, otherwise any object has an erroneous value if any of the bits in its value representation are erreonous. No other subobject of o (if any) has indeterminate or an erroneous value.
    • Except where o has indeterminate value, the value of o is an unspecified member of the subset corresponding to the value representation, selected to maximize the defined prefix of the execution (4.1.2 [intro.abstract]); if the subset is empty, the value is not replaced (7.3.2 [conv.lval]).
  2. Change in 20.2.6 [obj.lifetime] paragraph 5 as follows:

    Effects: Implicitly creates objects (6.8.2 [intro.object]) within the denoted region consisting of an object a of type T whose address is p, and objects nested within a, as follows: The object representation of a is the contents of the storage prior to the call to start_lifetime_as. The value of each Each created object o of trivially copyable type acquires its value representation (6.9.2 [basic.types.trivial]) (6.9.1 [basic.types.general]) U is determined in the same manner as for a call to bit_cast<U>(E) (22.11.3 [bit.cast]), where E is an lvalue of type U denoting o, except that the storage is not accessed. The value of any other created object is unspecified.
  3. Change in 22.11.3 [bit.cast] paragraph 3 as follows: (remove rules now redundant with "acquire a value representation"; the entire result is trivially copyable per the constraints)

    Returns: An object of type To., in which the value of a bit b in the object representation is as follows: Implicitly creates objects nested within the result (6.8.2 [intro.object]). Each bit of the value representation of the result is equal to the corresponding bit in the object representation of from. Padding bits of the result are unspecified. Every trivially copyable object among the result and each object created within it acquires the value representation produced; if any such object does not receive a value, the behavior is undefined.
    • If b is a padding bit, its value is unspecified.
    • Otherwise, if b does not correspond to a bit in the value representation of from, b has indeterminate value.
    • Otherwise, if b corresponds to a bit for which no enclosing scalar object is within its lifetime, b has indeterminate value.
    • Otherwise, if the smallest enclosing scalar object within lifetime has indeterminate value (6.8.5 [basic.indet]), b has indeterminate value.
    • Otherwise, the value of b is the value of the corresponding bit in the object representation of from; if b corresponds to a bit for which the smallest enclosing scalar object within lifetime has an erroneous value, b has an erroneous value.

    Remarks: Implicitly creates objects nested within the result (6.8.2 [intro.object]). Every trivially copyable object among the result and each object created within it acquires (6.9.2 [basic.types.trivial]) the value representation produced. For any object o that is the result or a subobject thereof, of other than unsigned ordinary character type or std::byte type, if o has indeterminate value, the behavior is undefined; otherwise, if o has an erroneous value, the behavior is erroneous.

    A bit in the value representation of the result is indeterminate if it does not correspond to a bit in the value representation of from or corresponds to a bit for which the smallest enclosing object is not within its lifetime or has an indeterminate value (6.8.5 [basic.indet]). A bit in the value representation of the result is erroneous if it corresponds to a bit for which the smallest enclosing object has an erroneous value. For each bit b in the value representation of the result that is indeterminate or erroneous, let u be the smallest object containing that bit enclosing b:

    • If u is of unsigned ordinary character type or std::byte type, u has an indeterminate value if any of the bits in its value representation are indeterminate, or otherwise has an erroneous value.
    • Otherwise, if b is indeterminate, the behavior is undefined.
    • Otherwise, the behavior is erroneous, and the result is as specified above.
    The result does not otherwise contain any indeterminate or erroneous values.
Date: 2026-09-15.00:00:00

Possible resolution (September, 2026) [SUPERSEDED]:

  1. Change in 6.9.2 [basic.types.trivial] paragraph 1 as follows:

    Each trivially copyable type T has an implementation-defined set of discrete values. Each possible value representation of an object of type T corresponds to a distinct implementation-defined subset of this set. The union of these subsets is the set of values; for scalar types other than object pointer types, each such subset contains no more than one value. Certain operations cause an object o to acquire a value representation, in which case the object's value is replaced as follows:
    • For each bit b in the value representation that is indeterminate or erroneous, any scalar object enclosing b has indeterminate value if any of the bits in its value representation are indeterminate, or otherwise has an erroneous value. No other subobject of o (if any) has indeterminate or an erroneous value.
    • Except where o has indeterminate value, the value of o is with an unspecified member , if any, of the corresponding subset that would result in corresponding to the value representation, selected such that the program having would have defined behavior, if any possible.
  2. Change in 20.2.6 [obj.lifetime] paragraph 5 as follows:

    Effects: Implicitly creates objects (6.8.2 [intro.object]) within the denoted region consisting of an object a of type T whose address is p, and objects nested within a, as follows: The object representation of a is the contents of the storage prior to the call to start_lifetime_as. The value of each Each created object o of trivially copyable type acquires its value representation (6.9.1 [basic.types.general]) U is determined in the same manner as for a call to bit_cast<U>(E) (22.11.3 [bit.cast]), where E is an lvalue of type U denoting o, except that the storage is not accessed. The value of any other created object is unspecified.
  3. Change in 22.11.3 [bit.cast] paragraph 3 as follows: (remove rules now redundant with "acquire a value representation"; the entire result is trivially copyable per the constraints)

    Returns: An object of type To. Implicitly creates objects nested within the result (6.8.2 [intro.object]). Each bit of the value representation of the result is equal to the corresponding bit in the object representation of from. Padding bits of the result are unspecified. Every trivially copyable object among the result and each object created within it acquires the value representation produced; if any such object does not receive a value, the behavior is undefined. A bit in the value representation of the result is indeterminate if it does not correspond to a bit in the value representation of from or corresponds to a bit for which the smallest no enclosing scalar object is not within its lifetime or the enclosing scalar object within lifetime, if any, has an indeterminate value (6.8.5 [basic.indet]). A bit in the value representation of the result is erroneous if it corresponds to a bit for which the smallest the enclosing scalar object within lifetime, if any, has an erroneous value. Every trivially copyable object among the result and each object created within it acquires (6.9.2 [basic.types.trivial]) the value representation produced. If any object among the result of other than unsigned ordinary character type or std::byte type has indeterminate value, the behavior is undefined. Otherwise, if any object among the result of other than unsigned ordinary character type or std::byte type has erroneous value, the behavior is erroneous. For each bit b in the value representation of the result that is indeterminate or erroneous, let u be the smallest object containing that bit enclosing b:
    • If u is of unsigned ordinary character type or std::byte type, u has an indeterminate value if any of the bits in its value representation are indeterminate, or otherwise has an erroneous value.
    • Otherwise, if b is indeterminate, the behavior is undefined.
    • Otherwise, the behavior is erroneous, and the result is as specified above.
    The result does not otherwise contain any indeterminate or erroneous values.
Date: 2026-08-17.00:00:00

(From submission #980.)

An unsigned char value that is indeterminate is not immediately causing undefined behavior per 6.8.5 [basic.indet]. When std::bit_cast is applied to such a value, converting to an unsigned char type, the "acquire a value representation" wording in 6.9.2 [basic.types.trivial] paragraph 1 is not equipped to handle the situation.

Furthermore, consider:

  #include <cstring>

  int main() {
    int x = 42, *p = &x, *q = p + 1;
    std::memcpy(&p, &q, sizeof(p)); // giving `p` the value of `q` would _not_ lead to the
	       // program having defined behaviour
    return *p; // Is the value of `p` here still `&x`? Prior to P2434R5, no.
  }
History
Date User Action Args
2026-10-16 21:39:00adminsetmessages: + msg8708
2026-08-17 21:28:22adminsetmessages: + msg8650
2026-08-17 00:00:00admincreate