I have code snippet that, I assume, should not produce asserton failure. But with gcc 13.2 with O3 option it fails.
So I think it is Undefined Behaviour here. clang and gcc with O0 works fine. And if I change destructor to some other method - assertion failure dissapears.
#include <cstddef>
#include <new>
#include <cassert>
struct Foo
{
~Foo()
{
destructed = true;
}
bool destructed = false;
};
int main()
{
alignas(alignof(Foo)) std::byte buffer[sizeof(Foo)];
Foo* p1 = std::launder(reinterpret_cast<Foo*>(buffer));
new (p1) Foo();
assert(p1->destructed == false);
Foo* p3 = std::launder(reinterpret_cast<Foo*>(buffer));
p3->~Foo();
//////////// Assertion failure ?????????????????????????
assert(p3->destructed == true);
return 0;
}
The first call to
std::launderhas undefined behavior, because when you call it there is noFooobject in its lifetime at the provided address (becauseFooisn't an implicit-lifetime type). That's a precondition forstd::launder. You may only do thestd::laundercall after the placement-new.And
p3->destructed == truehas undefined behavior either way, because you ended the lifetime of theFooobject with its destructor call. After that you aren't allowed to access the object anymore.