Bug 11674 - Erroneous warning when using clang-via-ccache that doesn't appear in /usr/bin/clang
Erroneous warning when using clang-via-ccache that doesn't appear in /usr/bin...
Status: RESOLVED INVALID
Product: ccache
Classification: Unclassified
Component: ccache
3.2.4
x64 Linux
: P5 normal
: ---
Assigned To: Joel Rosdahl
Joel Rosdahl
:
Depends on:
Blocks:
  Show dependency treegraph
 
Reported: 2016-01-14 21:01 UTC by Shlomi Fish
Modified: 2016-01-18 10:39 UTC (History)
0 users

See Also:


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Shlomi Fish 2016-01-14 21:01:05 UTC
I'm on Mageia Linux x86-64 v6 using ccache-3.2.4-1.mga6 and clang from llvm-3.7.1-3.mga6.src.rpm . When I compile my C source via the ccache's "clang" symlink I am getting a warning that does not appear with the same command line in /usr/bin/clang (even with the -Warray-bounds warn flag specified). See the sample C code and the makefile at:

https://github.com/shlomif/ccache-clang-stray-Warray-bounds-warning-bug

Shell session (also happens in a new UNIX user account):

<<<<<<<<<<<<

kdetest@telaviv1:~$ ls
1_001.png                                      Music@
bin/                                           Perl-Locale-gettext/
ccache-clang-stray-Warray-bounds-warning-bug/  Pictures/
Delete-Local-Settings.bash                     Templates/
Desktop/                                       test-song.h2song
Documents/                                     tmp/
Downloads/                                     Videos/
firefox.dump.txt                               Xorg.1.log
korganizer-20160111-001849.kcrash.txt
kdetest@telaviv1:~$ cd ccache-clang-stray-Warray-bounds-warning-bug/
kdetest@telaviv1:~/ccache-clang-stray-Warray-bounds-warning-bug$ ls
Makefile                            pi_make_microsoft_freecell_board.o
pi_make_microsoft_freecell_board.c
kdetest@telaviv1:~/ccache-clang-stray-Warray-bounds-warning-bug$ make good
/usr/bin/clang -Warray-bounds -DFCS_COMPILE_DEBUG_FUNCTIONS=1 -DFCS_DBM_USE_LIBAVL=1 -DFCS_DBM_WITHOUT_CACHES=1 -DFCS_DEBONDT_DELTA_STATES=1 -I/home/shlomif/progs/freecell/git/fc-solve/fc-solve/source/libavl -I/home/shlomif/progs/freecell/git/fc-solve/fc-solve/B -I/home/shlomif/progs/freecell/git/fc-solve/fc-solve/source -I/home/shlomif/progs/freecell/git/fc-solve/fc-solve/source/patsolve-shlomif/patsolve  -O2 -g -DNDEBUG   -fvisibility=hidden -march=corei7-avx -fomit-frame-pointer -c pi_make_microsoft_freecell_board.c
kdetest@telaviv1:~/ccache-clang-stray-Warray-bounds-warning-bug$ make bad
/home/kdetest/bin/clang -DFCS_COMPILE_DEBUG_FUNCTIONS=1 -DFCS_DBM_USE_LIBAVL=1 -DFCS_DBM_WITHOUT_CACHES=1 -DFCS_DEBONDT_DELTA_STATES=1 -I/home/shlomif/progs/freecell/git/fc-solve/fc-solve/source/libavl -I/home/shlomif/progs/freecell/git/fc-solve/fc-solve/B -I/home/shlomif/progs/freecell/git/fc-solve/fc-solve/source -I/home/shlomif/progs/freecell/git/fc-solve/fc-solve/source/patsolve-shlomif/patsolve  -O2 -g -DNDEBUG   -fvisibility=hidden -march=corei7-avx -fomit-frame-pointer -c pi_make_microsoft_freecell_board.c
pi_make_microsoft_freecell_board.c:168:2087: warning: array index 3 is past the end of the array (which contains 3 elements) [-Warray-bounds]
        if (!__extension__ ({ size_t __s1_len, __s2_len; (__builtin_constant_p (argv[arg]) && __builtin_constant_p ("-t") && (__s1_len = strlen (argv[arg]), __s2_len = strlen ("-t"), (!((size_t)(const void *)((argv[arg]) + 1) - (size_t)(const void *)(argv[arg]) == 1) || __s1_len >= 4) && (!((size_t)(const void *)(("-t") + 1) - (size_t)(const void *)("-t") == 1) || __s2_len >= 4)) ? __builtin_strcmp (argv[arg], "-t") : (__builtin_constant_p (argv[arg]) && ((size_t)(const void *)((argv[arg]) + 1) - (size_t)(const void *)(argv[arg]) == 1) && (__s1_len = strlen (argv[arg]), __s1_len < 4) ? (__builtin_constant_p ("-t") && ((size_t)(const void *)(("-t") + 1) - (size_t)(const void *)("-t") == 1) ? __builtin_strcmp (argv[arg], "-t") : (__extension__ ({ const unsigned char *__s2 = (const unsigned char *) (const char *) ("-t"); int __result = (((const unsigned char *) (const char *) (argv[arg]))[0] - __s2[0]); if (__s1_len > 0 && __result == 0) { __result = (((const unsigned char *) (const char *) (argv[arg]))[1] - __s2[1]); if (__s1_len > 1 && __result == 0) { __result = (((const unsigned char *) (const char *) (argv[arg]))[2] - __s2[2]); if (__s1_len > 2 && __result == 0) __result = (((const unsigned char *) (const char *) (argv[arg]))[3] - __s2[3]); } } __result; }))) : (__builtin_constant_p ("-t") && ((size_t)(const void *)(("-t") + 1) - (size_t)(const void *)("-t") == 1) && (__s2_len = strlen ("-t"), __s2_len < 4) ? (__builtin_constant_p (argv[arg]) && ((size_t)(const void *)((argv[arg]) + 1) - (size_t)(const void *)(argv[arg]) == 1) ? __builtin_strcmp (argv[arg], "-t") : (- (__extension__ ({ const unsigned char *__s2 = (const unsigned char *) (const char *) (argv[arg]); int __result = (((const unsigned char *) (const char *) ("-t"))[0] - __s2[0]); if (__s2_len > 0 && __result == 0) { __result = (((const unsigned char *) (const char *) ("-t"))[1] - __s2[1]); if (__s2_len > 1 && __result == 0) { __result = (((const unsigned char *) (const char *) ("-t"))[2] - __s2[2]); if (__s2_len > 2 && __result == 0) __result = (((const unsigned char *) (const char *) ("-t"))[3] - __s2[3]); } } __result; })))) : __builtin_strcmp (argv[arg], "-t")))); }))
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      ^      ~
1 warning generated.
kdetest@telaviv1:~/ccache-clang-stray-Warray-bounds-warning-bug$ 
>>>>>>>>>>>>>>>>>>>
Comment 1 Joel Rosdahl 2016-01-16 15:37:10 UTC
The default settings of ccache require the compiler to be able to compile its own preprocessed output without errors/warnings. You seem to have hit a bug in clang which can be reproduced like this:

/usr/bin/clang -Warray-bounds -DFCS_COMPILE_DEBUG_FUNCTIONS=1 -DFCS_DBM_USE_LIBAVL=1 -DFCS_DBM_WITHOUT_CACHES=1 -DFCS_DEBONDT_DELTA_STATES=1   -O2 -g -DNDEBUG   -fvisibility=hidden -march=corei7-avx -fomit-frame-pointer -E pi_make_microsoft_freecell_board.c -o pi_make_microsoft_freecell_board.i && /usr/bin/clang -DFCS_COMPILE_DEBUG_FUNCTIONS=1 -DFCS_DBM_USE_LIBAVL=1 -DFCS_DBM_WITHOUT_CACHES=1 -DFCS_DEBONDT_DELTA_STATES=1  -O2 -g -DNDEBUG   -fvisibility=hidden -march=corei7-avx -fomit-frame-pointer -c pi_make_microsoft_freecell_board.i

Output:

pi_make_microsoft_freecell_board.c:168:2127: warning: array index 3 is past the end of the array (which contains 3 elements) [-Warray-bounds]
  ...char *) ("-t"))[2] - __s2[2]); if (__s2_len > 2 && __result == 0) __result = (((const unsigned char *) (const char *) ("-t"))[3] - __s2[3]); } } __result; ...
                                                                                                                            ^      ~
1 warning generated.

A workaround is to set the run_second_cpp (CCACHE_CPP2) configuration option, see "Errors when compiling with ccache" on https://ccache.samba.org/manual.html#_errors_when_compiling_with_ccache.

I don't see anything that ccache could reasonably do to avoid the warning in this case, so closing as invalid.
Comment 2 Shlomi Fish 2016-01-16 19:45:51 UTC
Thanks for the investigation and the insights. I updated the repository and reported it to clang's bug tracker here:

https://llvm.org/bugs/show_bug.cgi?id=26178
Comment 3 Shlomi Fish 2016-01-16 21:12:21 UTC
Hi! I received this comment on this reported clang ticket - https://llvm.org/bugs/show_bug.cgi?id=26178 :

< quote >

I take it the bug you're reporting is that clang produces this warning when running over the preprocessed output, but does not produce the warning when running over the original code?

That is not itself a bug - Clang's diagnostic system detects the use of macros and uses them as hints to improve warning quality. Clang does not intend to produce the same output on preprocessed and non-preprocessed inputs.

For tools like ccache, you could consider using things like Clang's -frewrite-includes feature which handles the #includes but leaves macros in tact so that Clang's warning infrastructure can still see them. (include based warning behavior - such as suppressing certain warnings in system headers, may still work with -frewrite-includes output, I think (but don't quote me on that), since the file still has line directives to indicate which bits of code came from which header)

< / quote >

and the ticket there was closed. Can I reopen the ticket here (on the ccache bugzilla?)
Comment 4 Joel Rosdahl 2016-01-17 20:06:28 UTC
As noted in the manual, ccache "only works with GCC and compilers that behave similar enough". If Clang doesn't work similar enough to GCC then it's not possible to use Clang with ccache. :-) But it would of course be great if it were possible.

> That is not itself a bug - Clang's diagnostic system detects the use
> of macros and uses them as hints to improve warning quality.

I suspect that it would be possible for Clang to include some special directive in its preprocessed output so that it can avoid emitting warnings like the one discussed when compiling preprocessed input.

> Clang does not intend to produce the same output on preprocessed and
> non-preprocessed inputs.

This standpoint is inherently incompatible with ccache's default (and quickest) settings. I understand if Clang developers would like to duck this issue since it might be hard to implement or maintain, but I would say that it breaks the since long established behavior of GCC-like compilers.

By the way, it's not just ccache that breaks, it's also tools like distcc (in "non-pump" mode at least). Another case I'm coming to think of is that if one wants to report a problem with the compiler, it's handy if it's enough to send just the preprocessed output of some compilation instead of having to include all needed header in the report.

> For tools like ccache, you could consider using things like Clang's
> -frewrite-includes feature which handles the #includes but leaves
> macros in tact so that Clang's warning infrastructure can still see
> them.

ccache would like to stay as compiler-agnostic as possible. It would be possible to let ccache add -frewrite-includes if the compiler is named "clang", but there are at least two problems with that approach:

* It won't work if the compiler for some reason is not called "clang". (Perhaps somebody
  made a wrapper script with another name? Etc.)
* It won't work for clang versions earlier than 3.2 ("won't work" as in "will fail to
  compile", not just "will produce warnings").

Another approach would be to add yet another configuration option for telling ccache to add -frewrite-includes, but since it won't make ccache+Clang work out of the box, I think that it would have very little value.

A third approach could be to introduce compiler detection support in ccache, for instance by running "$compiler --version", parse the output and cache the compiler version in some way. This would probably be the best solution if it's possible to get it robust.

> Can I reopen the ticket here (on the ccache bugzilla?)

You can reopen it if you like, but I would say that it's more of a feature request than a bug. Also, to make anything happen, we (you, me or others) need to come up with a solution on what to do... :-)
Comment 5 Shlomi Fish 2016-01-18 10:39:26 UTC
(In reply to Joel Rosdahl from comment #4)

Thanks for the insights, Joel! I'm not going to reopen this bug for now, but it's sad that there's an incompatibility between ccache and clang.