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

Reply via email to