C++ Logo

std-discussion

Advanced search

Re: Is it valid use reinterpret_cast to form pointer to object?

From: Thiago Macieira <thiago_at_[hidden]>
Date: Mon, 31 Jul 2023 16:44:04 -0700
On Monday, 31 July 2023 13:35:15 PDT Brian Bi via Std-Discussion wrote:
> You do need to call `std::launder` after the `reinterpret_cast` because the
> object that is nested within the `storage_` array is not
> pointer-interconvertible with it.

Except that the standard has a loophole if the compiler doesn't see all
possible object lifetime starts.

http://eel.is/c++draft/basic.compound#4
> Two objects a and b are pointer-interconvertible if:
> - ...
> - one is a union object and the other is a non-static data member of that
> object
> - ...
> - there exists an object c such that a and c are pointer-interconvertible,
> and c and b are pointer-interconvertible

For any two types X1 and X2, you can define a union

union U
{
    X1 x1;
    X2 x2;
};

>From 4.2, an object of type X1 and and one of U are pointer-interconvertible
and ditto for X2 and U. From 4.4, because of that, X1 and X2 are pointer-
interconvertible.

This means this has to be allowed:
  X1 *x2 = get_pointer_x1();
  auto x2 = reinterpret_cast<X2 *>(x1);
unless the compiler can prove that get_pointer_x1() did not create an object
of type U there.

In particular, if get_pointer_x1() is malloc(), then the compiler's hands are
tied and it has to assume it did create an object of type U.

In the OP's case, if he were to insert an opaque function:

alignas(T) std::byte storage_[sizeof(T)];
opaque_function(&storage_);
T *ptr_ = reinterpret_cast<T *>(&storage_);

then this is no longer UB because the compiler can't prove opaque_function()
didn't new U there with X1 = uchar[sizeof(T)] and X2 = T.

If the function isn't opaque, then OP must insert something to convince the
compiler that U or T were created there (or, better yet, actually do it), so
that's either std::start_lifetime_as or std::construct_at or something
similar. But what are we gaining from this? The case when the compiler *can*
prove you didn't create such an object is the exception, not the rule.

-- 
Thiago Macieira - thiago (AT) macieira.info - thiago (AT) kde.org
   Software Architect - Intel DCAI Cloud Engineering

Received on 2023-07-31 23:44:06