cplusplus / CWG

Core Working Group
23 stars 7 forks source link

[basic.types.general] Disallow modifying object representations #547

Closed Eisenwave closed 4 weeks ago

Eisenwave commented 4 weeks ago

Reference (section label): [basic.types.general]

Issue description

The following code has well-defined behavior, and changes the value of an object by modifying its first byte in-place.

std::uint32_t x = 0xff;
*std::launder(reinterpret_cast<unsigned char*>(&x)) = 0;
// on some implementations, x is now zero

An object representation is a sequence of unsigned char objects, the first of which logically has to exist at the same address as the object. Therefore, std::launder can be used to obtain a pointer to the first byte of the object representation, and [basic.types.general] paragraph 4 states:

For trivially copyable types, the value representation is a set of bits in the object representation that determines a value [...]

Because the value is determined directly by the object representation, and because std::uint32_t has no padding bits, this code has well-defined behavior. The value of x should change accordingly when its object representation is being modified.

It is undesirable to support direct modifications of the object representation; there are already better mechanisms for type punning such as std::bit_cast.

Note that obtaining a pointer to the object representation raises a few additional problems:

Suggested resolution

(none yet)

Eisenwave commented 4 weeks ago

https://github.com/cplusplus/papers/issues/592 does not resolve this issue.

https://github.com/cplusplus/papers/issues/1703 does not resolve this issue.

frederick-vs-ja commented 4 weeks ago

I think this is blocked on P1839. It's currently even unclear where the object representation of an object is located. (P1839R5 clarifies that the object representation occupies the same storage of the object).

Eisenwave commented 4 weeks ago

Hmm yeah, P1839 lists this as a known issue:

The current proposed wording allows reinterpret_cast or std::launder to unsigned char* to produce a pointer to the first element of an object representation. The same cannot be said for std::byte*.

It doesn't appear to resolve that known issue though.

jensmaurer commented 4 weeks ago

P1839 should (even if it currently does not) address this. This is too large for a core issue. If you feel P1839 is stalled, please contact its author and/or submit your own paper to address the specification holes around object representations.