Bug 10819 - Missing warning with ccache: "incorrect-type-passed-to-function"
Summary: Missing warning with ccache: "incorrect-type-passed-to-function"
Status: RESOLVED INVALID
Alias: None
Product: ccache
Classification: Unclassified
Component: ccache (show other bugs)
Version: 3.1.9
Hardware: All All
: P5 normal
Target Milestone: ---
Assignee: Joel Rosdahl
QA Contact: Joel Rosdahl
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2014-09-17 20:02 UTC by sambabugs
Modified: 2014-12-26 08:54 UTC (History)
0 users

See Also:


Attachments
bugreport.c (206 bytes, text/x-csrc)
2014-09-17 20:02 UTC, sambabugs
no flags Details
bugreport.h (66 bytes, application/octet-stream)
2014-09-17 20:03 UTC, sambabugs
no flags Details

Note You need to log in before you can comment on or make changes to this bug.
Description sambabugs 2014-09-17 20:02:08 UTC
Created attachment 10293 [details]
bugreport.c

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;
    fff(&sss,0,0);

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
<no output>

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.
Comment 1 sambabugs 2014-09-17 20:03:01 UTC
Created attachment 10294 [details]
bugreport.h
Comment 2 Joel Rosdahl 2014-09-19 18:59:54 UTC
Hi Dima,

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.

In essence,

    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
     fff(&sss,0,0);
         ^
    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
    int fn1()
    {
        sss_t* sss = ((void *)0);

        printf("%s %d",
     "bugreport.c"
    # 12 "bugreport.c" 3 4
        , 0 )
                      ;
        fff(&sss,0,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.
Comment 3 sambabugs 2014-09-19 19:22:02 UTC
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
Comment 4 Chance 2014-12-23 22:38:38 UTC
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?
Comment 5 Joel Rosdahl 2014-12-26 08:54:03 UTC
(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.