Created attachment 44532 [details] Preprocessed source Compiling the code with the following command: gcc -v -save-temps -Wall -O test.c Gives this output: gcc -v -save-temps -Wall -O test.c Using built-in specs. COLLECT_GCC=gcc COLLECT_LTO_WRAPPER=/usr/local/libexec/gcc/x86_64-pc-linux-gnu/8.2.0/lto-wrapper Target: x86_64-pc-linux-gnu Configured with: ../gcc-8.2.0/configure --enable-languages=c,c++ Thread model: posix gcc version 8.2.0 (GCC) COLLECT_GCC_OPTIONS='-v' '-save-temps' '-Wall' '-O' '-mtune=generic' '-march=x86-64' /usr/local/libexec/gcc/x86_64-pc-linux-gnu/8.2.0/cc1 -E -quiet -v -imultiarch x86_64-linux-gnu test.c -mtune=generic -march=x86-64 -Wall -O -fpch-preprocess -o test.i ignoring nonexistent directory "/usr/local/include/x86_64-linux-gnu" ignoring nonexistent directory "/usr/local/lib/gcc/x86_64-pc-linux-gnu/8.2.0/../../../../x86_64-pc-linux-gnu/include" #include "..." search starts here: #include <...> search starts here: /usr/local/lib/gcc/x86_64-pc-linux-gnu/8.2.0/include /usr/local/include /usr/local/lib/gcc/x86_64-pc-linux-gnu/8.2.0/include-fixed /usr/include/x86_64-linux-gnu /usr/include End of search list. COLLECT_GCC_OPTIONS='-v' '-save-temps' '-Wall' '-O' '-mtune=generic' '-march=x86-64' /usr/local/libexec/gcc/x86_64-pc-linux-gnu/8.2.0/cc1 -fpreprocessed test.i -quiet -dumpbase test.c -mtune=generic -march=x86-64 -auxbase test -O -Wall -version -o test.s GNU C17 (GCC) version 8.2.0 (x86_64-pc-linux-gnu) compiled by GNU C version 8.2.0, GMP version 6.1.2, MPFR version 4.0.1, MPC version 1.1.0, isl version isl-0.19-GMP GGC heuristics: --param ggc-min-expand=100 --param ggc-min-heapsize=131072 GNU C17 (GCC) version 8.2.0 (x86_64-pc-linux-gnu) compiled by GNU C version 8.2.0, GMP version 6.1.2, MPFR version 4.0.1, MPC version 1.1.0, isl version isl-0.19-GMP GGC heuristics: --param ggc-min-expand=100 --param ggc-min-heapsize=131072 Compiler executable checksum: 82490e2e2080530dcab0165c2e5082fa test.c: In function ‘main’: test.c:15:20: warning: ‘str’ may be used uninitialized in this function [-Wmaybe-uninitialized] if(initialize) free(str); ^~~~~~~~~ COLLECT_GCC_OPTIONS='-v' '-save-temps' '-Wall' '-O' '-mtune=generic' '-march=x86-64' /usr/local/lib/gcc/x86_64-pc-linux-gnu/8.2.0/../../../../x86_64-pc-linux-gnu/bin/as -v --64 -o test.o test.s GNU assembler version 2.31.1 (x86_64-pc-linux-gnu) using BFD version (GNU Binutils) 2.31.1 COMPILER_PATH=/usr/local/libexec/gcc/x86_64-pc-linux-gnu/8.2.0/:/usr/local/libexec/gcc/x86_64-pc-linux-gnu/8.2.0/:/usr/local/libexec/gcc/x86_64-pc-linux-gnu/:/usr/local/lib/gcc/x86_64-pc-linux-gnu/8.2.0/:/usr/local/lib/gcc/x86_64-pc-linux-gnu/:/usr/local/lib/gcc/x86_64-pc-linux-gnu/8.2.0/../../../../x86_64-pc-linux-gnu/bin/ LIBRARY_PATH=/usr/local/lib/gcc/x86_64-pc-linux-gnu/8.2.0/:/usr/local/lib/gcc/x86_64-pc-linux-gnu/8.2.0/../../../../lib64/:/lib/x86_64-linux-gnu/:/lib/../lib64/:/usr/lib/x86_64-linux-gnu/:/usr/lib/../lib64/:/usr/local/lib/gcc/x86_64-pc-linux-gnu/8.2.0/../../../../x86_64-pc-linux-gnu/lib/:/usr/local/lib/gcc/x86_64-pc-linux-gnu/8.2.0/../../../:/lib/:/usr/lib/ COLLECT_GCC_OPTIONS='-v' '-save-temps' '-Wall' '-O' '-mtune=generic' '-march=x86-64' /usr/local/libexec/gcc/x86_64-pc-linux-gnu/8.2.0/collect2 -plugin /usr/local/libexec/gcc/x86_64-pc-linux-gnu/8.2.0/liblto_plugin.so -plugin-opt=/usr/local/libexec/gcc/x86_64-pc-linux-gnu/8.2.0/lto-wrapper -plugin-opt=-fresolution=test.res -plugin-opt=-pass-through=-lgcc -plugin-opt=-pass-through=-lgcc_s -plugin-opt=-pass-through=-lc -plugin-opt=-pass-through=-lgcc -plugin-opt=-pass-through=-lgcc_s --eh-frame-hdr -m elf_x86_64 -dynamic-linker /lib64/ld-linux-x86-64.so.2 /usr/lib/x86_64-linux-gnu/crt1.o /usr/lib/x86_64-linux-gnu/crti.o /usr/local/lib/gcc/x86_64-pc-linux-gnu/8.2.0/crtbegin.o -L/usr/local/lib/gcc/x86_64-pc-linux-gnu/8.2.0 -L/usr/local/lib/gcc/x86_64-pc-linux-gnu/8.2.0/../../../../lib64 -L/lib/x86_64-linux-gnu -L/lib/../lib64 -L/usr/lib/x86_64-linux-gnu -L/usr/lib/../lib64 -L/usr/local/lib/gcc/x86_64-pc-linux-gnu/8.2.0/../../../../x86_64-pc-linux-gnu/lib -L/usr/local/lib/gcc/x86_64-pc-linux-gnu/8.2.0/../../.. test.o -lgcc --as-needed -lgcc_s --no-as-needed -lc -lgcc --as-needed -lgcc_s --no-as-needed /usr/local/lib/gcc/x86_64-pc-linux-gnu/8.2.0/crtend.o /usr/lib/x86_64-linux-gnu/crtn.o COLLECT_GCC_OPTIONS='-v' '-save-temps' '-Wall' '-O' '-mtune=generic' '-march=x86-64' GCC complains that 'str' may be uninitialized, which is not possible. Requirements for triggering the bug include compiling with -O1 or greater. Omitting this flag gives no warning. Also, no warning is produced if func() returns just a constant value. It appears like GCC thinks that func() may have some side effects which change the value of initialize, which is not the case. Also, while substituting the call to free() with another expression with str (e.g. puts(str) or printf("%p", str)) does not remove the warning, the call to malloc() turns out to be important. Replacing it with a constant value makes the warning dissapear, regardless of the expression used in place of free().
How does GCC know that rand does not change the global variable initialize? Or something else before main has changed it from 1 to 0?
I don't know. Somehow it does know it when the testcase is compiled without any -O flags, but it not something trivial, and so I would not be surprised if GCC were not able to get that information.
(In reply to Aritz Erkiaga from comment #2) > I don't know. Somehow it does know it when the testcase is compiled without > any -O flags, but it not something trivial, and so I would not be surprised > if GCC were not able to get that information. Because without any -O option (aka -O0) GCC does not enable any flow based uninitilization checking.
Ok, then this is not a bug. Maybe a feature request? Well, actually I think it would be safe for the compiler to assume that libc (and possibly other external libraries) don't have access to variables defined in the source file being compiled. Of course, they could do whatever they like, but the possibility is not worth a warning, as I see it.
(In reply to Aritz Erkiaga from comment #4) GCC does have knowledge about many libc functions but rand() isn't one of them (yet). It would be possible to add rand() to the list but it would only solve this one test case (i.e., involving rand()). I don't think adding a built-in just to avoid a -Wuninitialized in this case is worth it. There may be other reasons to add it, such as constraining its return value to [0, RAND_MAX]. If you can make a more compelling case for it there's a decent chance that it will be added. Barring that, the test case reduces to: $ cat pr86940.c && gcc -O2 -S -Wall pr86940.c int f (void); void g (void) { void *p; if (f ()) p = __builtin_malloc (8); if (f ()) __builtin_free (p); } pr86940.c: In function ‘g’: pr86940.c:10:5: warning: ‘p’ may be used uninitialized in this function [-Wmaybe-uninitialized] __builtin_free (p); ^~~~~~~~~~~~~~~~~~