This is the mail archive of the
mailing list for the GCC project.
Re: -Wuninitialized issues
- From: Mark Mitchell <mark at codesourcery dot com>
- To: law at redhat dot com
- Cc: gcc at gcc dot gnu dot org
- Date: Mon, 31 Oct 2005 17:11:26 -0800
- Subject: Re: -Wuninitialized issues
- References: <4365CA5E.email@example.com> <firstname.lastname@example.org>
Jeffrey A Law wrote:
> On Sun, 2005-10-30 at 23:40 -0800, Mark Mitchell wrote:
>>In reviewing the PR list, I saw several (maybe 5?) PRs about problems
> Where I suspect we're falling down more often is not issuing warnings
> because the uninitialized variable was optimized away or its uses were
> turned into uses of other variables (possibly temporaries) due to copy
That may be an accurate assessment.
>>modification. I'd expect that most users want a warning about:
>> int x;
>> if (f())
>> x = 3;
>> return x;
>>even if f() happens to always return true on this system. (I don't know
>>that we don't warn in this case; it's just meant as an example of a case
>>where doing too much optimization might cause us to miss a warning
> Certainly if we can't prove f always returns a nonzero value, then a
> warning should be issued. If we do prove f always returns a nonzero
> value, then I think it becomes unclear if we should generate a warning.
I don't think it's unclear; I think it should be a warning. :-) The
fact that f always returns a nonzero value may be a function of
something about the current environment; I think people want this
warning to tell them something about the code, semi-independent of the
current environment. It may be that I've got different ideas about how
this ought to work from some others in the community.
Tools like valgrind/mudflap (and Purify, TestCenter, and CodeCenter
before them...) exist to tell you about bugs that you definitely have.
If there's a bug that doesn't happen to manifest in the test corpus you
have, valgrind doesn't tell you. Often, that's exactly what you want --
don't tell me about the bugs I might have; tell me about the ones I do
have on the inputs I care about.
Tools like lint (including modern incarnations like the Stanford
checker) exist to tell you about bugs you might have. For example: if
this function returns an error code, then you'll exit this function
without releasing the lock you grabbed here. Maybe that function never
returns an error code, or you can magically reclaim the lock somewhere
else; the purpose of the tool is to help you bulletproof against
We have to figure out where this warning ought to lie on this continuum
in order to figure how to implement it. I think most of our optimizer
people think the right point on the continuum lies pretty close to the
valgrind situation. In particular, the question they want to answer is
"is there a code path through this function, when compiled on this
architecture with these flags, etc., for which we might actually use an
uninitialized value?" Using that question, if function f always returns
non-zero, then we should not warn. Different levels of optimization
give different levels of approximation to the abstractly right answer
there; one would hope that as you crank up the optimization level, the
answers get better, as you prove more things about the program.
However, I think the right question is the more lint-like "Is there a
code path through this function, when considered in isolation, and
without being too clever, under which an uninitialized value is used?"
Going back to the original example, if f always returns non-zero on all
architectures, and always will, then why bother writing the conditional?
The programmer who wrote that imagined that, at some point, f might
return zero, and then the code would be buggy. I would consider that a
"latent bug", and in my lint-like mindset, I want to fix it now.
> The late pass could then also warn for those variables which were
> marked by the first pass as maybe uninitialized, but which were
> not marked by the second pass as maybe uninitialized -- these
> are precisely those were optimizations either eliminated problem
> paths through the CFG or DCE eliminated the uninitialized uses.
Why doesn't that boil down to just warning about all the variables
marked by the first pass, either right at the time of the first pass, or
later during the second pass?