Created attachment 10293 [details]
Hi. I encountered a bug where under certain conditions the compiler would miss an obvious warning when running with ccache. Originally this looked like a gcc bug to me, so I reported it there: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=63178
Looking closer, ccache appears to be to blame (ccache 3.1.9-1 from Debian). I'm copying that gcc bug report here.
I'm seeing that under particular conditions I can pass a wrong type into a function, and no warning results. I'm attaching a minimized test case to show this. There are two files: bugreport.c and bugreport.h. The .c includes the .h. The issue only happens when the .h file is placed into /usr/include, and included using <> instead of "".
bugreport.c has this snippet:
typedef ... sss_t;
int fff( sss_t* ctx, ... )
sss_t* sss = NULL;
So fff() expects a sss_t* as its first argument, but we're giving it a sss_t** instead. This should generate a warning. However:
dima@shorty:/tmp$ gcc-4.9 -Wall -Wextra -c -o/dev/null bugreport.c
So gcc thinks this is fine. Tweaking the test case even a little bit makes the warning come back. For instance, including the header in the local directory, instead of in /usr/include makes it work, as does simply putting the header the contents into the .c and including nothing. Removing the F() call makes it work. Changing the whitespace in the F() call makes it work.
I'm seeing the missing warning with gcc 4.8 and 4.9 with ccache (works fine without ccache). gcc 4.4 emits the warning even with ccache.
Created attachment 10294 [details]
I would say that this is not a ccache bug. For ccache to work as expected in its default operation mode, the compiler must be able to compile its own preprocessed source code with the same result as compiling without the preprocessing step.
compiler [OPTIONS] -E source.c -o source.i
compiler [OPTIONS] -c source.i -o source.o
needs to give the same result as
compiler [OPTIONS] -c source.c -o source.o
GCC doesn't do that for your test case:
% gcc-4.9 -Wall -Wextra -E bugreport.c -o bugreport.i
% gcc-4.9 -Wall -Wextra -c bugreport.i -o /dev/null
% gcc-4.9 -Wall -Wextra -c bugreport.c -o /dev/null
bugreport.c: In function ‘fn1’:
bugreport.c:14:5: warning: passing argument 1 of ‘fff’ from incompatible pointer type
bugreport.c:6:5: note: expected ‘struct sss_t *’ but argument is of type ‘struct sss_t **’
int fff( sss_t* ctx, int a, int b);
bugreport.c:15:1: warning: control reaches end of non-void function [-Wreturn-type]
Whether this is to be considered a bug in GCC is up to the GCC developers, I guess, but it's at least not compatible with ccache's expectations.
One workaround is to tell ccache not to compile the preprocessed source code by setting CCACHE_CPP2. This has a performance cost, however.
Digging a bit deeper, the behavior difference comes from this part of the preprocessed output:
% tail -n 11 bugreport.i
sss_t* sss = ((void *)0);
# 12 "bugreport.c" 3 4
, 0 )
The flag "3" after '# 12 "bugreport.c"' indicates that the following text comes from a system header, which doesn't look right. (If bugreport.h is found locally instead of in /usr/include, then the "3" flag disappears.) Sounds like a GCC bug to me.
Aha. As a mentioned in the bug report bugreport.h needs to be #included with <> instead of "" for the bug to show itself. But the problematic code isn't IN bugreport.h, so the warning should show up regardless. I'll go back to the gcc bug tracker. Thanks for the insight
Do I need to clear the cache via -c or -C after setting this option? I had a warning that was not showing up when using ccache (-Wformat). I set the CCACHE_CPP2 value to true, but it still was not showing up when using ccache, but it was when compiling without it. I finally did a -c and -C to clear out the cache. Is the lack of a -Wformat warning a bug, or was it a matter of clearing out the cache after enabling the right flags?
(In reply to Chance from comment #4)
Yes, you currently need to clear the cache (with "-C") to avoid getting cache hits from when you didn't use CCACHE_CPP2. This will be fixed in future ccache versions.