[Bug middle-end/60488] missing uninitialized warning (address taken, VOP)
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=60488 Martin Sebor changed: What|Removed |Added CC||matthew at wil dot cx --- Comment #10 from Martin Sebor --- *** Bug 88518 has been marked as a duplicate of this bug. ***
[Bug middle-end/60488] missing uninitialized warning (address taken, VOP)
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=60488 --- Comment #9 from Manuel López-Ibáñez --- (In reply to Martin Sebor from comment #8) > You're right, the test cases aren't equivalent, or meant to be. What I want > to highlight is that in the test case in comment #6, in g() and other > similar ones like it the warning is most likely going to be a false > positive, while in h(), not warning most likely a false negative. Both of > these "problems" are due to the same underlying assumption: that a variable > whose address escapes may be modified by a subsequent call to an unknown > function. Sure, but that assumption is not the problem in this PR, since assuming one thing or the other only matters for distinguishing between "is" and "may be", but a warning should have been given and it is not given.
[Bug middle-end/60488] missing uninitialized warning (address taken, VOP)
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=60488 --- Comment #8 from Martin Sebor --- You're right, the test cases aren't equivalent, or meant to be. What I want to highlight is that in the test case in comment #6, in g() and other similar ones like it the warning is most likely going to be a false positive, while in h(), not warning most likely a false negative. Both of these "problems" are due to the same underlying assumption: that a variable whose address escapes may be modified by a subsequent call to an unknown function. The upshot is that the warning (indeed, all flow-based warnings) should consider not just what can be proven might happen based on the IL but also the likelihood with which it might happen. I'm not saying there's a coding bug in the implementation of the warning, rather that the heuristics it implements aren't sufficient to capture this distinction.
[Bug middle-end/60488] missing uninitialized warning (address taken, VOP)
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=60488 --- Comment #7 from Manuel López-Ibáñez --- (In reply to Martin Sebor from comment #6) > The problem is that when the address of a variable escapes, because GCC > doesn't track when, when the function from which it escapes calls another > that might access the escaped variable, the warning (as a result of relying > on the conservative assumptions the optimizers must make) assumes the called > function initializes the variable. Another example of this is function h() > below. I don't think these are equivalent testcases. It is OK to assume that the invisible function initializes the variable. The problem arises when there is a path that never calls the function but GCC does not see that. The key here is the logical operator splits the possible paths in two. In one of the paths, b (comment #5) is never initialized, no matter what you assume about f(). It also happens with a simple if(): int f (int*); int g(void); int foo (void) { int b; if (g()) { f(); } return b; } However, a similar construct without works: int g(void); int foo (void) { int b; if (g()) { b = g(); } return b; } If you look at the VOPs, there is a chain that goes from the VUSE of b to the VDEF<(D)> through at least one PHI node. The "return 0" is problematic because CPP (PR18501) will trigger and mess up things even more. But the above testcases avoid PR18501 and still show this bug.
[Bug middle-end/60488] missing uninitialized warning (address taken, VOP)
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=60488 Martin Sebor changed: What|Removed |Added Last reconfirmed|2016-08-23 00:00:00 |2021-3-26 Known to fail|7.0 |11.0 --- Comment #6 from Martin Sebor --- Reconfirming with GCC 11. The problem is that when the address of a variable escapes, because GCC doesn't track when, when the function from which it escapes calls another that might access the escaped variable, the warning (as a result of relying on the conservative assumptions the optimizers must make) assumes the called function initializes the variable. Another example of this is function h() below. The irony (and I'd say the bug) here is that the warning uses the same conservative assumptions to trigger in cases when an equivalent same situation might lead to the variable not having been initialized such as in g() below. These conflicting assumptions make the warning seem unpredictable. $ cat z.c && gcc -O2 -S -Wall z.c void f (void); int i, *p; int g (int j) { int x; if (i) // assume i is zero x = j + 1; f ();// assume call sets i if (i) return x; // issue -Wmaybe-uninitalized return i; } int h (int j) { int x; p = // address of x escapes f ();// assume call sets x return x;// avoid warning here } z.c: In function ‘g’: z.c:14:12: warning: ‘x’ may be used uninitialized in this function [-Wmaybe-uninitialized] 14 | return x; // issue -Wmaybe-uninitalized |^ z.c:7:7: note: ‘x’ was declared here 7 | int x; | ^
[Bug middle-end/60488] missing uninitialized warning (address taken, VOP)
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=60488 --- Comment #5 from Manuel López-Ibáñez --- Even simpler: int f (int*); int g(void); int foo (void) { int b; if (g() && f ()) return 0; return b; } we have: # .MEM_7 = VDEF <.MEM_6(D)> # USE = nonlocal null { D.1912 } (escaped) # CLB = nonlocal null { D.1912 } (escaped) _1 = gD.1908 (); if (_1 != 0) goto ; [33.00%] else goto ; [67.00%] ;; basic block 6, loop depth 0, count 719407024 (estimated locally), maybe hot # .MEM_11 = PHI <.MEM_7(6), .MEM_8(8)> # DEBUG BEGIN_STMT # VUSE <.MEM_11> _9 = bD.1912; but uninit pass does not follow the PHI chain for memory ops.
[Bug middle-end/60488] missing uninitialized warning (address taken, VOP)
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=60488 Martin Sebor changed: What|Removed |Added Keywords||diagnostic Known to fail||4.8.3, 4.9.3, 5.3.0, 6.2.0, ||7.0 --- Comment #4 from Martin Sebor --- You're right that the goto isn't essential here. The same problem can be demonstrated in the simplified test case below. When f() && f() evaluates to true (and assuming f() initializes what it points to) there "exists a path from the function entry to a use of the variable that is initialized." But f() evaluates to false f() is not called then "there exists a path for which b is not initialized." Since there is no way to prove that the second path is not taken at runtime then, according to the documentation, GCC should emit a warning. However, no warning is issued. int f (int*); int foo (void) { int a, b; if (f () && f ()) return 0; return a + b; }
[Bug middle-end/60488] missing uninitialized warning (address taken, VOP)
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=60488 Manuel López-Ibáñez changed: What|Removed |Added Status|UNCONFIRMED |NEW Last reconfirmed||2016-08-23 Blocks||24639 Summary|missing |missing uninitialized |-Wmaybe-uninitialized on a |warning (address taken, |conditional with goto |VOP) Ever confirmed|0 |1 --- Comment #3 from Manuel López-Ibáñez --- I don't think the goto has anything to do with it, but there are several bugs about taking the address of a variable breaking any obvious uninitialized warnings. Referenced Bugs: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=24639 [Bug 24639] [meta-bug] bug to track all Wuninitialized issues