On 2/4/19, Martin Sebor <mse...@gmail.com> wrote:
>>> In practice, false positives (and negatives) of both kinds, whether
>>> they fit the formal definition or the informal one, are the nature
>>> of virtually all non-trivial static diagnostics, certainly all those
>>> that depend on control or data flow analysis.  Some are due to bugs
>>> or limitations in the implementation of the warning.  Others are
>>> inherent in the technology.
>>
>> Yes, and I argue that these warnings belong in a different "level" of
>> warnings than the trivial warnings.
>
> Introducing more levels sounds fine to me.  I wouldn't want to see
> a more permissive default; my preference would be the opposite,
> leaving it to projects to adjust.

For reference, besides -Wuninitialized and -Wmaybe-uninitialized,
clang also has its uninitialized warnings split further into
-Wsometimes-uninitialized and -Wconditional-uninitialized.
-Wsometimes-uninitialized relies on the integration of their static
analyzer into their FE and gets stuff that gcc puts under
-Wjump-misses-init and -Wswitch-unreachable instead.
-Wconditional-uninitialized is their super-aggressive variant and
warns about just about everything. It intentionally includes false
positives as described in the comments on this bug:
https://bugs.llvm.org/show_bug.cgi?id=38856
If gcc wants to introduce more levels to -Wuninitialized, I'd start by
considering the additional flags clang supports.

>
>>
>>> Lastly, in the case of uninitialized variables, the usual solution
>>> of initializing them is trivial and always safe (some coding styles
>>> even require it).
>>
>> Here it shows that we don't work with the same type of code at all. If I
>> am using a boost::optional, i.e. a class with a buffer and a boolean
>> that says if the buffer is initialized, how do I initialize the
>> (private) buffer? Or should boost itself zero out the buffer whenever
>> the boolean is set to false? The variables can easily be hidden behind
>> dozens of levels of abstraction that make them hard to initialize, and
>> there may be nothing meaningful to initialize them with. Uninitialized
>> also includes clobbered (out-of-scope for instance) in gcc, where it
>> isn't clear what you are supposed to initialize to quiet the warning.
>
> You're right that this is hard to imagine without first hand experience
> with the problem.  If this is a common pattern with the warning in C++
> class templates in general, a representative test case would help get
> a better appreciation of the problem and might also give us an idea
> of a better solution.  (If there is one in Bugzilla please point me
> at it.)
>
>>>> This message concentrates on the negatives, but that doesn't mean I
>>>> consider -Wmaybe-uninitialized as useless. It can find true
>>>> uninitialized uses. And even some false positives can point at places
>>>> where we can help the compiler generate better code (say with a
>>>> default __builtin_unreachable case in a switch). I did in the past
>>>> contribute patches to make it warn more often, and I might do so
>>>> again in the future.
>>>
>>> This paragraph makes me think you equate false positives from this
>>> warning with those from -Wuninitialized.
>>
>> Uh? No, I don't know what gave you this impression.
>
> It's common to view as a false positive (or "bad" as you write below)
> every instance of a warning designed to detect or prevent bugs that
> doesn't indicate one (as opposed to warnings designed to help write
> better/clearer code like -Wparentheses).
>
>>> "May be unitialized" doesn't preclude the possibility that the
>>> variable is not used uninitialized.
>>
>> But if the variable can never be used uninitialized and gcc is simply
>> unable to prove it, the warning is bad. It may not be a "false positive"
>> depending on your definition, but it is undesirable.
>
> Ideally each instance of every warning designed to find bugs would
> point out one.  But 100% accuracy or a zero rate of the undesirable
> instances is not attainable in general, and reducing their rate at
> the expense of the helpful ones also isn't the best tradeoff either.
> The challenge is striking the right balance between their ratios.
> (Only if that can't done then it might be time to consider
> disabling/demoting the warning.  I don't have the impression
> we are at that point with -Wmaybe-uninitialized but I haven't
> done any research.)
>
>>>> My opinion is that -Wmaybe-uninitialized would serve its purpose
>>>> better as part of -Wextra. People tend to use -Wall with -Werror
>>>> (either explicitly or implicitly by modifying the code until all
>>>> warnings are gone). What I see currently in projects where I
>>>> participate is that -Wmaybe-uninitialized is making things worse.
>>>> People don't investigate deeply the cause of the warning, they just
>>>> go for whatever "quick-fix" makes the compiler shut up. Quite often,
>>>> this involves extra code that is less readable and performs worse,
>>>> while it didn't even "fix" what caused the warning, it just randomly
>>>> ended up with code where the compiler doesn't warn (possibly because
>>>> the function got bigger, which changed inlining decisions...).
>>>
>>> I agree that we need to be mindful of warnings leading to unnecessary
>>> and perhaps inappropriate code changes (as the author of a few warnings
>>> with this potential it has been on mind a lot).
>>>
>>> At the same time, not taking the time to properly analyze diagnostics
>>> and come up with the appropriate solutions seems like a problem that's
>>> orthogonal to the warnings themselves.  Disabling warnings in hopes of
>>> solving what's really a problem with the development process or
>>> a culture of a subset of projects doesn't seem like an optimal solution.
>>
>> I agree with that. But if I complain about the mindless quickfixes, the
>> reply is that customers ask for a library that does not warn, and the
>> developers do not have infinite time, so they do the minimum to avoid
>> warnings. This is strongly linked to the warning levels.
>>
>> One could recommend that customers include the library with -isystem to
>> disable the warnings inside the library, bug that's fragile (though it
>> has gotten quite good), and most importantly it also disables some
>> warnings that are relevant to the user.
>
> Right, that wouldn't be much better than disabling the warning on
> the command line (or us removing it from -Wall and perhaps also
> from -Wextra).
>
> So since mindless quick fixes aren't the way to go and assuming we
> agree that warnings have value even with some noise, is demoting
> them to lower levels because they're not always used properly
> the best solution?  No predetermined system of warning levels is
> going to make everyone happy.  Different projects have different
> constraints and tolerances for noise, or even resources to fix
> real bugs -- GCC with over 400 wrong-code bugs in Open status
> being a case in point, so a level that works for one, like
> a library, may be overly pedantic for an application.
>
> More warning levels might help.  Warning profiles (say one for
> system libraries or freestanding code like the kernel, another
> for C++ class libraries, yet another for applications) might
> be another approach.  Others might be worth brainstorming about.
>
>>>> If the warning is not enabled by default so much but only when people
>>>> are ready to investigate any warning thoroughly, the quickfix
>>>> mentality is less likely to be present. People using
>>>> -Wmaybe-uninitialized need to be willing to ignore false positives,
>>>> or disable them with pragmas.
>>>>
>>>> Note that similar arguments may apply to some other warnings that
>>>> somehow made their way into -Wall when they shouldn't have, but for
>>>> now I am only proposing to move -Wmaybe-uninitialized. Some people
>>>> tend to consider that if a warning is not part of -Wall, it might as
>>>> well not exist. Obviously I disagree with that.
>>>
>>> The description of -Wall is vague enough that arguments about which
>>> warnings should or shouldn't be enabled by it are unavoidably subject
>>> to individual biases and unlikely to lead to a consensus, either among
>>> ourselves or, even less likely, among users.
>>
>> True. To me, one of the key documented properties of -Wall is being
>> "easy to avoid". -Wall -Werror should be a usable combination. Anything
>> not easy to avoid belongs in a different class, say -Wextra. We can
>> rename that to W1/W2/... if Wall is too charged with historical meaning.
>
> I would have expected dealing with -Wmaybe-uninitialized to always
> be easy.  Your comment about std::optional suggests there are cases
> when it isn't.  Can we look at some of those cases and see if there
> is something we can do to make it easier?
>
>>> A shared definition of a false positive should be one of the very
>>> first steps to coming closer to a consensus.  Real world (as opposed
>>> to anecdotal) data on the rates of actual rates of false positives and
>>> negatives vs true positives would be also most helpful, as would some
>>> consensus of the severity of the bugs the true positives expose, as
>>> well as some objective measure of the ease of suppression.  There
>>> probably are others but these would be a start.
>>
>> This data is going to be super hard to get. Most projects have been
>> compiling for years and tweaking their code to avoid some warnings. We
>> do not get to see the code that people originally write, we can only see
>> what they commit.
>
> It's not perfect but we should be able to get a rough idea based
> on bug reports in Bugzilla.  Many distros rebuild the world before
> a GCC release and new instances of build-breaking warnings tend to
> get filed there.  Meta-bugs can be helpful as the first step.
> A finer-grained classification by search terms (e.g., "bogus"
> "spurious", etc.) helps narrow it down even more.
>
> Martin
>

Reply via email to