Date: Sun, 25 Dec 2022 12:33:36 -0500
On Sun, Dec 25, 2022 at 7:08 AM Thiago Macieira via Std-Discussion
<std-discussion_at_[hidden]> wrote:
> That's an interesting reading. Are you concluding that
>
> B(&i)
>
> *was* valid and specified because it was obtained from C's this
> pointer, but once control transfers to B's constructor, it's no
> longer valid? This seems to be the same conclusion in your second
> example.
Yes, that's roughly correct. At this point, it's valid for C's
constructor to form a pointer to i, since the A subobject that i is a
direct member of has already started (and finished) its construction
(11.9.5 [class.cdtor] para. 3). It would also be valid for C's
constructor to access the value of i at this point (since it no longer
has an indeterminate value), for B's constructor to access the value
of i via its own this pointer, or for B's constructor to modify the
value of i via *p. But when B's constructor attempts to read the value
of i via *p, the wording implies that the access results in an
unspecified value.
> I add that this is something UB could do, but not unspecified.
What do you mean? The wording says that the value is unspecified, not
that the behavior is undefined. At worst, the program could have
implementation-defined behavior from reading an invalid pointer value.
This paragraph has been around for a long time, and to me it appears
not to have been properly updated to account for virtual base classes.
In ISO C++98 (12.1 [class.ctor] para. 15), it applied only to const
objects under construction. In ISO C++17, it was expanded to apply to
all objects under construction, in response to DR 2271. Based on the
examples, the rationale appears to be to prevent programs from
referring to the object under construction from external sources such
as global variables. However, its wording is broad enough to also
prevent a constructor from accessing a pointer into a virtual base
class subobject, if that pointer was otherwise validly obtained from
the constructor of a derived class.
<std-discussion_at_[hidden]> wrote:
> That's an interesting reading. Are you concluding that
>
> B(&i)
>
> *was* valid and specified because it was obtained from C's this
> pointer, but once control transfers to B's constructor, it's no
> longer valid? This seems to be the same conclusion in your second
> example.
Yes, that's roughly correct. At this point, it's valid for C's
constructor to form a pointer to i, since the A subobject that i is a
direct member of has already started (and finished) its construction
(11.9.5 [class.cdtor] para. 3). It would also be valid for C's
constructor to access the value of i at this point (since it no longer
has an indeterminate value), for B's constructor to access the value
of i via its own this pointer, or for B's constructor to modify the
value of i via *p. But when B's constructor attempts to read the value
of i via *p, the wording implies that the access results in an
unspecified value.
> I add that this is something UB could do, but not unspecified.
What do you mean? The wording says that the value is unspecified, not
that the behavior is undefined. At worst, the program could have
implementation-defined behavior from reading an invalid pointer value.
This paragraph has been around for a long time, and to me it appears
not to have been properly updated to account for virtual base classes.
In ISO C++98 (12.1 [class.ctor] para. 15), it applied only to const
objects under construction. In ISO C++17, it was expanded to apply to
all objects under construction, in response to DR 2271. Based on the
examples, the rationale appears to be to prevent programs from
referring to the object under construction from external sources such
as global variables. However, its wording is broad enough to also
prevent a constructor from accessing a pointer into a virtual base
class subobject, if that pointer was otherwise validly obtained from
the constructor of a derived class.
Received on 2022-12-25 17:33:49