Bug 55985 - Misleading message about which variable 'may be used uninitialized in this function'
Summary: Misleading message about which variable 'may be used uninitialized in this fu...
Status: RESOLVED FIXED
Alias: None
Product: gcc
Classification: Unclassified
Component: tree-optimization (show other bugs)
Version: 4.7.1
: P3 normal
Target Milestone: ---
Assignee: Not yet assigned to anyone
URL:
Keywords: diagnostic
Depends on:
Blocks: Wuninitialized
  Show dependency treegraph
 
Reported: 2013-01-15 01:01 UTC by Jonathan Leffler
Modified: 2017-03-21 15:37 UTC (History)
1 user (show)

See Also:
Host:
Target:
Build:
Known to work:
Known to fail:
Last reconfirmed: 2013-01-15 00:00:00


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Jonathan Leffler 2013-01-15 01:01:06 UTC
The problem has been reduced to the following 30 lines of code with no preprocessing required.

typedef struct vtype { int type; } vtype_t;
typedef struct field { int length; } field_t;
typedef struct clist { char *tuple; field_t *fields; } clist_t;

extern int  cvint(const char *p);
extern void updtypes(clist_t *clist, int ocnt, vtype_t *obind);

void
updtypes(clist_t *clist, int ocnt, vtype_t *obind)
{
    char    *tupstart = clist->tuple;
    char    *savtupstart;
    int      colsize = 0;
    field_t *field = clist->fields;

    for (int cnt = ocnt; cnt--; field++, obind++)
    {
        unsigned col_flags = 0;

        tupstart += colsize;

        colsize = cvint(tupstart+1);
        if (*tupstart & 1)
            col_flags |= 0x04;
        tupstart += 5;

        if (col_flags & 0x04)
            tupstart = savtupstart;
    }
}

The problem is that compilation like this refers to 'tupstart' as the uninitialized variable, not 'savtupstart'.  The source file was called 'gccbug.c' for this reproduction.

$ gcc-4.7.1 -O3 -Werror -Wall -g -std=c99 -c gccbug.c
gccbug.c: In function ‘updtypes’:
gccbug.c:20:18: error: ‘tupstart’ may be used uninitialized in this function [-Werror=maybe-uninitialized]
cc1: all warnings being treated as errors
$ gcc-4.7.1 -Werror -Wall -g -std=c99 -c gccbug.c
gccbug.c: In function ‘updtypes’:
gccbug.c:29:22: error: ‘savtupstart’ may be used uninitialized in this function [-Werror=uninitialized]
cc1: all warnings being treated as errors
$

The real problem is that savtupstart is not initialized.

Compilation with '-v' too gives:

$ gcc-4.7.1 -v -O3 -Werror -Wall -g -std=c99 -c gccbug.c
Using built-in specs.
COLLECT_GCC=/usr/gcc/v4.7.1/bin/gcc
Target: x86_64-unknown-linux-gnu
Configured with: /work4/jleffler/open.source/GCC/gcc-4.7.1/configure --prefix=/usr/gcc/v4.7.1 --with-gmp=/usr/gnu64 --with-mpfr=/usr/gnu64 -with-mpc=/usr/gnu64
Thread model: posix
gcc version 4.7.1 (GCC) 
COLLECT_GCC_OPTIONS='-v' '-O3' '-Werror' '-Wall' '-g' '-std=c99' '-c' '-mtune=generic' '-march=x86-64'
 /work5/gcc/v4.7.1/bin/../libexec/gcc/x86_64-unknown-linux-gnu/4.7.1/cc1 -quiet -v -iprefix /work5/gcc/v4.7.1/bin/../lib/gcc/x86_64-unknown-linux-gnu/4.7.1/ gccbug.c -quiet -dumpbase gccbug.c -mtune=generic -march=x86-64 -auxbase gccbug -g -O3 -Werror -Wall -std=c99 -version -o /tmp/ccYrtwtL.s
GNU C (GCC) version 4.7.1 (x86_64-unknown-linux-gnu)
	compiled by GNU C version 4.7.1, GMP version 5.0.2, MPFR version 3.1.0, MPC version 0.9
GGC heuristics: --param ggc-min-expand=89 --param ggc-min-heapsize=112207
ignoring nonexistent directory "/work5/gcc/v4.7.1/bin/../lib/gcc/x86_64-unknown-linux-gnu/4.7.1/../../../../x86_64-unknown-linux-gnu/include"
ignoring duplicate directory "/work5/gcc/v4.7.1/bin/../lib/gcc/../../lib/gcc/x86_64-unknown-linux-gnu/4.7.1/include"
ignoring duplicate directory "/work5/gcc/v4.7.1/bin/../lib/gcc/../../lib/gcc/x86_64-unknown-linux-gnu/4.7.1/include-fixed"
ignoring nonexistent directory "/work5/gcc/v4.7.1/bin/../lib/gcc/../../lib/gcc/x86_64-unknown-linux-gnu/4.7.1/../../../../x86_64-unknown-linux-gnu/include"
#include "..." search starts here:
#include <...> search starts here:
 /work5/gcc/v4.7.1/bin/../lib/gcc/x86_64-unknown-linux-gnu/4.7.1/include
 /work5/gcc/v4.7.1/bin/../lib/gcc/x86_64-unknown-linux-gnu/4.7.1/include-fixed
 /usr/local/include
 /work5/gcc/v4.7.1/bin/../lib/gcc/../../include
 /usr/include
End of search list.
GNU C (GCC) version 4.7.1 (x86_64-unknown-linux-gnu)
	compiled by GNU C version 4.7.1, GMP version 5.0.2, MPFR version 3.1.0, MPC version 0.9
GGC heuristics: --param ggc-min-expand=89 --param ggc-min-heapsize=112207
Compiler executable checksum: 2d58955a5e5707524f76b1886c2957fc
gccbug.c: In function ‘updtypes’:
gccbug.c:20:18: error: ‘tupstart’ may be used uninitialized in this function [-Werror=maybe-uninitialized]
cc1: all warnings being treated as errors
$

The machine where it is running, and was built, is RHEL5:

$ uname -a
Linux toru 2.6.18-128.el5 #1 SMP Wed Dec 17 11:41:38 EST 2008 x86_64 x86_64 x86_64 GNU/Linux
$

(Yes, archaic...sorry about that.)

The variable names and function names have been renamed from the original code; it is unlikely that anyone could spot where it comes from. The structure types have been renamed and their content minimized. The reduced code does not do anything useful. Most changes to the code seem to give the correct 'savtupstart' message; I'm sure there are changes I've not tried that don't change the erroneous output, but not all that many.  Removing the call to 'cvint()' leads to successful compilation (no warning at all), while removing the test before `tupstart = savtupstart;` leads to the warning mentioning 'savtupstart'.

The problem was originally spotted in a 2850 line source file which includes many files and generates over 18,000 lines of preprocessor output.  The original function is just about 1030 lines in the body, plus the declaration which has more parameters and is spread over 8 lines.
Comment 1 Richard Biener 2013-01-15 09:54:56 UTC
Confirmed.  There recently was a duplicate reported for exactly the same issue
(too lazy to look it up).
Comment 2 Jonathan Leffler 2017-03-20 21:05:13 UTC
This problem has been mostly resolved in 5.3.0 (and quite possibly earlier):

$ gcc -O3 -Werror -Wall -g -std=c99   -c -o gccbug.o gccbug.c
gccbug.c: In function ‘updtypes’:
gccbug.c:20:18: error: ‘savtupstart’ may be used uninitialized in this function [-Werror=maybe-uninitialized]
         tupstart += colsize;
                  ^
cc1: all warnings being treated as errors
make: *** [gccbug.o] Error 1
$ gcc  -Werror -Wall -g -std=c99 -c gccbug.c
gccbug.c: In function ‘updtypes’:
gccbug.c:28:22: error: ‘savtupstart’ may be used uninitialized in this function [-Werror=maybe-uninitialized]
             tupstart = savtupstart;
                      ^
cc1: all warnings being treated as errors
rmk: error code 1
$ gcc --version
gcc (GCC) 5.3.0
Copyright (C) 2015 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
$

These warnings are correctly identifying savtupstart (instead of tupstart) as the uninitialized variable.  We can argue about the line that's identified in the first invocation, but the main message is identifying the correct variable.

This test was conducted on the same machine referenced in the original bug report; the version information from 'uname -a' hasn't changed.  The machine is behind multiple layers of firewall and was last booted 'system boot  2015-08-23 21:35'.

The -v output for the non-optimized test was:

$ gcc -v -Werror -Wall -g -std=c99 -c gccbug.c
Using built-in specs.
COLLECT_GCC=gcc
Target: x86_64-unknown-linux-gnu
Configured with: ../gcc-5.3.0/configure --prefix=/usr/gcc/v5.3.0 --with-as=/usr/gnu64/bin/as --with-ld=/usr/gnu64/bin/ld CC=/usr/bin/gcc CXX=/usr/bin/g++ : (reconfigured) ../gcc-5.3.0/configure --prefix=/usr/gcc/v5.3.0 --with-as=/usr/gnu64/bin/as --with-ld=/usr/gnu64/bin/ld CC=/usr/bin/gcc CXX=/usr/bin/g++
Thread model: posix
gcc version 5.3.0 (GCC) 
COLLECT_GCC_OPTIONS='-v' '-Werror' '-Wall' '-g' '-std=c99' '-c' '-mtune=generic' '-march=x86-64'
 /work5/gcc/v5.3.0/bin/../libexec/gcc/x86_64-unknown-linux-gnu/5.3.0/cc1 -quiet -v -iprefix /work5/gcc/v5.3.0/bin/../lib/gcc/x86_64-unknown-linux-gnu/5.3.0/ gccbug.c -quiet -dumpbase gccbug.c -mtune=generic -march=x86-64 -auxbase gccbug -g -Werror -Wall -std=c99 -version -o /tmp/cc6Q2aEc.s
GNU C99 (GCC) version 5.3.0 (x86_64-unknown-linux-gnu)
	compiled by GNU C version 5.3.0, GMP version 6.0.0, MPFR version 3.1.3, MPC version 1.0.3
GGC heuristics: --param ggc-min-expand=100 --param ggc-min-heapsize=131072
ignoring nonexistent directory "/work5/gcc/v5.3.0/bin/../lib/gcc/x86_64-unknown-linux-gnu/5.3.0/../../../../x86_64-unknown-linux-gnu/include"
ignoring duplicate directory "/work5/gcc/v5.3.0/bin/../lib/gcc/../../lib/gcc/x86_64-unknown-linux-gnu/5.3.0/include"
ignoring duplicate directory "/work5/gcc/v5.3.0/bin/../lib/gcc/../../lib/gcc/x86_64-unknown-linux-gnu/5.3.0/include-fixed"
ignoring nonexistent directory "/work5/gcc/v5.3.0/bin/../lib/gcc/../../lib/gcc/x86_64-unknown-linux-gnu/5.3.0/../../../../x86_64-unknown-linux-gnu/include"
#include "..." search starts here:
#include <...> search starts here:
 /work5/gcc/v5.3.0/bin/../lib/gcc/x86_64-unknown-linux-gnu/5.3.0/include
 /work5/gcc/v5.3.0/bin/../lib/gcc/x86_64-unknown-linux-gnu/5.3.0/include-fixed
 /usr/local/include
 /work5/gcc/v5.3.0/bin/../lib/gcc/../../include
 /usr/include
End of search list.
GNU C99 (GCC) version 5.3.0 (x86_64-unknown-linux-gnu)
	compiled by GNU C version 5.3.0, GMP version 6.0.0, MPFR version 3.1.3, MPC version 1.0.3
GGC heuristics: --param ggc-min-expand=100 --param ggc-min-heapsize=131072
Compiler executable checksum: 981b21321de4233d53ef0e051a81a41f
gccbug.c: In function ‘updtypes’:
gccbug.c:28:22: error: ‘savtupstart’ may be used uninitialized in this function [-Werror=maybe-uninitialized]
             tupstart = savtupstart;
                      ^
cc1: all warnings being treated as errors
$

If you require a test with 6.3.0 or a similar more modern version of GCC, please let me know.
Comment 3 Jeffrey A. Law 2017-03-21 15:37:50 UTC
Trunk behaves same way as gcc-5.3 (ie, identifies the right variable as being uninitialized).