[Bug c++/80635] std::optional and bogus -Wmaybe-uninitialized warning
palves at redhat dot com
gcc-bugzilla@gcc.gnu.org
Fri May 5 09:26:00 GMT 2017
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?
More information about the Gcc-bugs
mailing list