https://gcc.gnu.org/bugzilla/show_bug.cgi?id=93246

--- Comment #3 from Richard Biener <rguenth at gcc dot gnu.org> ---
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";
}

Reply via email to