cplusplus / CWG

Core Working Group
24 stars 7 forks source link

[class.dtor] The meaning of "referring to" is not a clear #107

Open xmh0511 opened 2 years ago

xmh0511 commented 2 years ago

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

[class.cdtor] p1 says

For an object with a non-trivial constructor, referring to any non-static member or base class of the object before the constructor begins execution results in undefined behavior. For an object with a non-trivial destructor, referring to any non-static member or base class of the object after the destructor finishes execution results in undefined behavior.

Consider a case that lakes to specify in the example, which would help to comprehension the meaning of "referring to"

struct X { int i; }; //trivial constructor and destructor
struct Y {
   X x;
   Y(); // non-trivial
};
extern Y yobj;
int* ptr = &yobj.x.i; // #1

Is the id-expression(x) considered as "referring to" the non-static data member x of the object Y?

Suggested resolution

If the "referring to" does not intend to cover the above case, [class.cdtor] p1 will be clear if it is changed to

For an object with a non-trivial constructor, a pointer(glvalue) referring to any member or base class subobject of the object before the constructor begins execution results in undefined behavior. For an object with a non-trivial destructor, a pointer(glvalue) referring to any member or base class subobject of the object after the destructor finishes execution results in undefined behavior.

This is clear that, in the above case, #1 does not result in undefined behavior since the glvalue(yobj.x.i) refers to the member subobject of the member subobject x of yobj where the object x's class has the trivial constructor. The same is true for the pointer value that results from the glvalue.

frederick-vs-ja commented 9 months ago

I think we should say evaluation of something and/or binding reference to some out-of-lifetime object results in undefined behavior.

If stricter restrictions are wanted, we may say evaluation of

results in UB.

It should be unnecessary to talk about a pointer to member subobject as it must be obtained from a glvalue.

But perhaps we shouldn't additionally specify UB here except for conversions involving a virtual base classes (see also CWG1517). I guess out-of-lifetime member access &yobj.x should be OK - it's unclear why the triviality of constructors/destructors is in effect.