Using the clang static analyzer under Linux

A couple months ago I used the clang static analyzer on my MacBook. At that time the tool still yielded many false positives. Today I decided to try to get it running on my Linux laptop, mainly so I can run it on some of the source code I have stored there.

The static analyzer is available as a binary package for MacOSX, but if you are on a different platform you have to compile it manually. That was not a problem and the source compiled cleanly. Just follow the instructions and you'll be fine.

When I first tried to analyze a bigger project, it failed because clang couldn't find the stddef.h header. But because my system had about four versions in different directories, it wasn't easy to find out which one was the correct. The obvious choice to me was to add /usr/include/linux to the header search path, but that didn't work and clang failed with even more errors. After a bit googling I found out that it needs the file from the gcc compiler. On my gentoo box it is stored under /usr/lib/gcc/x86_64-pc-linux-gnu/4.4.2/include. In case you don't know your chost and gcc version, you can use this command to automatically determine the path: /usr/lib/gcc/$(gcc -dumpmachine)/$(gcc -dumpversion)/include. In the end, I had to add these two paths to CFLAGS:

  • /usr/lib/gcc/$(gcc -dumpmachine)/$(gcc -dumpversion)/include (stddef.h and friends)
  • /usr/lib/gcc/$(gcc -dumpmachine)/$(gcc -dumpversion)/include-fixed (limit.h)

After that I was able to successfully analyze transmission, the X.org xserver and git. I also tried the linux kernel, but it uses way too much black magic for clang to handle.

Notes

You have to wrap both the configure script and make with scan-build. Otherwise make might not pick up the correct compiler:

$ scan-build ./configure
$ scan-build make

Interestingly enough, even some of the conf tests have bugs in them. In the xserver configure script were mostly dead assignments or increments, but one dereference of an undefined pointer which looks genuine. I wouldn't worry too much about that though.

When analyzing transmission, I hit a bug in ccc-analyzer (a perl wrapper script around clang-cc):

$ touch test.c
$ scan-build gcc -c -DFOO=\"bar\ baz\" test.c
gcc: baz": No such file or directory
<command-line>: warning: missing terminating " character

The wrapper script seems to have issues with the quoting around the FOO define. My perl fu is very limited, so instead of fixing the script, I fixed the configure script to not emit such defines. The particular define, PACKAGE_STRING, comes from autoconf, so all projects which use autoconf and set PACKAGE_STRING on the compiler commandline may run into this issue. I suggest putting these defines into config.h instead of the commandline.

I strongly suggest you to compile the release build of clang. The debug version, which is the default when you run ./configure, can be up to ten times slower than the optimized build:

$ ./configure --enable-optimized