cplusplus / CWG

Core Working Group
24 stars 7 forks source link

[intro.object] Object representations of implicitly created objects #347

Closed frederick-vs-ja closed 1 year ago

frederick-vs-ja commented 1 year ago

Full name of submitter (unless configured in github; will be published with the issue): Jiang An

Reference (section label): [intro.object], [basic.indet]

Link to reflector thread (if any):

Issue description:

When the bytes in a given storage are already set to determined values and objects are implicitly created within that storage, is the object representation of such an implicitly created object guaranteed to be same as the previously set bytes?

For example, assuming int is of little endian:

#include <cassert>
#include <new>

int main() {
  alignas(int) unsigned char buf[sizeof(int)]{42};
  assert(*std::launder(std::reinterpret_cast<int*>(buf)) == 42); // Is this guaranteed to pass?
}

If the new object can hold previous object represetations, it seems that we can implement std::start_lifetime_as<T>(p) as something like return static_cast<T*>(::operator new(sizeof(T), p)); (modulo cv-qualification and checking for implicit-lifetime types).

This issue may be related CWG1997.

Suggested resolution:

languagelawyer commented 1 year ago

When the bytes in a given storage are already set to determined values

I think, similarly to modifying, initializing an object ≠ initializing its bytes

is the object representation of such an implicitly created object guaranteed to be same as the previously set bytes?

This won't mean the object will have non-indeterminate value, since the value is not a function of object representation

This issue may be related CWG1997

I'd say it is related to CWG2533. Anyway, https://timsong-cpp.github.io/cppwp/n4868/basic.indet#1 has the answer

frederick-vs-ja commented 1 year ago

I think, similarly to modifying, initializing an object ≠ initializing its bytes

Yes. There seems to be a more general issue that the value of an object (at least of a trivially copyable type) is not always synchronized with the underlying value bits.

However, it's specified that value representation determines the value of an object of a trivially copyable type (N4868 [basic.types.general] p4). Although it's not clear where the object/value representation is (P1839).

Is [basic.indet] p1 implying that it's possible for an object of an indeterminate value and another object of a determined value to have the same value representation? Or, while the value representation of an object determines its value, the indeterminacy is ruled out?

languagelawyer commented 1 year ago

However, it's specified that value representation determines the value of an object of a trivially copyable type

Which is obviously not the case, and this wording should be removed. E.g. a pointer to an object and a pointer past the end of some other can haz the same representation, but they are different values. You can recreate a billion of objects in the same buffer in a loop, and pointers to them are a billion of different values with, likely, the same representation.

bit_cast is defined only for objects of trivially copyable types, but is aware that a value is not determined by the bit pattern

Is [basic.indet] p1 implying that it's possible for an object of an indeterminate value and another object of a determined value to have the same value representation?

I do not have a definitive answer. IIUC Core guys have model of «indeterminate bit values» in their head. I like some C DR response model that indeterminate value can be represented by any bit pattern.

jensmaurer commented 1 year ago

An "indeterminate value" does not (necessarily) have a manifested bit pattern at all. You can't inspect an "indeterminate value" without undefined behavior, so there is no way to determine the bit pattern within the abstract machine.

languagelawyer commented 1 year ago

Reading unsigned char object with indeterminate value to immediately write into another such object is not UB, one can write into a volatile object associated with, say, teletype tape and observe the bit pattern this way 🤡

jensmaurer commented 1 year ago

"within the abstract machine" doesn't feature teletype tape, I think.

Anyway, the original question here seems answered; implicitly created objects have indeterminate value per https://timsong-cpp.github.io/cppwp/n4868/basic.indet#1 .