Launder dereferencing type-punned address

This is a small patch to avoid strict aliasing issues manifested in GCC
I came across a while ago.

The test case was complex and the failing assertion with a matcher was
present only with `-O3`, so I don't have a standalone test. However, I
manually confirmed adding `-fno-strict-aliasing` fixed the issue before
this patch, and `-O3` behaved as intended after this patch without
turning strict-aliasing off.

There is a similar previous change in 50ce520161.

For the relevant clause from the C++17 standard, refer to below note
from https://timsong-cpp.github.io/cppwp/n4659/basic.life#8:

> [ Note: If these conditions are not met, a pointer to the new object
can be obtained from a pointer that represents the address of its
storage by calling std::launder ([support.dynamic]).  — end note ]
This commit is contained in:
Omer Ozarslan 2025-12-29 10:17:12 -08:00
parent 9156d4caac
commit 9fec814a9a

View File

@ -42,6 +42,7 @@
#include <atomic>
#include <functional>
#include <memory>
#include <new>
#include <ostream>
#include <string>
#include <type_traits>
@ -402,11 +403,9 @@ class [[nodiscard]] MatcherBase : private MatcherDescriberInterface {
template <typename M, bool = MatcherBase::IsInlined<M>()>
struct ValuePolicy {
static const M& Get(const MatcherBase& m) {
// When inlined along with Init, need to be explicit to avoid violating
// When inlined along with Init, need to be laundered to avoid violating
// strict aliasing rules.
const M* ptr =
static_cast<const M*>(static_cast<const void*>(&m.buffer_));
return *ptr;
return *std::launder(reinterpret_cast<const M*>(&m.buffer_));
}
static void Init(MatcherBase& m, M impl) {
::new (static_cast<void*>(&m.buffer_)) M(impl);