The warning below is inappropriate since j can never be used in the function. $ cat t.cpp && gcc -c -O -W t.cpp int foo () { int i; int j; for ( ; ; ) { i = 0; if (0 == i) break; } if (1 == i) return j; return 0; } t.cpp: In function `int foo()': t.cpp:4: warning: 'j' might be used uninitialized in this function
I think we had decided even though the code is unreachable, we want to warn about this.
I can imagine that it may not be straightforward to fix but I can't think of a reason why a warning could ever be useful in this case (i.e., when the code is provably safe). I could of course be missing something -- could you point me to the discussion where this was decided? Thanks!
(In reply to comment #2) > I can imagine that it may not be straightforward to fix but I can't think of a > reason why a warning could ever be useful in this case (i.e., when the code is > provably safe). I could of course be missing something -- could you point me to > the discussion where this was decided? Thanks! Actually in 4.0.0 and above, it is an easy fix, just moving around the order around of the passes.
I think I'd appreciate that warning when writing portable code: The warning can be useful if the 1 is replaced with a macro which may or may not expand to 1, or an enum defined in an #ifdef, or an implementation-dependent expression like ((char)-1 < 0). But of course, it depends on how many false positives the warning tends to give for normal programs. Maybe there could be a warning option to turn on and off some warnings that do not apply with the particular #defines and constants being used. (And also turn on/off -Wunreachable for this case.)
Bogus warning no longer issued with GCC 4.1 based compilers.
(In reply to comment #5) > Bogus warning no longer issued with GCC 4.1 based compilers. Huh: gcc version 4.1.0 20051106 (experimental) ../t6.c: In function ‘foo’: ../t6.c:13: warning: ‘j’ is used uninitialized in this function
Even simpler testcase: int foo () { int i = 0; int j; if (1 == i) return j; return 0; } This will only be reliably fixed by building a better SSA representation. Moving the passes around will just solve it by chance (because CCP will assume that j undefined value is actually 0, and thus remove j). Also, it will silence many warnings (for the same reason, CCP happily initializing uninitialized variables) So instead of: foo () { int j; int i; int D.1280; <bb 0>: [pr20644.c : 3] i_2 = 0; [pr20644.c : 6] if ([pr20644.c : 6] i_2 == 1) goto <L0>; else goto <L1>; <L0>:; [pr20644.c : 7] D.1280_6 = j_5; [pr20644.c : 7] goto <bb 3> (<L2>); <L1>:; [pr20644.c : 9] D.1280_4 = 0; # D.1280_1 = PHI <D.1280_6(1), D.1280_4(2)>; <L2>:; return D.1280_1; } We could generate: foo () { int j; int i; <bb 0>: [pr20644.c : 3] i_2 = 0; [pr20644.c : 6] if ([pr20644.c : 6] i_2 == 1) goto <L0>; else goto <L1>; <L0>:; [pr20644.c : 7] goto <bb 3> (<L2>); <L1>:; [pr20644.c : 9] j_6 = 0; # j_7 = PHI <j_5(D), j_6(2)>; <L2>:; return j_7; }
(In reply to comment #6) > (In reply to comment #5) > gcc version 4.1.0 20051106 (experimental) > ../t6.c: In function ‘foo’: > ../t6.c:13: warning: ‘j’ is used uninitialized in this function > Despite what I said before, for this particular case, we should never give a "is used" warning if the BB is not executed with 100% probability. Hmm, I'll check whether we can detect this.
(In reply to comment #8) > Despite what I said before, for this particular case, we should never give a > "is used" warning if the BB is not executed with 100% probability. Hmm, I'll > check whether we can detect this. We could avoid the warning by doing the following: --- gcc/tree-ssa.c (revision 126606) +++ gcc/tree-ssa.c (working copy) @@ -1302,8 +1334,11 @@ } } static unsigned int execute_early_warn_uninitialized (void) { block_stmt_iterator bsi; basic_block bb; FOR_EACH_BB (bb) - for (bsi = bsi_start (bb); !bsi_end_p (bsi); bsi_next (&bsi)) - { - tree context = bsi_stmt (bsi); - walk_tree (bsi_stmt_ptr (bsi), warn_uninitialized_var, - context, NULL); - } + { + edge e; + edge_iterator ei; + FOR_EACH_EDGE (e, ei, bb->preds) + if (e->flags & EDGE_FALLTHRU) + { + for (bsi = bsi_start (bb); !bsi_end_p (bsi); bsi_next (&bsi)) + { + tree context = bsi_stmt (bsi); + walk_tree (bsi_stmt_ptr (bsi), warn_uninitialized_var, + context, NULL); + } + break; + } + } I think this is the "Right Thing To Do". Otherwise, we are giving "is used" warnings for BBs that are conditionally executed. On the other hand, we will miss a few of the correct warnings that we get by chance by not doing the "Right Thing". Comments?
Subject: Bug 20644 Author: manu Date: Sun Aug 10 18:46:10 2008 New Revision: 138933 URL: http://gcc.gnu.org/viewcvs?root=gcc&view=rev&rev=138933 Log: 2008-08-10 Manuel Lopez-Ibanez <manu@gcc.gnu.org> PR middle-end/20644 * tree-ssa.c (struct walk_data): Add new flag warn_possibly_uninitialized. (warn_uninitialized_var): Use it. (warn_uninitialized_vars): New. (execute_early_warn_uninitialized): Call it. (execute_late_warn_uninitialized): Likewise. testsuite/ * gcc.dg/uninit-pr20644-O0.c: New. * gcc.dg/uninit-pr20644.c: New. Added: trunk/gcc/testsuite/gcc.dg/uninit-pr20644-O0.c trunk/gcc/testsuite/gcc.dg/uninit-pr20644.c Modified: trunk/gcc/ChangeLog trunk/gcc/testsuite/ChangeLog trunk/gcc/tree-ssa.c
This is FIXED in GCC 4.4. This may have fixed other uninitialized PRs, so if you have reported one, please recheck with the a recent 4.4 revision