https://gcc.gnu.org/bugzilla/show_bug.cgi?id=80635
--- Comment #4 from Pedro Alves <palves at redhat dot com> --- Hi Marc, thanks much for taking a look. Looks like I over reduced in the minimal reproducer. std::optional has a boolean field to track whether the contained object had been fully initialized, which is checked in the desctructor, but I removed it because its presence doesn't affect whether the warning is emitted. Of course, std::optional has that field, but still, it warns. A couple of things that look suspiciously odd to me, even in the original testcase: - the warning is about A::m_dummy, while optional::~optional calls the m_item/T's destructor, not m_dummy's. - the warning triggers in A/optional<A>, but for some reason, only if B/optional<B> exist, as well as the maybe_b variable, which are all completely unrelated to A. This one makes me wonder if there's some miscompilation related to aliasing or or object lifetimes going on, not just a warning. Here's the corrected testcase: ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ $ cat optional2.cc //#include <optional> //#include <experimental/optional> #include <new> template<typename T> struct optional { optional () : m_dummy (), m_instantiated (false) {} ~optional () { if (m_instantiated) m_item.~T (); // won't run unless T is fully constructed. } void emplace () { new (&m_item) T (); m_instantiated = true; // not set if T() throws } union { int m_dummy; T m_item; }; bool m_instantiated; }; template <typename T> using Optional = optional<T>; // warns //using Optional = std::experimental::optional<T>; // warns too //using Optional = std::optional<T>; // warns too extern int get (); extern void set (int); struct A { A () : m (get ()) {} // warns here ~A () { set (m); } int m; }; // for some reason, need B to trigger the warning. struct B { B (); // remove or make noexcept, and the warning disappears ~B (); // remove, and the warning disappears }; void func () { Optional<A> maybe_a; Optional<B> maybe_b; // for some reason, need this here to trigger a // warning in _A_. maybe_a.emplace (); maybe_b.emplace (); // comment out, and the warning disappears. } $ /opt/gcc/bin/g++ optional2.cc -O2 -Wall -c optional2.cc: In function ‘void func()’: optional2.cc:45:15: warning: ‘maybe_a.optional<A>::<anonymous>.optional<A>::<unnamed union>::m_dummy’ may be used uninitialized in this function [-Wmaybe-uninitialized] ~A () { set (m); } ~~~~^~~ optional2.cc:59:15: note: ‘maybe_a.optional<A>::<anonymous>.optional<A>::<unnamed union>::m_dummy’ was declared here Optional<A> maybe_a; ^~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Do you see anything invalid in this version of the test?