https://gcc.gnu.org/bugzilla/show_bug.cgi?id=93246
--- Comment #4 from Martin Liška <marxin at gcc dot gnu.org> --- (In reply to Richard Biener from comment #3) > So FRE optimizes > > wo.value = &buf; > _48 = __MEM <struct Optional *> ((struct Optional * *)&wo); > _20 = __MEM <const bool> ((bool *)_48); > if (_20 != _Literal (bool) 0) > goto __BB4; > else > goto __BB3; > > __BB(3): > _48->inner.present = _Literal (bool) 1; > goto __BB4; > > __BB(4): > _49 = __MEM <struct Optional *> ((struct Optional * *)&wo); > _52 = __MEM <const bool> ((bool *)_49); > > in a way disregarding the store via _48->inner.present. Adjusted testcase > that doesn't need -fsanitize=address. I wonder if that results in the > same bisection for the "fix"? > > #include <iostream> > > template <typename = void> struct Optional { > auto is_present() const { return inner.present; } > > auto set_present() { > if (not is_present()) > inner.present = true; > } > > struct InnerType { > bool present = false; > char padding[1] = {0}; > }; > > using inner_t = InnerType; > // InnerType inner = {}; // this works as expected! > inner_t inner = {}; // this doesn't! > }; > > template <typename WrappedType> struct Wrapper { > auto operator-> () { return value; } > > WrappedType *value; > }; > > void __attribute__((noipa)) foo(Optional<>& x) {} > > int main() { > Optional<> buf{}; > foo(buf); > Wrapper<Optional<>> wo = {&buf}; > > wo->set_present(); > > auto x = wo->is_present(); > auto y = wo->is_present(); > std::cout << "x=" << x << ", y=" << y; > auto z = wo->is_present(); > std::cout << ", z=" << z << "\n"; > } This test-case started to be fixed since g:ff6686d2e5f797d6