How to get around GCC ‘*((void*)& b +4)’ may be used uninitialized in this function warning while using boost::optional
Solution 1
There are two levels of uninitialized analysis in gcc:
-Wuninitialized
: flags variables that are certainly used uninitialized-Wmaybe-uninitialized
: flags variables that are potentially used uninitialized
In gcc (*), -Wall
turns on both levels even though the latter has spurious warnings because the analysis is imperfect. Spurious warnings are a plague, so the simplest way to avoid them is to pass -Wno-maybe-uninitialized
(after -Wall
).
If you still want the warnings, but not have them cause build failure (through -Werror
) you can white list them using -Wno-error=maybe-uninitialized
.
(*) Clang does not activate -Wmaybe-uninitialized
by default precisely because it's very imprecise and has a good number of false positives; I wish gcc followed this guideline too.
Solution 2
I have found that changing the construction of b into the following (effectively equal) code:
auto b = boost::make_optional(false,0);
eliminates the warning. However, the following code (which is also effectively equal):
boost::optional<int> b(false,0);
does not eliminate the warning. It's still a little unsatisfactory...
Solution 3
Had the same issue with this piece of code:
void MyClass::func( bool repaint, bool cond )
{
boost::optional<int> old = m_sizeLimit; // m_sizeLimit is a boost::optional<int> class attribute
if ( cond )
m_sizeLimit = 60;
else
m_sizeLimit.reset();
if ( repaint )
{
if ( old != m_sizeLimit ) // warning here
doSomething();
}
}
Could not get rid of the warning with Paul Omta answer, tried to write:
boost::optional<int> old;
if ( m_sizeLimit )
old = boost::make_optional<int>(true, m_sizeLimit.value());
else
old = boost::make_optional<int>(false, 0);
...with no success.
Did not want to completely disable the warning from my code, so I found an alternative solution I would recommend: disable the warning locally:
#ifdef SDE_MOBILE
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wmaybe-uninitialized"
#endif
if ( old != m_sizeLimit ) // warning here
doSomething();
#ifdef SDE_MOBILE
#pragma GCC diagnostic pop
#endif
Solution 4
I had a type which wasn't easily constructed so didn't want to go the boost::make_optional route. Assigning an auto variable using the return from a function got around this problem for me. So you can do:
boost::optional<Foo> Default()
{
return boost::none;
}
auto var(Default());
This will also work as a one line lambda so you can just do:
auto var([]()->boost::optional<Foo> { return boost::none; }());
Paul Omta
Updated on June 19, 2022Comments
-
Paul Omta almost 2 years
I have code similar to the following:
#include <boost/optional.hpp> ::boost::optional<int> getitem(); int go(int nr) { boost::optional<int> a = getitem(); boost::optional<int> b; if (nr > 0) b = nr; if (a != b) return 1; return 0; }
When compiling with GCC 4.7.2 with Boost 1.53, using the following command:
g++ -c -O2 -Wall -DNDEBUG
The following warning is issued:
13:3: warning: ‘((void)& b +4)’ may be used uninitialized in this function [-Wmaybe-uninitialized]
Apparently, the root problem lies with GCC. See GCC Bugzilla Does anyone know a workaround?
-
rubenvb over 10 yearshow about
auto b = boost::make_optional<int>(false, 0);
? -
Paul Omta over 10 years@rubenvb: using auto, I consider that to be better style. I'll change the answer.
-
Angew is no longer proud of SO over 7 yearsI had the exact same warning, but this solution didn't help me. I had to get rid of the
optional
altogether (which I fortunately could in my situation). -
mindriot about 7 yearsThanks for the solution. Ran into the problem with gcc 4.9.2, and your
#pragma
-based solution worked and was the best option for me. -
Marc Glisse almost 6 yearsSomehow this causes gcc to set the TREE_NO_WARNING internal flag on this variable. The warning is not unlikely to come back in a future version, this is more fragile than the pragma.
-
Kiril Kirov about 3 yearsYou're a life saver! :) Strangely enough, this is an issue only with gcc 4.9.2 and it works perfectly fine on 4.9.3. Even more - it works fine on 4.9.2 in debug builds, but fails on release builds.