UB & object lifetime

launder, implicit lifetimes, start_lifetime_as, erroneous behavior.

The hazard map: strict aliasing, signed overflow, placement new + manual destruction, and the memcpy idiom as the only legal pun. Lifetime rules are folklore more than API.

alignas(T) unsigned char slot[sizeof(T)];
T* p = new (slot) T(args);     // begin lifetime
p->~T();                       // end it yourself

No change; constexpr evaluation quietly becomes a UB detector — anything UB is ill-formed in a constant expression.

std::launder names the pointer-blessing operation after placement-new-over-const/reference members; still expert territory, but at least spellable.

new (&storage) T(next);
T* p = std::launder(reinterpret_cast<T*>(&storage));

Implicit-lifetime types (P0593): malloc-ed or memcpy-ed buffers of suitable types now contain objects without placement new — network/file deserialization gains legal footing. bit_cast covers value punning.

auto* buf = static_cast<Header*>(std::malloc(sizeof(Header)));
// Header is implicit-lifetime: reading *buf after memcpy is OK (C++20)

std::start_lifetime_as<T> finishes the deserialization story: bless existing bytes as a T (and arrays) without running a constructor.

const Frame* f = std::start_lifetime_as<Frame>(packet_bytes);

Erroneous behavior debuts: uninitialized reads become defined-but-wrong and diagnosable instead of anything-goes UB — the first installment of shrinking the UB surface by category.

int x;            // reading x is erroneous (diagnosable), not wild UB
use(x);
C++29direction · not adopted

Direction: pointer provenance standardization and extending erroneous behavior to further UB classes are the active Core threads.

C++26 per the final working draft; C++29 rows are proposals and direction, not adopted features.