Bug 65812

Summary: gcc 4.9.1 doesn't warn about uninitialized variable use declared in a switch/case statement when compiled with -O
Product: gcc Reporter: Joe Perches <joe>
Component: cAssignee: Not yet assigned to anyone <unassigned>
Status: RESOLVED INVALID    
Severity: normal CC: jakub
Priority: P3    
Version: 4.9.1   
Target Milestone: ---   
Host: Target:
Build: Known to work:
Known to fail: Last reconfirmed: 2015-04-20 00:00:00
Attachments: sample code

Description Joe Perches 2015-04-20 10:37:18 UTC
Created attachment 35365 [details]
sample code

Here is a small example:

$ cat t.c
struct foo {
       int bar[100];
};

void foo_1(void)
{
	unsigned int m;
	extern struct foo *array[100];
	struct foo *a = array[m];

	a = a;
}

void foo_2(void)
{
	int i = 1;

	switch (i) {
	case 1: {
		unsigned int m;
		extern struct foo *array[100];
		struct foo *a = array[m];

		a = a;
		break;
	}
	}
}

$

gcc warns properly about both foo_1 and foo_2 without -O

$ gcc -c -Wall t.c
t.c: In function ‘foo_1’:
t.c:9:14: warning: ‘m’ is used uninitialized in this function [-Wuninitialized]
  struct foo *a = array[m];
              ^
t.c: In function ‘foo_2’:
t.c:21:15: warning: ‘m’ may be used uninitialized in this function [-Wmaybe-uninitialized]
   struct foo *a = array[m];
               ^
$

but gcc warns about foo_1 but not foo_2 with -O

$ gcc -c -Wall -O t.c
t.c: In function ‘foo_1’:
t.c:9:14: warning: ‘m’ is used uninitialized in this function [-Wuninitialized]
  struct foo *a = array[m];
              ^

$ gcc -v
Using built-in specs.
COLLECT_GCC=/usr/bin/gcc
COLLECT_LTO_WRAPPER=/usr/lib/gcc/x86_64-linux-gnu/4.9/lto-wrapper
Target: x86_64-linux-gnu
Configured with: ../src/configure -v --with-pkgversion='Ubuntu 4.9.1-16ubuntu6' --with-bugurl=file:///usr/share/doc/gcc-4.9/README.Bugs --enable-languages=c,c++,java,go,d,fortran,objc,obj-c++ --prefix=/usr --program-suffix=-4.9 --enable-shared --enable-linker-build-id --libexecdir=/usr/lib --without-included-gettext --enable-threads=posix --with-gxx-include-dir=/usr/include/c++/4.9 --libdir=/usr/lib --enable-nls --with-sysroot=/ --enable-clocale=gnu --enable-libstdcxx-debug --enable-libstdcxx-time=yes --enable-gnu-unique-object --disable-vtable-verify --enable-plugin --with-system-zlib --disable-browser-plugin --enable-java-awt=gtk --enable-gtk-cairo --with-java-home=/usr/lib/jvm/java-1.5.0-gcj-4.9-amd64/jre --enable-java-home --with-jvm-root-dir=/usr/lib/jvm/java-1.5.0-gcj-4.9-amd64 --with-jvm-jar-dir=/usr/lib/jvm-exports/java-1.5.0-gcj-4.9-amd64 --with-arch-directory=amd64 --with-ecj-jar=/usr/share/java/eclipse-ecj.jar --enable-objc-gc --enable-multiarch --disable-werror --with-arch-32=i686 --with-abi=m64 --with-multilib-list=m32,m64,mx32 --enable-multilib --with-tune=generic --enable-checking=release --build=x86_64-linux-gnu --host=x86_64-linux-gnu --target=x86_64-linux-gnu
Thread model: posix
gcc version 4.9.1 (Ubuntu 4.9.1-16ubuntu6)
Comment 1 Richard Biener 2015-04-20 10:46:15 UTC
This is because at the point where we warn we don't know that the code is
executed unconditionally and with optimization we don't warn about maybe-uninitialized uses early.

Late we have removed all code as dead and thus do not warn either.

I'd say it works as intended (even though surprising).
Comment 2 Jakub Jelinek 2015-04-20 10:53:40 UTC
This changed supposedly with r138933 and from that PR20644 I think it is quite clear this is intentional.  The code in foo_2 is conditional (on a condition later proved to be always true, though), so we really don't want to warn on it early, because it might be in dead code, and we don't warn for it late because it really is dead code, optimized away as nothing uses it.  If you add say a global void *b; variable and change the a = a; statements to b = a;, then it will warn even when optimizing, as the code won't be dead.
Comment 3 Joe Perches 2015-04-20 11:18:53 UTC
Thank you both for your very prompt replies.

It might be useful to have a -Wunused-eliminated type extra warning
though that might be very noisy.
Comment 4 Marek Polacek 2015-04-20 13:42:25 UTC
So shouldn't this be INVALID rather than NEW?
Comment 5 Jakub Jelinek 2015-04-20 13:43:06 UTC
Sure.