views:

231

answers:

2

Does anyone have experience with Sparse? I seem unable to find any documentation, so the warnings and errors it produces are unclear to me. I tried checking the mailing list and man page but there really isn't much in either.

For instance, I use INT_MAX in one of my files. This generates an error (undefined identifier) even though I #include limits.h.

Is there any place where the errors and warnings have been explained?

+1  A: 

If you look at limits.h you'll see that INT_MAX is defined inside this #if

/* If we are not using GNU CC we have to define all the symbols ourself.
 Otherwise use gcc's definitions (see below).  */
#if !defined __GNUC__ || __GNUC__ < 2

so to get it to work you should undefine __GNUC__ before including limits.h

Puppe
Actually it doesn't look like that in my limits.h. There is no #ifdef and INT_MAX is set to __INT_MAX__. That's at least the include KDevelop offers. But I think I skip splint as per tinkertim's explanation. I'll give him the "correct answer" because he explained the concept, even though your answer is correct, too.
Makis
+2  A: 

Sparse isn't intended to be a lint, per say. Sparse is intended to produce a parse tree of arbitrary code so that it can be further analyzed.

In your example, you either want to define GNU_SOURCE (which I believe turns on __GNUC__), which exposes the bits you need in limits.h

I would avoid defining __GNUC__ on its own, as several things it activates might behave in an undefined way without all of the other switches that GNU_SOURCE turns on being defined.

My point isn't to help you squash error by error, its to reiterate that sparse is mostly used as a library, not as a stand alone static analysis tool.

From my copy of the README (not sure if I have the current version) :

This means that a user of the library will literally just need to do

  struct string_list *filelist = NULL;
  char *file;

  action(sparse_initialize(argc, argv, filelist));

  FOR_EACH_PTR_NOTAG(filelist, file) {
    action(sparse(file));
  } END_FOR_EACH_PTR_NOTAG(file);

and he is now done - having a full C parse of the file he opened.  The
library doesn't need any more setup, and once done does not impose any
more requirements.  The user is free to do whatever he wants with the
parse tree that got built up, and needs not worry about the library ever
again.  There is no extra state, there are no parser callbacks, there is
only the parse tree that is described by the header files. The action
funtion takes a pointer to a symbol_list and does whatever it likes with it.

The library also contains (as an example user) a few clients that do the
preprocessing, parsing and type evaluation and just print out the
results.  These clients were done to verify and debug the library, and
also as trivial examples of what you can do with the parse tree once it
is formed, so that users can see how the tree is organized.

The included clients are more 'functional test suites and examples' than anything. Its a very useful tool, but you might consider another usage angle if you want to employ it. I like it because it doesn't use *lex / bison , which makes it remarkably easier to hack.

Tim Post
OK, I think I'll stick with splint then. Thanks for explaining this, though.
Makis