Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[class.cdtor] Access to virtual base class subobjects via derived classes #206

Open
LegionMammal978 opened this issue Dec 31, 2022 · 1 comment

Comments

@LegionMammal978
Copy link

LegionMammal978 commented Dec 31, 2022

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

Reference (section label): [class.cdtor] paragraph 2

Link to reflector thread (if any):

Issue description:

According to [class.cdtor] paragraph 2,

During the construction of an object, if the value of the object or any of its subobjects is accessed through a glvalue that is not obtained, directly or indirectly, from the constructor's this pointer, the value of the object or subobject thus obtained is unspecified.

Consider the following example:

#include <iostream>

struct A {
  A() : i(42) {}
  int i;
};

struct B : virtual A {
  B(int* p) { std::cout << *p << '\n'; }
};

struct C : virtual A, B {
  C() : B(&i) {}
};

int main() { C c; }

Since the A object is a (virtual) base class subobject of the B object, and since i is a member subobject of the A object, i is a subobject of the B object. Therefore, the wording implies that accessing i via *p in B's constructor yields an unspecified value, since p was not obtained from the this pointer of B's constructor, but instead from the this pointer of C's constructor.

This is problematic for virtual bases that store pointers to their own subobjects. Consider the following example:

#include <iostream>

struct A {
  A() : i(42), p(&i) {}
  A(const A&) = delete;
  A& operator=(const A&) = delete;
  int i;
  int* p;
};

struct B : virtual A {
  B() { std::cout << *p << '\n'; }
};

struct C : virtual A, B {};

int main() { C c; }

Here, the value of p was obtained from the this pointer of A's constructor, which was obtained directly from the this pointer of C's constructor. Therefore, accessing subobject i via *p in B's constructor again yields an unspecified value.

I suggest loosening this restriction to allow base class constructors to receive subobject pointers from constructors of derived classes.

Suggested resolution:

Change [class.cdtor] paragraph 2 as follows:

During the construction of an object, if the value of the object or any of its subobjects is accessed through a glvalue that is not obtained, directly or indirectly, from the constructor's this pointer of the constructor invoked to initialize the most derived object, the value of the object or subobject thus obtained is unspecified.

@Eisenwave
Copy link

Related: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=110912

GCC devs have interpreted this paragraph to imply that no aliasing takes place between this and any constructor parameters, for which the wording isn't strong enough.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants