Summary: | -Wmaybe-uninitialized and -O2: false positive with boost::optional | ||
---|---|---|---|
Product: | gcc | Reporter: | Romain Geissler <romain.geissler> |
Component: | middle-end | Assignee: | Not yet assigned to anyone <unassigned> |
Status: | RESOLVED FIXED | ||
Severity: | normal | CC: | akrzemi1, msebor |
Priority: | P3 | Keywords: | diagnostic |
Version: | unknown | ||
Target Milestone: | 10.0 | ||
Host: | Target: | ||
Build: | Known to work: | ||
Known to fail: | Last reconfirmed: | 2016-10-20 00:00:00 | |
Bug Depends on: | |||
Bug Blocks: | 24639 | ||
Attachments: |
test.cpp
test.i Reduced preprocessed test-case |
Created attachment 39844 [details]
test.i
There are already filed bug reports about false positive for this warning. This might be a dup of one of those. Also this warning is hard not to get false positives really for conditional unitialized variables which is why the option was split into two. One for the hard for GCC to prove that it is not a false positive (-Wmaybe-uninitialized). "which is why the option was split into two." Ok, it makes sense to have one reliable option that handles fewer cases, but doesn't have false positives. And another that checks more, but with false positives. The only problem I have with -Wmaybe-uninitialized is that it is included in -Wall. I thought that -Wall was meant to collect the warnings without false positives? Would it be possible not to turn -Wmaybe-uninitialized on when -Wall is turned on? Created attachment 39848 [details]
Reduced preprocessed test-case
Confirmed. Well. someFunction () is optimized down to just void someFunction() () { int aOptional$4; struct C D.2560; struct C D.2555; void * _4; <bb 2>: C::operator mpl_::B (&D.2555); D.2555 ={v} {CLOBBER}; _4 = operator new (8); C::operator mpl_::B (&D.2560); <bb 3>: D.2560 ={v} {CLOBBER}; MEM[(int *)_4 + 4B] = aOptional$4_2(D); return; <L0>: operator delete (_4, 8); resx 3 so unless C::operator mpl_::B (&D.2560); always throws we store aOptional$4_2(D) (uninitialized) to MEM[(int *)_4 + 4B]. The warning itself is a bit misleading I guess. Thus int __trans_tmp_1 = p1.get_impl (); new (m_storage.address ()) int(__trans_tmp_1); and int get_impl () { union { void *ap_pvoid; int *as_ptype; } caster{m_storage.address ()}; get_impl___trans_tmp_3 = *caster.as_ptype; int __trans_tmp_2 = get_impl___trans_tmp_3; B __trans_tmp_4 = C (); return __trans_tmp_2; } doesn't cover up the fact that m_storage is not initialized. This might be an artifact of the testcase reduction of course. This still reproduces in version 7.2. Here is a Wandbox link: https://wandbox.org/permlink/5uCAr5u0xpynljhQ Here is the code, you need to compile it with -DNDEBUG -O2: ``` #include <cassert> class O { int _val; bool _init = false; public: O() = default; O(const int& i) : _val(i), _init(true) {} explicit operator bool () const { return _init; } const int& operator*() const { assert (_init); return _val; } void operator=(int const& i) { _init = true; _val = i; } }; bool equal_pointees ( O const& x, O const& y ) { return (!x) != (!y) ? false : ( !x ? true : (*x) == (*y) ) ; } O getitem(); int main(int argc, const char *[]) { O a = getitem(); O b; if (argc > 0) b = argc; if (equal_pointees(a, b)) return 1; return 0; } ``` Is there a way to give a hint to the compiler (like with an attribute) so that the warning is silenced? |
Created attachment 39843 [details] test.cpp Hi, I am having a false positive when using -O2 and -Wmaybe-uninitialized with the latest gcc 6 (g++ (GCC) 6.2.1 20160916 (Red Hat 6.2.1-2) from Fedora 24) with boost::optional. Unfortunately my attempt to reduce the test case by trying to extract the relevant boost parts failed. Please find attached the reproducer test.cpp, that includes boost/optional.hpp (tested with boost 1.60 and 1.61, I have a warning in both cases). g++ -std=gnu++14 -O2 -Wall -c -o test.o test.cpp test.cpp: In function 'void someFunction(const void*)': test.cpp:22:16: warning: '*((void*)& aOptional +4)' may be used uninitialized in this function [-Wmaybe-uninitialized] Optional_t aOptional; ^~~~~~~~~ In "someFunction()" the boost::optional value that is being passed and copied is definitely not uninitialized. You can also find attached the preprocessor output in test.i Cheers, Romain