Getting started with the LLVM static analyzer

Hello all --

Wrote myself a little C file to try out the static analyzer. (Mac OS X 10.6.4, Xcode 3.2.2, etc)

#include <stdio.h>

int read_ptr ( int * ptr ) {
  int ret = *ptr;
  
  if ( ptr == NULL )
    return -1;
  return ret;
  }

int read_ptr2 ( int *ptr ) {
  int ret;
  if ( ptr != NULL )
    ret = *ptr;
  return ret;
  }

int main ( int argc, char *argv ) {
  int aVal = 12345;
  
  printf ( "12345 = %d\n", read_ptr ( &aVal ));
  printf ( "NULL = %d\n", read_ptr ( NULL ));

  printf ( "12345 = %d\n", read_ptr2 ( &aVal ));
  printf ( "NULL = %d\n", read_ptr2 ( NULL ));
  return 0;
  }
  
Looked at the web page (getting started) <http://clang-analyzer.llvm.org/scan-build.html&gt; saw:
Basic usage of scan-build is designed to be simple: just place the word "scan-build" in front of your build command:

So I tried:

$ /Marshall/Sources/llvm/tools/clang/tools/scan-build/scan-build clang null_check.c

-bash: scan-build: command not found129-46-76-102:mtc-tests marshall$ /Marshall/Sources/llvm/tools/clang/tools/scan-build/scan-build clang null_check.c
scan-build: 'clang' executable not found in '/Marshall/Sources/llvm/tools/clang/tools/scan-build/bin'.
scan-build: Using 'clang' from path: /usr/bin/clang
scan-build: Removing directory '/var/folders/X6/X6xeSru7EZ0ErJlIXsBQxE+++TI/-Tmp-/scan-build-2010-10-13-1' because it contains no reports.

Well, crap - that's not what I wanted; I want to use the clang I just built.

Try again:

$ /Marshall/Sources/llvm/tools/clang/tools/scan-build/scan-build /Marshall/Sources/llvm/Debug+Asserts/bin/clang null_check.c

scan-build: 'clang' executable not found in '/Marshall/Sources/llvm/tools/clang/tools/scan-build/bin'.
scan-build: Using 'clang' from path: /usr/bin/clang
scan-build: Removing directory '/var/folders/X6/X6xeSru7EZ0ErJlIXsBQxE+++TI/-Tmp-/scan-build-2010-10-13-1' because it contains no reports.

Third try: [ I moved /usr/bin to the end of my $PATH, and put /Marshall/Sources/llvm/Debug+Asserts/bin/clang before it. ]

$ /Marshall/Sources/llvm/tools/clang/tools/scan-build/scan-build /Marshall/Sources/llvm/Debug+Asserts/bin/clang null_check.c

scan-build: 'clang' executable not found in '/Marshall/Sources/llvm/tools/clang/tools/scan-build/bin'.
scan-build: Using 'clang' from path: /Marshall/Sources/llvm/Debug+Asserts/bin/clang
scan-build: Removing directory '/var/folders/X6/X6xeSru7EZ0ErJlIXsBQxE+++TI/-Tmp-/scan-build-2010-10-13-1' because it contains no reports.

Does the scan-build tool not work with "naked" clang commands?

So I built a makefile:

CC=/Marshall/Sources/llvm/Debug+Asserts/bin/clang

null_check: null_check.o

clean:
  rm -f null_check null_check.o

and verified that it worked, and tried:

$ /Marshall/Sources/llvm/tools/clang/tools/scan-build/scan-build make

scan-build: 'clang' executable not found in '/Marshall/Sources/llvm/tools/clang/tools/scan-build/bin'.
scan-build: Using 'clang' from path: /usr/bin/clang
/Marshall/Sources/llvm/Debug+Asserts/bin/clang -c -o null_check.o null_check.c
/Marshall/Sources/llvm/Debug+Asserts/bin/clang null_check.o -o null_check
scan-build: Removing directory '/var/folders/X6/X6xeSru7EZ0ErJlIXsBQxE+++TI/-Tmp-/scan-build-2010-10-13-1' because it contains no reports.

So now, I'm using the clang that I want (I think) - but I'm getting no reports. Char's up with that?
What am I missing? (the LLVM and clang were checked out fresh this morning from SVN).

Thanks in advance!

-- Marshall
Qualcomm, Inc.

Hi Marshall,

I just got back from vacation. Comments inline.

Hello all --

Wrote myself a little C file to try out the static analyzer. (Mac OS X 10.6.4, Xcode 3.2.2, etc)

#include <stdio.h>

int read_ptr ( int * ptr ) {
  int ret = *ptr;
  
  if ( ptr == NULL )
    return -1;
  return ret;
  }

int read_ptr2 ( int *ptr ) {
  int ret;
  if ( ptr != NULL )
    ret = *ptr;
  return ret;
  }

int main ( int argc, char *argv ) {
  int aVal = 12345;
  
  printf ( "12345 = %d\n", read_ptr ( &aVal ));
  printf ( "NULL = %d\n", read_ptr ( NULL ));

  printf ( "12345 = %d\n", read_ptr2 ( &aVal ));
  printf ( "NULL = %d\n", read_ptr2 ( NULL ));
  return 0;
  }
  
Looked at the web page (getting started) <http://clang-analyzer.llvm.org/scan-build.html&gt; saw:
Basic usage of scan-build is designed to be simple: just place the word "scan-build" in front of your build command:

So I tried:

$ /Marshall/Sources/llvm/tools/clang/tools/scan-build/scan-build clang null_check.c

-bash: scan-build: command not found129-46-76-102:mtc-tests marshall$ /Marshall/Sources/llvm/tools/clang/tools/scan-build/scan-build clang null_check.c
scan-build: 'clang' executable not found in '/Marshall/Sources/llvm/tools/clang/tools/scan-build/bin'.
scan-build: Using 'clang' from path: /usr/bin/clang
scan-build: Removing directory '/var/folders/X6/X6xeSru7EZ0ErJlIXsBQxE+++TI/-Tmp-/scan-build-2010-10-13-1' because it contains no reports.

Well, crap - that's not what I wanted; I want to use the clang I just built.

Try again:

$ /Marshall/Sources/llvm/tools/clang/tools/scan-build/scan-build /Marshall/Sources/llvm/Debug+Asserts/bin/clang null_check.c

scan-build: 'clang' executable not found in '/Marshall/Sources/llvm/tools/clang/tools/scan-build/bin'.
scan-build: Using 'clang' from path: /usr/bin/clang
scan-build: Removing directory '/var/folders/X6/X6xeSru7EZ0ErJlIXsBQxE+++TI/-Tmp-/scan-build-2010-10-13-1' because it contains no reports.

Third try: [ I moved /usr/bin to the end of my $PATH, and put /Marshall/Sources/llvm/Debug+Asserts/bin/clang before it. ]

$ /Marshall/Sources/llvm/tools/clang/tools/scan-build/scan-build /Marshall/Sources/llvm/Debug+Asserts/bin/clang null_check.c

scan-build: 'clang' executable not found in '/Marshall/Sources/llvm/tools/clang/tools/scan-build/bin'.
scan-build: Using 'clang' from path: /Marshall/Sources/llvm/Debug+Asserts/bin/clang
scan-build: Removing directory '/var/folders/X6/X6xeSru7EZ0ErJlIXsBQxE+++TI/-Tmp-/scan-build-2010-10-13-1' because it contains no reports.

Does the scan-build tool not work with "naked" clang commands?

This is an oversight, now fixed:

http://llvm.org/viewvc/llvm-project?view=rev&revision=116651

So I built a makefile:

CC=/Marshall/Sources/llvm/Debug+Asserts/bin/clang

null_check: null_check.o

clean:
  rm -f null_check null_check.o

and verified that it worked, and tried:

$ /Marshall/Sources/llvm/tools/clang/tools/scan-build/scan-build make

scan-build: 'clang' executable not found in '/Marshall/Sources/llvm/tools/clang/tools/scan-build/bin'.
scan-build: Using 'clang' from path: /usr/bin/clang
/Marshall/Sources/llvm/Debug+Asserts/bin/clang -c -o null_check.o null_check.c
/Marshall/Sources/llvm/Debug+Asserts/bin/clang null_check.o -o null_check
scan-build: Removing directory '/var/folders/X6/X6xeSru7EZ0ErJlIXsBQxE+++TI/-Tmp-/scan-build-2010-10-13-1' because it contains no reports.

So now, I'm using the clang that I want (I think) - but I'm getting no reports. Char's up with that?
What am I missing? (the LLVM and clang were checked out fresh this morning from SVN).

The problem is that scan-build does a poor man's interposition. It overrides the compiler used by your build by setting the environment variable CC to 'ccc-analyzer'. Because your Makefile explicitly sets CC, this interposition doesn't take place. The solution is to omit CC from your Makefile.

This problem is somewhat alluded to in the following section of the scan-build docs:

  http://clang-analyzer.llvm.org/scan-build.html#recommended_autoconf

Because 'configure' generates Makefiles with a hardwired 'CC', one needs to run configure through scan-build in order to interpose the analyzer when one does the actual build.

Note that the analyzer defaults to having your compiler be 'gcc'. To override, make use of scan-build's '--use-cc' option.

The ultimate solution is to one day replace scan-build's build interposition with something more flexible and generic that doesn't require such trickery.