On Mon, Jan 6, 2014 at 10:22 AM, Jason Merrill <jason@redhat.com> wrote:
On 01/06/2014 04:26 AM, Fabio Fracassi wrote:
> if it is not (legal): could we make it legal or would we run afoul of
> the aliasing rules?

The access is not allowed by the aliasing rules in 3.10.  But it seems
that this would be:

struct B {
   int i;

struct D {
   B bmem;
   void foo() { /* access bmem.i */ }

B b;

because B is a non-static data member of D, and 9.2/19 guarantees that
the address of D::bmem is the same as the address of the D object.

How is that fundamentally different? 9.3.1/2 makes that UB too, if 'reinterpret_cast<D&>(b)' does not refer to an object of type 'b'. And within D::foo, the implicit this->bmem would have the same problem.

If I might play devil's advocate for a moment...

  struct B { int i; };
  struct D : B {
    void foo();

  B b;

I claim this line starts the lifetime of an object of type D. Per [basic.life]p1, the lifetime of an object of type 'D' begins when storage with the proper alignment and size for type T is obtained (which "B b" happens to satisfy). The object does not have non-trivial initialization, so the second bullet does not apply.

(This is the same argument that makes this valid:

  D *p = (D*)malloc(sizeof(D));

... so any counterargument will need to explain why the two cases are fundamentally different.)



... is valid, because the cast produces the same memory address, and that memory address contains an object of type 'D' (as claimed above).