On 2/1/19 1:31 PM, Marc Glisse wrote:
> 
> I am not surprised, but I had to at least start the conversation. Would
> you mind providing a patch that changes the definition of -Wall, since
> the current one doesn't quite match reality anymore? Also, what do you
> recommend people do when they hit false positives?
So I'm not sure how I'd change the definition of -Wall.

> 
>> If we move it to Wextra it's going to see a lot less usage in real
>> world codebases
> 
> I am very tempted by the strawman: should we deprecate -Wextra since
> nobody uses it? (Sorry)
:-)  I don't see a lot of use of -Wextra and I'm always disappointed
when we have to relegate useful warnings to it precisely because it gets
used so rarely.

But as I've indicated earlier on this thread, it may make sense to split
out uninitialized warnings on aggregates/addressables and relegate those
to -Wextra until we can really beef up analysis in that space.



> 
> Ideally serious projects would use (parts of) -Wextra, at least
> occasionally, and with circumspection. But some warnings like
> -Wmaybe-uninitialized are dangerous tools in the hands of quickfix
> developers, and I am indeed trying to keep it out of their hands...
Well, that's a different problem.  If the developers are doing quick,
dumb hacks to avoid a warning, then the developers need to be retrained.
 We shouldn't cater the warning set to make that class of developer
happy or less dangerous.

> 
>> and potentially lead to the re-introduction of a class of bugs that
>> we've largely helped stomp out.
> 
> That's very optimistic. -Wmaybe-uninitialized only detects a very small
> proportion of uninitialized uses. Also, my experience is that people
> have stomped out the warning, not the bugs. In some cases they even
> introduced bugs to stomp out false warnings, or made it harder to detect
> real bugs in the future, so the warning did more harm than good. I am
> mostly working on large C++ header-only template-heavy scientific
> libraries, it is quite possible that people who handle different types
> of code bases have a different experience, and -Wmaybe-uninitialized may
> have had a more positive impact on other projects.
I see things differently.  Specifically we've done a good job at making
the analysis good for simple objects (anything that's an SSA_NAME).
False positives happen, but are relatively rare and developers have
through the decades addressed most of these problems (we've had this
stuff in -Wall for 3 decades).

Are there cases where developers have screwed things up in the process,
certainly, but I suspect that's the exception rather than the rule.

The simple fact is that if we throw an uninitialized warning on a scalar
you *really* have to look at the code to figure out if it's a false
positive or not.  And you have to really think hard about how to
initialize the value if that's in fact what you end up doing -- there's
no guaranteed safe value and that's why I've resisted calls to have
"initialize everything to XXX" flags through the years.

On the addressable/aggregate side things are totally different.  We miss
tons of warnings, our ability to analyze things to avoid false positives
is poor at best, etc.


> 
>> 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.
> 
> Hmm, you know those things better than me, so you are probably right,
> but I am not seeing it. We omit "maybe" if, starting from the entry of
> the function, and barring exceptions, we know the statement will always
> be executed. If you take a false positive for maybe-uninitialized, i.e.
> a statement in a dead branch, I don't see how block duplication can make
> it so the statement is now always executed. The natural way to remove
> "maybe" is through function cloning or outlining. Then you can create
> functions that are never called, and any warning about those is a false
> positive.
Well, that's the problem.  Right now the maybe vs always is based on if
the value flows through a PHI.   But I can avoid having the value flow
through a PHI with simple block copying and light CFG manipulation.  But
in both cases there's still a control dependency path to get to the
point where the uninitialized use happens.  And you also have the issue
of proving that a particular function even executes to begin with.

That's why I think the distinction simply doesn't make any sense.  We
should just call them all maybe-uninitialized uses.

Jeff

Reply via email to