I found a particular usage pattern that seems completely ok and no compiler has ever complained on before. Now it raises a warning with gcc-11: A close to minimal example is below. Save as t.c
and compile using gcc-11 -O2 -Wall -c t.c
.
#include <stdlib.h>
#include <string.h>
extern void f(const char *s);
void
t(int len, char *d)
{ char tmp[500];
char *s, *o;
int i;
if ( len <= sizeof(tmp) )
s = tmp;
else if ( !(s=malloc(len)) )
return;
for(o=s,i=0; i < len; i++)
*o++ = d[i]+1;
f(s);
// i = strlen(s);
if ( s != tmp )
free(s);
}
Compiling results in:
gcc-11 -O2 -Wall -c t.c
t.c: In function ‘t’:
t.c:20:3: warning: ‘s’ may be used uninitialized [-Wmaybe-uninitialized]
20 | f(s);
| ^~~~
t.c:4:13: note: by argument 1 of type ‘const char *’ to ‘f’ declared here
4 | extern void f(const char *s);
| ^
t.c:20:3: warning: ‘tmp’ may be used uninitialized [-Wmaybe-uninitialized]
20 | f(s);
| ^~~~
t.c:4:13: note: by argument 1 of type ‘const char *’ to ‘f’ declared here
4 | extern void f(const char *s);
| ^
t.c:8:8: note: ‘tmp’ declared here
8 | { char tmp[500];
| ^~~
Now there are some observations
- calling strlen(s) instead of f(s) does not result in a warning. Note that both accept
const char*
(checked in/usr/include/string.h
) - If I remove the
const
in the declaration off()
, the problem vanishes too. - Calling using
f((const char*)s)
doesn't help either. - Initializing s as in
char *s = NULL
does not help either (and I do not want that anyway as it hides correct warnings about not initializing a variable).
I have learned that claiming something is a GCC bug is typically rightfully proven to be wrong. So I first check here what I'm missing.
edit As I cannot put code in the comment, here is code that disproves part of the claim. This compiles fine:
extern void f(const char *__s);
void
t(int len, char *d)
{ char tmp[500];
char *s=tmp, *o;
int i;
for(o=s,i=0; i < len; i++)
*o++ = d[i]+1;
f(tmp);
}