18

I am looking for a free static checker for C99 code (including GCC extensions) with the ability to explicitly say "these preprocessor macros are always defined."

I need that last part because I am compiling embedded code for a single target processor. The compiler (Microchip's C32, GCC based) sets a macro based on the selected processor, which is then used in the PIC32 header files to select a processor-specific header file to include. cppcheck therefore fails because it detects the 30 different #ifdefs used to select one of the many possible PIC32 processors, tries to analyse all possible combinations of these plus all other #defines, and fails.

For example, if splint could process C99 code, I would use

splint -D__PIC32_FEATURE_SET__=460 -D__32MX460F512L__ \
-D__LANGUAGE_C__ -I/path/to/my/includes source.c

An additional problem is that the PIC32 toolchain compiler is called pic32-gcc and not just gcc, although I haven't yet gotten to the point of needing to account for this.

Update #1 - One thing I'm interested in, but is orthogonal to this question, is Eclipse integration (it'd be nice not to have to write a makefile for 30+ compilation units). I asked about this on the Eclipse forums (although the discussion there is more about integration into Eclipse). Nothing groundbreaking.

Update #2 - just tried scan-build from clang, using:

scan-build --use-cc=/usr/local/bin/pic32-gcc make -B -k all

...(also without the --use-cc flag) but all I got was the typical build output, an example of which is:

Building file: ../src/MoreMath.c
Invoking: PIC C32 C Compiler
pic32-gcc -D__DEBUG -I/usr/local/pic32-libs/include -O0 -Wall -c -fmessage-length=0 -std=gnu99 -Werror-implicit-function-declaration -MMD -MP -MF"src/MoreMath.d" -MT"src/MoreMath.d" -mprocessor=32MX460F512L -D__DEBUG -g -o"src/MoreMath.o" "../src/MoreMath.c"
Finished building: ../src/MoreMath.c

...and at the end:

Building target: MyBinary.elf
Invoking: PIC C32 C Linker
pic32-gcc -Wl,-Map,MyBinary.map -mprocessor=32MX460F512L --defsym=__MPLAB_DEBUG=1 -o"MyBinary.elf" <<ALL OF MY *.o FILES HERE>>
Finished building target: MyBinary.elf

scan-build: Removing directory '/tmp/scan-build-2010-06-21-1' because it contains no reports.

So either my code is perfect according to scan-build, or it's not doing anything. I'm not sure what a good test might be to see if it is working.

detly
  • 29,332
  • 18
  • 93
  • 152
  • You should add your stipulation to be used in Eclipse to your question if that is indeed a requirement for your solution. – mbauman Jun 21 '10 at 01:37
  • No, it would be an added bonus. I'll edit the question to make that clearer. I'm still wokring on getting `scan-build` to work with the PIC32 toolchain, and if I do, I'll accept the answer below. – detly Jun 21 '10 at 01:52
  • @Adam Davis - I was going to tweak the question to better emphasise my use of the PIC32 toolchain, but I don't know whether this will interfere with your motivation for putting up a bounty. Let me know if you want me to wait. – detly Jun 21 '10 at 04:58
  • Hi, I don't mean to ask an off-topic question but I am very curious. Why would someone want to program a microchip? What are you building? Thanks.. – the_machinist_ Jun 27 '10 at 23:46
  • The microchip is part of the control system for some electronic devices. They're are almost entirely automatic, so it monitors the conditions via on board sensors (and what few inputs there are), and adjusts various peripherals to maintain certain operational states. – detly Jun 28 '10 at 00:16

6 Answers6

5

Clang's static analyzer should work.

Another option with the source code #defines is that you could run cpp over the source code with some of the preprocessor statements, and then run that resultant code through a static analyzer.

Bill Lynch
  • 80,138
  • 16
  • 128
  • 173
  • I think `scan-build` is about as good as I can get. I'm developing under Eclipse and using the internal builder (ie. no explicit makefile), and I don't think there's any clang integration for the Eclipse CDT. It might be worth switching to a makefile based project. – detly Apr 27 '10 at 05:00
  • Alas, I cannot see a way to get `scan-build` (or any Clang tools) to work with Eclipse. – detly Jun 10 '10 at 02:44
  • 2
    @detly: Why on Earth is a proficient C programmer such as yourself bound to an ungodly abomination such as Eclipse? – Matt Joiner Nov 19 '10 at 16:29
  • @Matt Joiner - what would you recommend? (Besides, I think in this case, it was not Eclipse, but simply that scan-build did not work in the way I expected.) – detly Nov 21 '10 at 02:28
  • http://stackoverflow.com/questions/3528079/which-text-editor-for-ubuntu-should-i-use – Matt Joiner Nov 21 '10 at 04:04
  • @Matt Joiner - As much as I love Geany, it's hardly an IDE. It doesn't do refactoring, autocompletion only works with open files and isn't nearly as smart as Eclipse's, and no error highlighting. It doesn't have a decent colour theme either (zenburn-like) - but neither does Eclipse, so that's nil-both I guess. I used to love Geany, but at the moment I'd use gedit or emacs before it. – detly Nov 21 '10 at 05:20
  • Ah. See I don't like my C to be invaded. I know how to write C I don't need the editor telling me what to do, or confusing the hell out of me with 10000 features. Each to their own, at least you are using the right languages :) – Matt Joiner Nov 21 '10 at 07:19
3

You could just add some code like this to the top of your header that guarantees that it's defined:

#ifndef MACRO_I_NEED
#error "MACRO_I_NEED should be defined"
#define MACRO_I_NEED  // to appease cppcheck
#endif
Adam Rosenfield
  • 390,455
  • 97
  • 512
  • 589
  • 1
    Wouldn't I need to do that for every single source file though? – detly Apr 27 '10 at 04:11
  • 1
    @detly: Not necessarily -- if you have a header file that every file includes (such as a precompiled header), then you can put it at the top of that. – Adam Rosenfield Apr 27 '10 at 18:18
2

Instead of using scan-build with clang, consider swapping out gcc altogether! Clang's C support is stable (and does its best to emulate gcc), and should handle your code just fine.

Try something like make -j3 CC=clang and see what happens!

PS. That syntax might be totally wrong. Haven't used makefiles in ages (CMake is amazing btw).

Clark Gaebel
  • 17,280
  • 20
  • 66
  • 93
  • It doesn't support the `-MT` option, which means I have to rewrite a lot of makefiles. Currently the build uses autodependency files - `.d` files - which contain the header dependencies for each `.o` file. It'll be a while before I can test this. – detly Jun 28 '10 at 02:56
  • @detly, generate the dependency files and chop out their handling (mostly templates, I suppose) in your Makefile)? – vonbrand Feb 02 '13 at 19:45
2

Depending on what actual analyses you want to run on your code, you might take a look at Frama-C. It uses whatever C preprocessor you tell it to, so you can use PIC32's CPP if you want.

porges
  • 30,133
  • 4
  • 83
  • 114
1

This might not directly give you the solution, but you might consider having a look to Coverity, which is a proprietary static syntax analyser, but that is free of charge for OS projects. It should do the job concerning your needs!

Cheers!

1

You can use a tool like sunifdef to partially preprocess the source code according to the assumed defined macros. You'd have to make copies of system and library headers that are affected by those defines and process them as well. Then when doing the static analysis you would specify a different include path pointing to your already processed headers.

Geoff Reedy
  • 34,891
  • 3
  • 56
  • 79