https://gcc.gnu.org/bugzilla/show_bug.cgi?id=95349
Christopher Nerz <Christopher.Nerz at de dot bosch.com> changed:
What |Removed |Added
----------------------------------------------------------------------------
CC| |Christopher.Nerz at de dot
bosch.c
| |om
--- Comment #45 from Christopher Nerz <Christopher.Nerz at de dot bosch.com> ---
This is a critical bug which renders gcc unusable for safety relevant systems
using expected/variant or simple ipc.
You can get the same buggy behavior with far simpler code:
https://godbolt.org/z/1WTnnYceM
#include <cstdint>
#include <memory>
bool check()
{
// Just to prove that it is not a problem with alignment etc.
static_assert(alignof(double) == alignof(std::uint64_t));
static_assert(sizeof(double) == sizeof(std::uint64_t));
alignas(8) std::byte buffer[8]; // some buffer
new (buffer) double{1}; // some completely trivial data
// reuse memory -> double ends lifetime, uint64 starts lifetime
std::uint64_t * res = new (buffer) std::uint64_t;
// *res is allowed to be used as it is the correct pointer returned by new
// *res == 0x3ff0000000000000 // and gives correct value
// The very definition of std::launder says that it is suppose to be used
as:
return (*res == *std::launder(reinterpret_cast<std::uint64_t*>(buffer)));
}
int main(int argc, char **argv) {
return check(); // gives false with activatred O2 (true with O0)
}
We get the same behavior when initialisating the memory at our version of
"std::uint64_t * res = new (buffer) std::uint64_t;", but were unable to give a
minimal example for that behavior.