C++ Logo


Advanced search

Subject: Re: [ub] type punning through congruent base class?
From: Richard Smith (richardsmith_at_[hidden])
Date: 2014-01-06 17:44:29

On Mon, Jan 6, 2014 at 10:22 AM, Jason Merrill <jason_at_[hidden]> 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;
> reinterpret_cast<D&>(b).foo();
> 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).

SG12 list run by herb.sutter at gmail.com