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::launder
has undefined behavior, because when you call it there is no Foo
object in its lifetime at the provided address (because Foo
isn't an implicit-lifetime type). That's a precondition for std::launder
. You may only do the std::launder
call after the placement-new
.
And p3->destructed == true
has undefined behavior either way, because you ended the lifetime of the Foo
object with its destructor call. After that you aren't allowed to access the object anymore.