C++ Logo


Advanced search

Re: [ub] type punning through congruent base class?

From: Richard Smith <richardsmith_at_[hidden]>
Date: Mon, 6 Jan 2014 15:44:29 -0800
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).

Received on 2014-01-12 04:28:07