$ cat uninit.c static int blocksize = 4096; int bar (int); void foo (void) { int toread; int bytes; static char eof_reached = 0; toread = blocksize; while (toread != 0) { bytes = bar (toread); if (bytes <= 0) { if (bytes < 0) continue; break; } toread -= bytes; } if (bytes == 0) eof_reached = 1; } $ gcc -O2 -Wall -c uninit.c uninit.c: In function ‘foo’: uninit.c:25: warning: ‘bytes’ is used uninitialized in this function This warning is wrong, since bytes is never used uninitialized as long as blocksize is non-zero.
hmm, what happens if blocksize is zero when foo is entered.
The program logic guarantees that blocksize is never zero.
The compiler can't be expected to follow that logic. If blocksize is set to zero by some magic daemon, then the bytes would be undefined.
To clarify, the problem is the "is used" part. This should be "might be used" instead.
It is not _always_ uninitialized.
I also get the warning in 3.4.0 and 3.3.3 with your example, did you reduce it too far?
It's nothing to do with ALWAYS. It's to do with COULD BE. There are values that blocksize COULD take that would lead to bytes being uninitialized. That's all the warning is telling you. The compiler is correct to warn.
That's why it should say "might be used".
In 4.1.0, we give: t.c:8: warning: ‘bytes’ may be used uninitialized in this function So this is only a 4.0.0 bug, let me see how it is considered as "is used".
Actually rethinking the problem, the only time we could execute the "if(bytes == 0)" is not going through the loop. Maybe the order in execute_late_warn_uninitialized should be switched around but that will not fix this case as we already found that is the only time we can get there. Hmm, I think we are now missing a jump thread opportunity on the mainline then.
Maybe not. Hmm, there might be a wrong code bug here on the 4.0 branch.
thinking again out loud: The function could be changed to (which we seem to be missing on the mainline): static int blocksize = 4096; int bar (int); void foo (void) { int toread; int bytes; static char eof_reached = 0; toread = blocksize; while (1) { bytes = bar (toread); if (bytes <= 0) { if (bytes < 0) continue; goto temp; } toread -= bytes; if (toread == 0) goto temp1; } if (bytes == 0) temp: eof_reached = 1; temp1: } So comming out of the loop bytes will be zero if we break out of it but otherwise cannot, so we can skip if statement. This is a missing optimization on the mainline (someone should look into it) but now my comment #10 becomes true and we see that it is always used as uninitized.
Note after fixing PR 21559, we will be back to "is used" warning instead of "may be used".
As I mentioned, this will be come a regression again once fixing PR 21559.
Won't fix for GCC-4.0.x