cplusplus / CWG

Core Working Group
23 stars 7 forks source link

[basic.life] p8 An object that was originally non-const cannot have a fallback after first transparently replaced #376

Open xmh0511 opened 1 year ago

xmh0511 commented 1 year ago

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

[basic.life] p8 says:

If, after the lifetime of an object has ended and before the storage which the object occupied is reused or released, a new object is created at the storage location which the original object occupied, ..., or the name of the original object will automatically refer to the new object and, once the lifetime of the new object has started, can be used to manipulate the new object, if the original object is transparently replaceable (see below) by the new object. An object o1 is transparently replaceable by an object o2 if:

  • [...]
  • o1 is not a const, complete object, and
  • [...]

Consider this example:

int main(){
    int a = 0;
    using type = int const;
    new (&a) type(1);  // #1
    new (&a) int(0);  // #2
    auto r = a; // UB
}

After #1, a refers to a const object o1, after #2, o1 has its lifetime ended and since o1 is not transparently replaceable with o2( an object of int) according to the above bullet, a can never automatically refer to the new created object. The subsequent access to a results in UB.

frederick-vs-ja commented 1 year ago

Related to CWG2514. A possible resolution is making new-expressions never create a complete object of a cv-qualified type (while keeping the type of new-expressions).

xmh0511 commented 1 year ago

A possible resolution is making new-expressions never create a complete object of a cv-qualified type (while keeping the type of new-expressions).

This would introduce another issue: whether such two objects are pointer-interconvertible or not.

frederick-vs-ja commented 1 year ago

This would introduce another issue: whether such two objects are pointer-interconvertible or not.

They are probably not, which is status quo. But it seems that [basic.life] p8 provides stronger guarantees than those of pointer-interconvertibility.

Perhaps it would be better to additionally specify the following (which seemingly belongs to another issue)?

o1 and o2 are considered to be the same object for the purpose of pointer-interconvertibility ([basic.compound]).

jensmaurer commented 1 year ago

What exactly is the defect here?

I think the analysis for the original example is correct, and that's what the rules of the language are.