4

I'm trying to use Clang static analyzer on a very simple program:

#include <stdio.h>
main ()
{
    printf("Hello, world !");
}

When i do

clang helloworld.c

It compiles the program successfully.


When i do

clang -cc1 -analyze -analyzer-checker=unix helloworld.c

it raises an error:

helloworld.c:1:10: fatal error: 'stdio.h' file not found
#include <stdio.h>
         ^
1 error generated.

clang --analyze -Xanalyzer -analyzer-checker=unix helloworld.c

doesn't print anything.


What is the problem and how can i fix it? I assume static analyzer doesn't see the header files though the compiler can use them. Please, help me.

evocatus
  • 111
  • 1
  • 2
  • 8
  • I'm running Debian 8, gcc 4.7.4, clang 3.4.1 – evocatus Jun 07 '16 at 08:42
  • looks like the last code chunk (using clang driver) runs correctly - i have tested it on a buggy code from here: http://stackoverflow.com/a/3486939/1301604 – evocatus Jun 07 '16 at 08:56

2 Answers2

4

Sometimes the checker is not able to read the default include path. So you might want to pass it as an argument. You can find the exact include path clang looks at using this command:

clang -E -x c - -v < /dev/null

and then your final query will become:

clang -I<path to include> --analyze -Xanalyzer -analyzer-checker=unix helloworld.c
Nishant Sharma
  • 683
  • 9
  • 16
0

Solution using -cc1 flag:

See what include paths the clang is receiving. The flag -v is the key option. The quick way of using it is the following (as given by @Nishant) along with the sample include paths it prints,

$ clang -E -x c - -v < /dev/null
...
#include <...> search starts here:
/usr/local/include
/home/codeman/.itsoflife/local/packages-live/llvm-clang6/build/lib/clang/6.0.1/include
/usr/include/x86_64-linux-gnu
/usr/include
...

On my machine, the simple use of the following command works seamlessly,

$ clang --analyze -Xanalyzer -analyzer-checker=debug.DumpCFG main.c

however the following form fails, as you pointed,

$ clang -cc1 -analyze -analyzer-checker=debug.DumpCFG main.c

For this second command (with -cc1) you can create an environment variable say MY_INCLUDES with the necessary includes. Paste the code below (with necessary include paths as per your system) into ~/.bashrc or ~/.zshrc depending on if you are using bash or zsh. (don't forget to source ~/.bashrc or source ~/.zshrc)

export MY_INCLUDES="-I/usr/local/include -I/home/codeman/.itsoflife/local/packages-live/llvm-clang6/build/lib/clang/6.0.1/include -I/usr/include/x86_64-linux-gnu -I/usr/include"

Now on bash use,

$ clang -cc1 $MY_INCLUDES -analyze -analyzer-checker=debug.DumpCFG main.c

on zsh use,

$ clang -cc1 ${=MY_INCLUDES} -analyze -analyzer-checker=debug.DumpCFG main.c

Note the use of MY_INCLUDES after -cc1 but before the main.c file. Moreover, on zsh one has to use the = prefix with the env variable or else its considered a single string (for details see this answer).

codeman48
  • 1,330
  • 11
  • 17