Date: Mon, 26 Dec 2022 11:22:41 -0500
On Mon, Dec 26, 2022 at 7:05 AM Thiago Macieira via Std-Discussion
<std-discussion_at_[hidden]> wrote:
> FYI, Arthur filed a bug against GCC at
> https://gcc.gnu.org/bugzilla/show_bug.cgi?id=108216
Ah, then perhaps my concern isn't so independent after all: reading
that bug (and the linked bugs) is what prompted me to take a closer
look at [basic.life] and [class.cdtor] in the first place.
> The original question in #standardese was this source code:
>
> struct A {
> virtual void f();
> };
>
> struct B : virtual A {};
>
> struct C : virtual A {
> C(B* p) {
> A* q = p; // <---
> }
> };
>
> struct D : B, C {
> D(): C(this) {}
> };
>
> Which when compiled with GCC does produce a nonsensical pointer
> (it's just over 4 MB away from where it should be, on testing).
> Clang seems to be similarly affected, but only if the bases aren't
> empty).
>
> And yet everyone who looks at this code says that it looks correct
> and valid.
For what it's worth, that code is also correct and valid by my own
reading. Converting this from D* to B* is valid since there are no
other bases between the two types (11.9.5 [class.cdtor] para. 3), and
converting p from B* to A* is valid because the B subobject is within
its lifetime. Perhaps the compilers (and/or the ABIs) are having
trouble with the Standard's implication that each and every base class
subobject, including each virtual base class subobject, must be fully
valid and usable immediately after its constructor returns.
<std-discussion_at_[hidden]> wrote:
> FYI, Arthur filed a bug against GCC at
> https://gcc.gnu.org/bugzilla/show_bug.cgi?id=108216
Ah, then perhaps my concern isn't so independent after all: reading
that bug (and the linked bugs) is what prompted me to take a closer
look at [basic.life] and [class.cdtor] in the first place.
> The original question in #standardese was this source code:
>
> struct A {
> virtual void f();
> };
>
> struct B : virtual A {};
>
> struct C : virtual A {
> C(B* p) {
> A* q = p; // <---
> }
> };
>
> struct D : B, C {
> D(): C(this) {}
> };
>
> Which when compiled with GCC does produce a nonsensical pointer
> (it's just over 4 MB away from where it should be, on testing).
> Clang seems to be similarly affected, but only if the bases aren't
> empty).
>
> And yet everyone who looks at this code says that it looks correct
> and valid.
For what it's worth, that code is also correct and valid by my own
reading. Converting this from D* to B* is valid since there are no
other bases between the two types (11.9.5 [class.cdtor] para. 3), and
converting p from B* to A* is valid because the B subobject is within
its lifetime. Perhaps the compilers (and/or the ABIs) are having
trouble with the Standard's implication that each and every base class
subobject, including each virtual base class subobject, must be fully
valid and usable immediately after its constructor returns.
Received on 2022-12-26 16:22:53