Bug 69230 - false -Wmaybe-uninitialized with -O1
Summary: false -Wmaybe-uninitialized with -O1
Status: RESOLVED INVALID
Alias: None
Product: gcc
Classification: Unclassified
Component: middle-end (show other bugs)
Version: 6.0
: P3 normal
Target Milestone: ---
Assignee: Not yet assigned to anyone
URL:
Keywords: diagnostic
Depends on:
Blocks:
 
Reported: 2016-01-11 19:12 UTC by Martin Sebor
Modified: 2016-01-11 20:37 UTC (History)
0 users

See Also:
Host:
Target:
Build:
Known to work:
Known to fail:
Last reconfirmed:


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Martin Sebor 2016-01-11 19:12:49 UTC
With -O2, versions of gcc going as far back as 4.5.3 all the way to recent trunk (6.0) issues a -Wmaybe-uninitialized warning for the code below.  The bug appears to be masking a large number of problems in glibc (see https://sourceware.org/bugzilla/show_bug.cgi?id=19444).

$ (cc=$HOME/bin/gcc-5.1.0/bin/gcc; cat a.c && set -x && $cc -S -o/dev/null -O1 -Wall -Wextra a.c && $cc -O2 -S -Wall -Wextra -o/dev/null a.c)
int foo (int i)
{
    int j;

    switch (i & 2) {
    case 0: j = 1; break;
    case 1: j = 2; break;
    case 2: j = 3; break;
    case 3: j = 4; break;
    }
    return j + 1;
}
+ /home/msebor/bin/gcc-5.1.0/bin/gcc -S -o/dev/null -O1 -Wall -Wextra a.c
a.c: In function ‘foo’:
a.c:11:12: warning: ‘j’ may be used uninitialized in this function [-Wmaybe-uninitialized]
     return j + 1;
            ^
+ /home/msebor/bin/gcc-5.1.0/bin/gcc -O2 -S -Wall -Wextra -o/dev/null a.c
Comment 1 Andrew Pinski 2016-01-11 19:21:34 UTC
switch (i & 2)

i & 2 is either 0 or 2.  there is a case for both 0 and 2 in the switch statement.

So this is invalid.
Comment 2 Martin Sebor 2016-01-11 20:06:16 UTC
The glibc test case is actually closer to the following (I had made a typo in the bitwise AND expression).  When (i == 4), j is never assigned to.

int foo (int i)
{
    int j;

    switch (i & 3) {
    case 0: j = 1; break;
    case 1: j = 2; break;
    case 2: j = 3; break;
    case 3: j = 4; break;
    }
    return j + 1;
}

For reference, an example of glibc code where this causes a problem is here:
https://sourceware.org/git/?p=glibc.git;a=blob;f=sysdeps/ieee754/dbl-64/e_jn.c#l103
Comment 3 Andrew Pinski 2016-01-11 20:16:48 UTC
This new testcase is still broken as i & 3 is 0, 1, 2 or 3.  All of the case statements are there too.  So if you want to say something the bug is in -O1 which should not warn instead.

But that requires VRP which is what figures out i & 3 to have a range of [0,3] and that only runs at -O2.

There is still no bug for -O2 here.  GCC is correct those j is initialized on all paths.
Comment 4 Martin Sebor 2016-01-11 20:37:07 UTC
My bad.  I confused the decimal 3 for a binary 111.  Gcc does warn both ways when the controlling expression is (i & 7) so the problem is the other way around.  Thanks for the correction.  I suppose this really is invalid since the GCC manual notes the -O1 caveat for a similar case, and glibc should either not be built with -Wmaybe-uninitialized and -O1 or it should add a default case to the switch.