On 2/2/19 1:20 PM, Segher Boessenkool wrote: > On Fri, Feb 01, 2019 at 12:27:57PM -0700, Jeff Law wrote: >> On 2/1/19 7:01 AM, Marek Polacek wrote: >>> On Fri, Feb 01, 2019 at 07:19:25AM -0600, Segher Boessenkool wrote: >>>> On Fri, Feb 01, 2019 at 12:32:45PM +0100, Marc Glisse wrote: >>>>> My opinion is that -Wmaybe-uninitialized would serve its purpose better >>>>> as >>>>> part of -Wextra. >>>> >>>> +1 >>> >>> +1 from me too. >> I disagree strongly. If we move it to Wextra it's going to see a lot >> less usage in real world codebases and potentially lead to the >> re-introduction of a class of bugs that we've largely helped stomp out. > > The usual workaround, especially for programs that build with multiple > (i.e. older) versions of GCC, is to initialise any such variable (to an > either or not useful value) early. This doesn't fix the actual problem > usually (which is that your control flow is too complex). > >> It's also the case that maybe uninitialized vs is uninitialized is >> really just a function of CFG shape. Give me any "maybe uninitialized" >> case and I can turn it into a "is uninitialized" with simple block >> duplication of the forms done by jump threading, path isolation, >> superblock formation, etc. > > Are you saying that -Wmaybe-uninitialized should be included in > -Wuninitialized, since it has no extra false positives? That wasn't true > at all historically: -Wuninitialized has false positives on paths that > cannot be executed because of function preconditions, but > -Wmaybe-uninitialized used to warn for things that can be locally proven to > never execute, like > if (a) > b = 42; > ... > if (a) > f(b); No, I'm saying the distinction between maybe and always uninitialized is a false distinction. Code duplication can easily take something that triggers a "maybe" warning and turn it into a "always" warning. The distinction between them is just bogus.
To take your example if (a) b = 42 ... if (a) f(b); Can be rewritten as if (a) { b = 42 [ copy of ...] f (b); } else { ... f (b); } But more importantly consider when the value flows by way of a PHI argument. We consider those "maybe" warnings (and it's not just the uninitialized warning analysis). But fairly simple code duplication can eliminate the flow via PHI and suddenly we go from a "maybe" to an "always" warning. Let's consider this... x4 = PHI (x0(D), x1, x2, x3) use x4; That's a maybe uninitialized warning by way of the value flow of x0 through the PHI into x4. But we can duplicate the block creating something like this: BB: x5 = PHI (x0(D)) use x5 goto join BB: x4 = PHI (x1, x2, x3) use x4 goto join Which we then simplify into BB: use x0(D) goto join BB: x4 = PHI (x1, x2, x3) use x4 goto join That changes the warning from a maybe-uninitialized into an always uninitialized. Note that we still may or may not reach the use at runtime. THe distinction between maybe and always is just bogus. Jeff