Bug 32759

Summary: False "may be used uninitialized" (missed VRP optimization)
Product: gcc Reporter: Bernard Leak <bernard>
Component: tree-optimizationAssignee: Not yet assigned to anyone <unassigned>
Status: RESOLVED FIXED    
Severity: minor CC: gcc-bugs, manu, pinskia
Priority: P3 Keywords: diagnostic
Version: 4.2.0   
Target Milestone: 4.4.0   
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
Bug Depends on:    
Bug Blocks: 24639    

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.