I've searched several of the other Wunitialized reports, but without deeper knowledge, I wasn't able to conclude whether this is a dup. Note that even if i happens to be zero-initialized, it is only in this strapped-down testcase. In the program I am hacking, I got an out-of-bound of roughly 2^31 over an array of 6 elements, pretty deep in a expression template hierarchy. ================================================================================ //Tested with (-Wall -Wextra): // * g++-4.3 (Debian 4.3.4-6) 4.3.4 // * g++-4.4 (Debian 4.4.2-9) 4.4.3 20100108 (prerelease) // * g++ (GCC) 4.5.0 20100306 (experimental) #include <iostream> int main () { int i; int array[10]; //std::cout << i; // get warning, okay for (; i<10; ++i) { // no warning std::cout << i; // no warning array [i] = i; // no warning, really hurts } // sidenote: same results for // for (int i; i<N; ++i) {...} } ================================================================================ Full triplets: Using built-in specs. Target: x86_64-linux-gnu Configured with: ../src/configure -v --with-pkgversion='Debian 4.3.4-6' --with-bugurl=file:///usr/share/doc/gcc-4.3/README.Bugs --enable-languages=c,c++,fortran,objc,obj-c++ --prefix=/usr --enable-shared --enable-multiarch --enable-linker-build-id --with-system-zlib --libexecdir=/usr/lib --without-included-gettext --enable-threads=posix --enable-nls --with-gxx-include-dir=/usr/include/c++/4.3 --program-suffix=-4.3 --enable-clocale=gnu --enable-libstdcxx-debug --enable-objc-gc --enable-mpfr --with-tune=generic --enable-checking=release --build=x86_64-linux-gnu --host=x86_64-linux-gnu --target=x86_64-linux-gnu Thread model: posix gcc version 4.3.4 (Debian 4.3.4-6) Using built-in specs. Target: x86_64-linux-gnu Configured with: ../src/configure -v --with-pkgversion='Debian 4.4.2-9' --with-bugurl=file:///usr/share/doc/gcc-4.4/README.Bugs --enable-languages=c,c++,fortran,objc,obj-c++ --prefix=/usr --enable-shared --enable-multiarch --enable-linker-build-id --with-system-zlib --libexecdir=/usr/lib --without-included-gettext --enable-threads=posix --with-gxx-include-dir=/usr/include/c++/4.4 --program-suffix=-4.4 --enable-nls --enable-clocale=gnu --enable-libstdcxx-debug --enable-objc-gc --with-arch-32=i486 --with-tune=generic --enable-checking=release --build=x86_64-linux-gnu --host=x86_64-linux-gnu --target=x86_64-linux-gnu Thread model: posix gcc version 4.4.3 20100108 (prerelease) (Debian 4.4.2-9) Using built-in specs. COLLECT_GCC=/usr/local/gcc-4.5-20100306/bin/g++ COLLECT_LTO_WRAPPER=/usr/local/gcc-4.5-20100306/libexec/gcc/x86_64-unknown-linux-gnu/4.5.0/lto-wrapper Target: x86_64-unknown-linux-gnu Configured with: ../configure --prefix=/usr/local/gcc-4.5-20100306 --enable-languages=c,c++ --enable-threads=posix --with-system-zlib --enable-__cxa_atexit --disable-checking --disable-nls --disable-multilib --enable-bootstrap --with-gcc --with-gnu-as --with-gnu-ld --with-gomp --with-lto Thread model: posix gcc version 4.5.0 20100306 (experimental) (GCC)
In GCC 4.3.x you need optimization enabled for Wuninitialized. In GCC 4.4.1 and GCC 4.5 (trunk) I get warnings in line 6 with -O1 -O2 and -O3. We do not get a warning with -O0 because the default definition appears in a PHI node: <bb 2>: [pr43361.C : 6 : 3] goto <bb 4>; <bb 3>: [pr43361.C : 7:19] std::basic_ostream<char>::operator<< ([pr43361.C : 7] &cout, i_1); [pr43361.C : 8:18] [pr43361.C : 8] array[i_1] = i_1; [pr43361.C : 6:3] i_4 = i_1 + 1; <bb 4>: # i_1 = PHI <i_2(D)(2), [pr43361.C : 6:3] i_4(3)> [pr43361.C : 6:3] D.21125_3 = i_1 <= 9; [pr43361.C : 6:3] if (D.21125_3 != 0) goto <bb 3>; else goto <bb 5>; <bb 5>: [pr43361.C : 0:0] D.21127_5 = 0; return D.21127_5; This can be seen as a natural limitation of the analysis at -O0 or a problem with the way GCC represents loops: for (init; test; next) { for-body }; is transformed to: init: init; goto eval body: for-body; next; goto eval; eval: (test) ? goto body : goto finish; finish: So, although we know what "test" is evaluated at least once after init, GCC doesn't know that with -O0. In any case, there is no trivial fix (but there is a workaround: use optimization).
(In reply to comment #1) > In GCC 4.3.x you need optimization enabled for Wuninitialized. > > In GCC 4.4.1 and GCC 4.5 (trunk) I get warnings in line 6 with -O1 -O2 and -O3. > > We do not get a warning with -O0 because the default definition appears in a > PHI node: > > <bb 2>: > [pr43361.C : 6 : 3] goto <bb 4>; > > <bb 3>: > [pr43361.C : 7:19] std::basic_ostream<char>::operator<< ([pr43361.C : 7] > &cout, i_1); > [pr43361.C : 8:18] [pr43361.C : 8] array[i_1] = i_1; > [pr43361.C : 6:3] i_4 = i_1 + 1; > > <bb 4>: > # i_1 = PHI <i_2(D)(2), [pr43361.C : 6:3] i_4(3)> > [pr43361.C : 6:3] D.21125_3 = i_1 <= 9; > [pr43361.C : 6:3] if (D.21125_3 != 0) > goto <bb 3>; > else > goto <bb 5>; > > <bb 5>: > [pr43361.C : 0:0] D.21127_5 = 0; > return D.21127_5; > > > This can be seen as a natural limitation of the analysis at -O0 or a problem > with the way GCC represents loops: > > for (init; test; next) { for-body }; is transformed to: > > init: > init; > goto eval > body: > for-body; > next; > goto eval; > eval: > (test) ? goto body : goto finish; > finish: > > So, although we know what "test" is evaluated at least once after init, GCC > doesn't know that with -O0. > > In any case, there is no trivial fix (but there is a workaround: use > optimization). The trivial fix would be to compute post-dominator info and check if the edge with the uninitialized use is executed on all paths from function entry to exit (its source and destination post-dominate the entry bb).
(In reply to comment #2) > > The trivial fix would be to compute post-dominator info and check if the > edge with the uninitialized use is executed on all paths from function > entry to exit (its source and destination post-dominate the entry bb). You want to do that at -O0?
(In reply to comment #3) > (In reply to comment #2) > > > > The trivial fix would be to compute post-dominator info and check if the > > edge with the uninitialized use is executed on all paths from function > > entry to exit (its source and destination post-dominate the entry bb). > > You want to do that at -O0? Not really.
Basing on the discussion, I'm closing this as wontfix.
*** Bug 58823 has been marked as a duplicate of this bug. ***
*** Bug 58236 has been marked as a duplicate of this bug. ***
*** Bug 69892 has been marked as a duplicate of this bug. ***
Jakub sketched a possible way to warn about this at -O0: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=69723#c7 Thus, let's reopen it.
*** Bug 84289 has been marked as a duplicate of this bug. ***
(In reply to Manuel López-Ibáñez from comment #9) > Jakub sketched a possible way to warn about this at -O0: > https://gcc.gnu.org/bugzilla/show_bug.cgi?id=69723#c7 > > Thus, let's reopen it. cc-ing him (and a few others)
*** Bug 92118 has been marked as a duplicate of this bug. ***
Not a C++ issue; removing the use of iostreams from the testcase and compiling as C has the same result.
Reconfirmed with GCC 11 and the C test case below: void f (int); int main () { int i; int array[10]; for (; i<10; ++i) { // no warning f (i); // no warning array [i] = i; // no warning, really hurts } }
(In reply to Martin Sebor from comment #14) > Reconfirmed with GCC 11 and the C test case below: > > void f (int); > > int main () { > int i; > int array[10]; > for (; i<10; ++i) { // no warning > f (i); // no warning > array [i] = i; // no warning, really hurts > } > } So what's going "wrong" here is that we figure the BB with the i<10 check post-dominates the entry block and thus is always executed. But when doing warn_uninit on the SSA var we do not consider the value on the always-executed path from entry (which is uninitialized i_3(D)). That's for the early pass, the late pass doesn't run at -O0. Note since we walk BBs in index order which 'i' we warn for is probably random, I think we'll only warn once since we set TREE_NO_WARNING on the underlying decl of the SSA name (that's probably misguided - different SSA defs can have different uninit state). It might be possible to populate possibly_undefined_names in the BB walk by visiting PHIs and considering fallthru entries being taken to have this work out without major restructuring of the pass (a lattice of "undefinedness" would probably be more to the point).
Note GCC 12 now diagnoses this at -O0, reporting the first use: > ../../obj-gcc12-g/gcc/cc1 -quiet t.c -Wall t.c: In function 'main': t.c:5:13: warning: variable 'array' set but not used [-Wunused-but-set-variable] 5 | int array[10]; | ^~~~~ t.c:6:17: warning: 'i' is used uninitialized [-Wuninitialized] 6 | for (; i<10; ++i) { // no warning | ~^~~ t.c:4:13: note: 'i' was declared here 4 | int i; | ^ PR101573 is a "duplicate" we have a testcase for now. *** This bug has been marked as a duplicate of bug 101573 ***