I'm compiling the attached test case with "gcc version 4.5.0 20091018 (experimental) [trunk revision 152966] (Ubuntu 20091018-0ubuntu1)".
When using the command line "gcc -Wuninitialized -Os -o test test_gccbug.c", I'm getting the following incorrect warning:
test_gccbug.c: In function 'main':
test_gccbug.c:17:6: warning: 'ret' may be used uninitialized in this function
Same happens with different builds of GCC 4.4.2, 4.4.1 and 4.3.4.
No such warning occurs with builds of GCC 4.2.4 and 4.1.3.
This problem does not occur if one or more of the following is done:
- You change the optimization level to -O0 or -O1 (-O2 and -O3 still trigger the bug in this GCC 4.5.0 version, but not always in older versions I've tested)
- You comment out line 10 of the test case
- You change line 22 of the test case to just 'if (!argc)'
Created attachment 19084 [details]
The test case
Created attachment 19085 [details]
The preprocessed test case
This would need conditional PHIs, so a duplicate of PR20968.
GCC never detects that ret is always initialized, it doesn't warn because at low optimization levels we do not warn for PHIs or because CCP (PR18501) just initializes the variable (probably to 1 or 10). There is some differences between the dumps of -O1 and -O2 in the way the logical or is transformed int bitwise-or and how dom1 deals with each of them, but I cannot tell if there is some missing optimization involved.
*** This bug has been marked as a duplicate of 20968 ***
PR20968 was closed, but this one is still valid in some cases. In particular this testcase with -Os produces a warning.
int translate(int in);
int main(int argc, char* argv)
ret = translate(5);
if (!argc || !ret)
ret = 1;
The reason is that with -Os, the check "if (!argc || !ret)" is transformed into:
# ret_1 = PHI <ret_5(D)(2), [pr19085.c : 8:9] ret_8(3)>
# .MEM_3 = PHI <.MEM_6(D)(2), .MEM_7(3)>
[pr19085.c : 10:7] # RANGE [0, 1]
_9 = argc_4(D) == 0;
[pr19085.c : 10:16] # RANGE [0, 1]
_10 = ret_1 == 0;
[pr19085.c : 10:13] # RANGE [0, 1]
_11 = _10 | _9;
[pr19085.c : 10:6] if (_11 != 0)
-Os disables jump threading except for very specific circumstances because the block duplication generally increases code size. As a result of restricting the optimizer, certain paths through the CFG which are unexecutable have to be left in the CFG which leads to the false positive.
*** Bug 58698 has been marked as a duplicate of this bug. ***
*** Bug 58455 has been marked as a duplicate of this bug. ***
*** Bug 57072 has been marked as a duplicate of this bug. ***
*** Bug 55759 has been marked as a duplicate of this bug. ***
*** Bug 49848 has been marked as a duplicate of this bug. ***
It is reproducible even with -O1:
int a, b;
a = f();
b = f();
if (a && b)
$ gcc -O1 -Wuninitialized -c a.c
a.c: In function 'main':
a.c:12:15: warning: 'b' may be used uninitialized in this function [-Wmaybe-uninitialized]
if (a && b)
$ gcc -v
Using built-in specs.
Configured with: /ws/builds2/jenkins/src/du/dilos-userland-review/components/gcc48/gcc-4.8.2/configure --prefix=/usr/gcc/4.8 --mandir=/usr/gcc/4.8/share/man --bindir=/usr/gcc/4.8/bin --libdir=/usr/gcc/4.8/lib --sbindir=/usr/gcc/4.8/sbin --infodir=/usr/share/info --without-gnu-as --with-as=/usr/bin/as --build=sparc-sun-solaris2.11 --infodir=/usr/gcc/4.8/share/info --libexecdir=/usr/gcc/4.8/lib --enable-languages=c,c++,fortran,objc --enable-shared --enable-targets=sparcv9-sun-solaris2.11 --without-gnu-ld --with-ld=/usr/bin/ld
Thread model: posix
gcc version 4.8.2 (GCC)
This is already fold-const.c transforming TRUTH_ANDIF into TRUTH_AND.
(In reply to Richard Biener from comment #12)
> This is already fold-const.c transforming TRUTH_ANDIF into TRUTH_AND.
I cannot find the discussion now, but I think it was discussed in one of the many duplicates that this is not wrong-code, but still it fools the Wuninitialized code and it is a bug despite gcc generating correct code.
(In reply to Manuel López-Ibáñez from comment #13)
> (In reply to Richard Biener from comment #12)
> > This is already fold-const.c transforming TRUTH_ANDIF into TRUTH_AND.
> I cannot find the discussion now, but I think it was discussed in one of the
> many duplicates that this is not wrong-code, but still it fools the
> Wuninitialized code and it is a bug despite gcc generating correct code.
probably correct in practice but it may change a && b to b && a which means
it may introduce an unconditional use of b which techincally is undefined
behavior (which we may not introduce). Thus the 'wrong-code'.