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

            Bug ID: 93246
           Summary: Unexpected program behavior when -fsanitize=address
                    and -O2/O3 used
           Product: gcc
           Version: 9.2.0
            Status: UNCONFIRMED
          Severity: normal
          Priority: P3
         Component: sanitizer
          Assignee: unassigned at gcc dot gnu.org
          Reporter: mtekieli+gcc at gmail dot com
                CC: dodji at gcc dot gnu.org, dvyukov at gcc dot gnu.org,
                    jakub at gcc dot gnu.org, kcc at gcc dot gnu.org, marxin at 
gcc dot gnu.org
  Target Milestone: ---

#include <iostream>

/*
$ g++-9 -O2 -fsanitize=address main.cpp && ./a.out
x=0, y=0, z=1
$ g++-8 -O2 -fsanitize=address main.cpp && ./a.out
x=1, y=1, z=1
$ clang++-9 -O2 -fsanitize=address main.cpp && ./a.out
x=1, y=1, z=1
*/

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;
};

int main() {
  Optional<> 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";
}

/*
Above code produces expected results when:
* -fsanitize=address is not used
* -O1 instead of -O2/O3 is used
* gcc8 is used
* InnerType instead of inner_t alias is used
*/

Reply via email to