Bug 32759 - False "may be used uninitialized" (missed VRP optimization)
Summary: False "may be used uninitialized" (missed VRP optimization)
Status: RESOLVED FIXED
Alias: None
Product: gcc
Classification: Unclassified
Component: tree-optimization (show other bugs)
Version: 4.2.0
: P3 minor
Target Milestone: 4.4.0
Assignee: Not yet assigned to anyone
URL:
Keywords: diagnostic
Depends on:
Blocks: Wuninitialized
  Show dependency treegraph
 
Reported: 2007-07-13 19:31 UTC by Bernard Leak
Modified: 2012-06-29 13:39 UTC (History)
3 users (show)

See Also:
Host: i686-pc-linux-gnu
Target: i686-pc-linux-gnu
Build: i686-pc-linux-gnu
Known to work:
Known to fail:
Last reconfirmed: 2007-07-15 21:05:38


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Bernard Leak 2007-07-13 19:31:54 UTC
I'd accept "may be used uninitialized", but I'm positively told
"is used uninitialized", which ain't true.

This is similar to bugs 32395 and 22197: apologies if it turns out to be
a mere duplicate.  My code example is much simpler than the examples
given for those bugs: there are no aggregate types, the parameter
passing isn't interesting, and initialisation obviously DOES happen.

Also seen in 4.1.2 (I got around to building 4.2.0 so I could
verify the problem...)


The warning is attached to the line where 'diff' is assigned a
value.  Note that this value is not then used again.

Required flags: -c -Wuninitialized -O1
(n.b.: -Wuninitialized is incompatible with -O0, but any other -O<n> will do)
No headers required.

double Find_Limit(double xcentre, unsigned ang)
{
        double diff;
        long xlimit;

        ang &= 1U;

        switch (ang)
        {
                case 0U:
                        xlimit = xcentre;
                        break;

                case 1U:
                        xlimit = xcentre;
                        break;
        }

        diff = xlimit;

        return ang ? xlimit : 0.0;
} /* End of function Find_Limit() */

Removing the assignment to diff (which isn't used) demotes
"is uninitialized" to "may be uninitialized".  Combining the two
case-clauses of the switch statement under the same header
(case 0U: case 1U: <stuff>) likewise demotes.  Removing the use of
xlimit in the final (returned-value) expression removes the warning
entirely (so it DOES notice that diff isn't used - or is it more
confused than I think?)

If, in the assignments to xlimit, the right-hand expressions are replaced
with literal constants, the warning disappears entirely - even if the
two literal constants are unequal.  So does the compiler recognise
that the two handled cases in the switch are exhaustive or doesn't it?

This looks deeply strange to me.
Comment 1 Andrew Pinski 2007-07-15 21:05:38 UTC
What is happening is that for the switch statement, we don't know that the value can't be just 0 or 1 at the point where we warn.  We should be able to lower this switch statement into an if statement and get better results.
Comment 2 Bernard Leak 2007-07-16 19:01:07 UTC
I have gone through this removing many repetitions of "see above for my
actual bug report".  Please take it as read (and see above for my actual
bug report).

I explicitly said that the mere confession of ignorance ("may be used
uninitialized") was not a problem.  The claim that 'xlimit' IS used
uninitialized is false.  I don't see that it is in any way justified
by claiming more rather than less ignorance.  The mistake is sensitive
to internal rearrangement (without changed semantics) of the clauses
in the 'switch' statement, and also to the presence or absence of the
assignment to 'diff' following the 'switch' statement.  It's hard to
see in what sense ignorance about the possible values of 'ang' is
affected by either feature of the code.  Even if it is, the mistake is
still a mistake.  The offered explanation is certainly not complete,
since it sheds no light on its selective appearance (well, none to my
possibly poor eyesight, anyway).
Comment 3 Andrew Pinski 2007-07-16 19:10:33 UTC
Oh but what happens is we do some duplication of code (for 4.2 at least) and then we see the variable is used unitialization.  This has changed in the trunk to a may used uninitialized but the issue is still the same, we should not get an may or an is unitialized variable warning anyways as it can never be used unitialized.
Comment 4 Manuel López-Ibáñez 2007-08-22 16:49:47 UTC
Basically, when we reach "diff = xlimit;" we don't know that xlimit must be initialized. This may end up in different scenarios depending on the SSA tree finally generated. In any of those scenarios, not warning is sheer luck.

If you remove the assignment to diff, still when we reach "ang ? xlimit : 0.0;" we don't know that xlimit is always initialized. We get the "may be" because we don't know the value of "ang", so xlimit may not be used at all.

Finally, I guess that using constants make the warning disappear because the constant-propagation pass assumes that the uninitialized value of xlimit is either of the constants and thus xlimit is never used uninitialized.

My conclusion here is that we should not get a "is uninitialized". Maybe we can use the fact that the block is not entered 100% of times to avoid saying "is used"? 

Nonetheless, avoiding the warning completely depends on being able to avoid a default case for the switch (which is a missed-optimization in VRP and not a diagnostics problem).
Comment 5 Richard Biener 2012-06-29 13:39:47 UTC
Fixed at -O2 since GCC 4.4.