the program below should result in a warning that "j" might be used uninitialized. If the "baz" call is replaced with an explicit assignment to "j" a warning is generated as expected. > gcc-3.4.2 -c -Wall -O2 ~/foo.c (stunning silence) extern int bar (int); extern void baz (int *); int foo (int i) { int j; if (bar (i)) { // These should do the same with respect to `j': baz (&j); // j = 1; } else { } return j; }
Confirmed. It doesn't work on mainline either. The warning machinery is getting confused with the first V_MAY_DEF to j in the first call to 'bar()'. It would probably not be too hard to fix for 4.0. <bb 0>: # j_7 = V_MAY_DEF <j_3>; D.1124_2 = bar (i_1); if (D.1124_2 != 0) goto <L0>; else goto <L1>; <L0>:; # j_8 = V_MAY_DEF <j_7>; baz (&j); # j_6 = PHI <j_7(0), j_8(1)>; <L1>:; # VUSE <j_6>; D.1125_4 = j; return D.1125_4;
*** Bug 23805 has been marked as a duplicate of this bug. ***
(In reply to comment #1) > Confirmed. It doesn't work on mainline either. The warning machinery is > getting confused with the first V_MAY_DEF to j in the first call to 'bar()'. Actually the warning machinery does not work with VOPs at all.
(In reply to comment #3) > (In reply to comment #1) > > Confirmed. It doesn't work on mainline either. The warning machinery is > > getting confused with the first V_MAY_DEF to j in the first call to 'bar()'. > Actually the warning machinery does not work with VOPs at all. I should say see PR 23805 for an example of that. Also the extra V_MAY_DEF is coming from that fact the clobber list is not flow sensitive, see PR 23384 for that bug.
Simplifying things a bit: void foo(int*); void bar(void) { int x; if(x) foo(&x); } gcc -c foo.c -Wall -O2 -Wuninitialized (More stunning silence.)
*** Bug 23844 has been marked as a duplicate of this bug. ***
An even simpler test case of this bug (tested with gcc 3.4.5): int main( void ) { int rc; return rc; *&rc = 0; } > gcc -O -Wall program.c (more stunning silence) NOTE: in this example, there is no function invocation inside main(). NOTE: remove the last statement in the program, and the warning will show up. g.
(In reply to comment #7) > An even simpler test case of this bug (tested with gcc 3.4.5): That works correctly in 4.0.0 and above.
Not going to work on this problem any time soon.
Can I bribe you to work on it by fixing a Wine bug in exchange? :)
*** Bug 29227 has been marked as a duplicate of this bug. ***
Here's my minimal test case. Compile with "-O3 -Wall -c": #include <stdio.h> void frob(int *pi); int main(void) { int i; printf("i = %d\n", i); frob(&i); return 0; } No warning from 4.0.3 nor 4.1.2....
*** Bug 31284 has been marked as a duplicate of this bug. ***
Trying to improve the summary to help spot duplicates.
This seems to me a duplicate of PR179. I am going to add a dependency to remember to check this PR when PR179 gets fixed.
All testcases except the one in the original description were actually duplicates of PR179 and are thusly fixed. The original testcase deals with PHI ops which is a completely different beast. I added it XFAILED as gcc.dg/uninit-pr19430.c but I doubt it will get magically fixed, so suggestions/patches welcome.
*** Bug 42079 has been marked as a duplicate of this bug. ***
This seems to be fixed in the trunk.
(In reply to Vincent Lefèvre from comment #18) > This seems to be fixed in the trunk. Is there an XPASS for gcc.dg/uninit-pr19430.c ? Also, the testcase from bug 42079?
(In reply to Manuel López-Ibáñez from comment #19) > (In reply to Vincent Lefèvre from comment #18) > > This seems to be fixed in the trunk. > > Is there an XPASS for gcc.dg/uninit-pr19430.c ? > > Also, the testcase from bug 42079? Clang warns for this in the FE without any optimization: gcc.dg/uninit-pr19430.c:10:7: warning: variable 'j' is used uninitialized whenever 'if' condition is false [-Wsometimes-uninitialized] if (bar (i)) { ^~~~~~~ gcc.dg/uninit-pr19430.c:15:10: note: uninitialized use occurs here return j; ^ gcc.dg/uninit-pr19430.c:10:3: note: remove the 'if' if its condition is always true if (bar (i)) { ^~~~~~~~~~~~~ gcc.dg/uninit-pr19430.c:8:8: note: initialize the variable 'j' to silence this warning int j; /* { dg-warning "'j' may be used uninitialized in this function" "uninitialized" { xfail *-*-* } 8 } */ ^ = 0
$ ~/test1/205036M/build/gcc/cc1 -O1 -Wuninitialized test.c -fdump-tree-all-all-lineno $ cat test.c.139t.uninit1 foo (intD.6 iD.1789) { intD.6 jD.1792; intD.6 _5; intD.6 _7; ;; basic block 2, loop depth 0, count 0, freq 10000, maybe hot ;; prev block 0, next block 5, flags: (NEW, REACHABLE) ;; pred: ENTRY [100.0%] (FALLTHRU,EXECUTABLE) ;; starting at line 10 [test.c : 10:11] # .MEM_4 = VDEF <.MEM_2(D)> # USE = nonlocal { D.1792 } (escaped) # CLB = nonlocal { D.1792 } (escaped) _5 = barD.1786 (i_3(D)); [test.c : 10:6] if (_5 != 0) goto <bb 3>; else goto <bb 5>; ;; succ: 3 [39.0%] (TRUE_VALUE,EXECUTABLE) ;; 5 [61.0%] (FALSE_VALUE,EXECUTABLE) ;; basic block 5, loop depth 0, count 0, freq 6102, maybe hot ;; prev block 2, next block 3, flags: (NEW) ;; pred: 2 [61.0%] (FALSE_VALUE,EXECUTABLE) ;; goto <bb 4>; ;; succ: 4 [100.0%] (FALLTHRU) ;; basic block 3, loop depth 0, count 0, freq 3898, maybe hot ;; prev block 5, next block 4, flags: (NEW, REACHABLE) ;; pred: 2 [39.0%] (TRUE_VALUE,EXECUTABLE) ;; starting at line 11 [test.c : 11:9] # .MEM_6 = VDEF <.MEM_4> # USE = nonlocal { D.1792 } (escaped) # CLB = nonlocal { D.1792 } (escaped) bazD.1788 ([test.c : 11] &jD.1792); ;; succ: 4 [100.0%] (FALLTHRU,EXECUTABLE) ;; basic block 4, loop depth 0, count 0, freq 10000, maybe hot ;; prev block 3, next block 1, flags: (NEW, REACHABLE) ;; pred: 5 [100.0%] (FALLTHRU) ;; 3 [100.0%] (FALLTHRU,EXECUTABLE) ;; starting at line 14 # .MEM_1 = PHI <.MEM_4(5), .MEM_6(3)> [test.c : 14:3] # VUSE <.MEM_1> _7 = jD.1792; # .MEM_8 = VDEF <.MEM_1> jD.1792 ={v} {CLOBBER}; [test.c : 14:3] # VUSE <.MEM_8> return _7; ;; succ: EXIT [100.0%] } It seems one could follow every operand of the MEM_1 PHI node until you find the MEM_4 = VDEF <.MEM_2(D)>. But perhaps this may produce a lot of false positives. The uninit pass avoids virtual operands on purpose, so it cannot be that trivial.
(In reply to Manuel López-Ibáñez from comment #19) > (In reply to Vincent Lefèvre from comment #18) > > This seems to be fixed in the trunk. > > Is there an XPASS for gcc.dg/uninit-pr19430.c ? Actually, with trunk revision 203899, only the last 3 tests now get the warning (those corresponding to -Wuninitialized). The first one (which should be a "may be uninitialized") is still silent.
BTW, I suppose that in this test, -Wuninitialized should be changed to "-Wuninitialized -Wmaybe-uninitialized" in case it is decided later that -Wuninitialized no longer enables -Wmaybe-uninitialized (see PR59223 about that).
Well, fact is we still don't have the machinery that warns for the use of uninitialized memory - and we never had. The cases that work by accident are for loads that alias-analysis can prove we can move to the function entry (well, a little less than that).
(In reply to Vincent Lefèvre from comment #23) > BTW, I suppose that in this test, -Wuninitialized should be changed to > "-Wuninitialized -Wmaybe-uninitialized" in case it is decided later that > -Wuninitialized no longer enables -Wmaybe-uninitialized (see PR59223 about > that). I don't see any reason for -Wuninitialized to not enable -Wmaybe-uninitialized.
(In reply to Manuel López-Ibáñez from comment #25) > I don't see any reason for -Wuninitialized to not enable > -Wmaybe-uninitialized. I can see 3 kinds of use: 1. Users who are interested in neither: they just don't use these options (if they want to use -Wall, they need the -Wno- version). 2. Users interested in -Wuninitialized but not in -Wmaybe-uninitialized (to avoid potential many false positives). Because -Wuninitialized enables -Wmaybe-uninitialized, they need 2 options: -Wuninitialized -Wno-maybe-uninitialized. If -Wuninitialized did not enable -Wmaybe-uninitialized, only one option would be needed: -Wuninitialized. 3. Users interested in both. I think that -Wmaybe-uninitialized should enable -Wuninitialized because it makes no sense to have -Wmaybe-uninitialized but not -Wuninitialized. Indeed, if some variable is uninitialized, then it may be uninitialized. So, only one option should be needed in this case: -Wmaybe-uninitialized.
(In reply to Vincent Lefèvre from comment #26) > (In reply to Manuel López-Ibáñez from comment #25) > > I don't see any reason for -Wuninitialized to not enable > > -Wmaybe-uninitialized. > > I can see 3 kinds of use: > > 1. Users who are interested in neither: they just don't use these options > (if they want to use -Wall, they need the -Wno- version). -Wall -Wno-uninitialized suppresses both. > 2. Users interested in -Wuninitialized but not in -Wmaybe-uninitialized (to > avoid potential many false positives). Because -Wuninitialized enables > -Wmaybe-uninitialized, they need 2 options: -Wuninitialized > -Wno-maybe-uninitialized. If -Wuninitialized did not enable > -Wmaybe-uninitialized, only one option would be needed: -Wuninitialized. This argument goes both ways: if you are interested in both warnings, you would need both options. > 3. Users interested in both. I think that -Wmaybe-uninitialized should > enable -Wuninitialized because it makes no sense to have > -Wmaybe-uninitialized but not -Wuninitialized. Indeed, if some variable is > uninitialized, then it may be uninitialized. So, only one option should be > needed in this case: -Wmaybe-uninitialized. Aha! This is a really good point on which I can agree. However, it will seriously break backwards compatibility for people that use either -Wuninitialized or -Wno-uninitialized explicitly. I am not sure if the pain is worth the beauty. I don't think it is worth to discuss this in Bugzilla (specially not on this PR). If you are convinced that this is the right thing to do, you could propose a patch to gcc-patches and see how people receive it.
*** Bug 65182 has been marked as a duplicate of this bug. ***
What remains seems to be complaining that int i; foo (&i); doesn't warn. And we have another bug that int i; foo (&i); ... = i; doesn't warn for the read from i. I think both of these need a different warning level as foo may not read from i and foo may initialize i.
(In reply to Richard Biener from comment #29) > What remains seems to be complaining that > > int i; > foo (&i); > > doesn't warn. And we have another bug that > > int i; > foo (&i); > ... = i; > > doesn't warn for the read from i. > > I think both of these need a different warning level as foo may not read > from i and foo may initialize i. This is not what this bug is about. Please read the discussions. It seems a waste of people's goodwill and effort over the years to close bugs as invalid/duplicates without understanding why they were open in the first place. This bug is about (comment #0) extern int bar (int); extern void baz (int *); int foo (int i) { int j; if (bar (i)) { // These should do the same with respect to `j': baz (&j); // j = 1; } return j; } If bar(i) returns false, j is never initialized. The bug implicitly assumes that baz(&j) does initialize j, thus it satisfies the heuristic used in GCC and still there should be a "may be" warning.
There's something I don't understand: Whether -Wuninitialized or -Wmaybe-uninitialized is used, I don't see any difference in the behavior of GCC between [...] if (bar (i)) { baz (&j); } [...] and [...] if (bar (i)) { j = 1; } [...] In any case, no warnings are generated. So, the problem here is not related to whether the address of j is taken, but to something else.
(In reply to Vincent Lefèvre from comment #31) > In any case, no warnings are generated. So, the problem here is not related > to whether the address of j is taken, but to something else. With a constant, you hit PR18501. If you use "j = i", it warns as it should.
*** Bug 82839 has been marked as a duplicate of this bug. ***
*** Bug 54544 has been marked as a duplicate of this bug. ***
GCC 11 issues a warning when the address of an uninitialized variable is passed to a function that takes a const pointer but it (still) doesn't warn when the address escapes. In both cases, it's possible for the called function to store a value into the variable but because it's highly unlikely issuing a warning regardless would be appropriate. In addition, in cases where the address of the variable doesn't escape until after the function call its value cannot be affected even when the address is assigned to a non-const pointer. The escape analysis is flow insensitive so it alone cannot be relied on to make the distinction. But modifying variables this way is rare so issuing the warning regardless is likely worthwhile. $ cat a.c && gcc -O2 -S -Wall a.c extern void f (const void*); int g (void) { int i; f (&i); // -Wmaybe-uninitialized return i; } int h (void) { extern const void *p; int i; f (0); p = &i; return i; // missing -Wmaybe-uninitialized } a.c: In function ‘int g()’: a.c:6:5: warning: ‘i’ may be used uninitialized [-Wmaybe-uninitialized] 6 | f (&i); | ~~^~~~ a.c:1:13: note: by argument 1 of type ‘const void*’ to ‘void f(const void*)’ declared here 1 | extern void f (const void*); | ^ a.c:5:7: note: ‘i’ declared here 5 | int i; | ^
*** Bug 78370 has been marked as a duplicate of this bug. ***
Re-confirmed for the original testcase. The issue is that while we now try to perform uninitialized diagnostics for memory we do not perform the maybe-uninit analysis via PHIs we do for non-memory. We see <bb 2> [local count: 1073741824]: # .MEM_5 = VDEF <.MEM_3(D)> _1 = bar (i_4(D)); if (_1 != 0) goto <bb 3>; [33.00%] else goto <bb 5>; [67.00%] <bb 5> [local count: 719407024]: goto <bb 4>; [100.00%] <bb 3> [local count: 354334800]: # .MEM_6 = VDEF <.MEM_5> baz (&j); <bb 4> [local count: 1073741824]: # .MEM_2 = PHI <.MEM_5(5), .MEM_6(3)> # VUSE <.MEM_2> _7 = j; so when we are walking and looking for defs of 'j' by means of walk_aliased_vdefs but that will simply process MEM_6 "unordered" and record that as possible definition. We are not properly forking the walk to discover a path where 'j' is not initialized nor are we trying to compute predicates which guard the use.
*** Bug 34721 has been marked as a duplicate of this bug. ***