Hello,
I am interested in learning about clang’s -Wsometimes-uninitialized implementation and how is it different than gcc’s -Wmaybe-uninitialized. For example, if we consider this code:
#include <stdlib.h>
int test(int random, int cond1, int cond2) {
volatile int *ptr;
if (cond1) { //<<<< cond1
ptr = (int *)calloc(1, sizeof(int));
}
if (cond2) { //<<<< cond2 , independent of cond1
*ptr = 1;
}
return 0;
}
With gcc 8.3.1, I get the following output:
$ gcc -g -c func.c -O1 -Wuninitialized
func.c: In function ‘test’:
func.c:8:10: warning: ‘ptr’ may be used uninitialized in this function [-Wmaybe-uninitialized]
*ptr = 1;
(debug-llvm-11) /nobackup/alissidd/CSCvv46785$ vim func.c
(debug-llvm-11) /nobackup/alissidd/CSCvv46785$ gcc -O1 -Wuninitialized -Wmaybe-uninitialized -c func.c
func.c: In function ‘test’:
func.c:8:10: warning: ‘ptr’ may be used uninitialized in this function [-Wmaybe-uninitialized]
*ptr = 1;
However, with clang 11.0.0 I don’t get any warnings:
**$** clang -O1 -Wuninitialized -Wsometimes-uninitialized -c func.c
**$**
It was detected by the static analyzer though:
Scan-build clang -O1 -Wuninitialized -Wsometimes-uninitialized -c func.c
scan-build: Using 'clang-11' for static analysis
func.c:8:10: warning: Dereference of undefined pointer value [core.NullDereference]
*ptr = 1;
~~~~~^~~
func.c:10:10: warning: Potential leak of memory pointed to by 'ptr' [unix.Malloc]
return 0;
^
2 warnings generated.
scan-build: Analysis run complete.
scan-build: 2 bugs found.
I did see the -Wsometimes-uninitialized flag working, if for example, I move the use of the **ptr** variable outside of a condition:
#include <stdlib.h>
int test(int random, int cond1, int cond2) {
volatile int *ptr;
if (cond1) { //<<<< cond1
ptr = (int *)calloc(1, sizeof(int));
}
if (cond2) { //<<<< cond2 , independent of cond1
*ptr = 1;
}
**return ptr**;
}
**$** clang -O1 -Wuninitialized -Wsometimes-uninitialized -c func.c
func.c:10:10: warning: incompatible pointer to integer conversion returning 'volatile int *' from a function with result type 'int' [-Wint-conversion]
return ptr;
^~~
func.c:4:7: warning: variable 'ptr' is used uninitialized whenever 'if' condition is false [-Wsometimes-uninitialized]
if (cond1) { //<<<< cond1
^~~~~
func.c:10:10: note: uninitialized use occurs here
return ptr;
^~~
func.c:4:3: note: remove the 'if' if its condition is always true
if (cond1) { //<<<< cond1
^~~~~~~~~~~
func.c:3:20: note: initialize the variable 'ptr' to silence this warning
volatile int *ptr;
^
= NULL
2 warnings generated.
I’m new to clang development and would appreciate the help with the following questions:
- Are clang’s -Wsometimes-uninitialized and gcc’s -Wmaybe-unintialized comparable?
- As is shown that a use of an uninitialized variable within a condition could not be detected by the -Wuninitialized/-Wsometimes-uninitialized flag, is this behavior by design?
- I’m trying to understand the source code of the -Wuninitialized and -Wsometimes-initialized in particular and I was able to single out the files that maybe used to implement it:
- clang/lib/Analysis/UninitializedValues.cpp
- clang/include/clang/Analysis/Analyses/UninitializedValues.h
- clang/lib/Sema/AnalysisBasedWarnings.cpp
Any pointers about how should I go about reading and understanding it will be very helpful.
Thank you,
Ali