Menu

handling of #if prerocessor directives

2017-05-22
2017-05-26
  • Robert Schwarzelt

    Hi,

    i am trying to use cppcheck for an embedded C project and encountered a problem, where cppcheck behaves different than gcc. The Project uses drivers from Atmel, which use a lot of preprocessor logic to set defines for chiptype, chipfamily, etc.
    Now cppcheck seems to handle #if conditionals different, than gcc.

    The following simplified (non-) working example ilustrates the problem:

    test.c

    #include <stdio.h>
    #define FOODEF defined(FOO)
    
    int main(void) {
      #if FOODEF
        printf("FOO defined");
      #else
        printf("FOO not defined");
      #endif
      return 0;
    }
    

    preprocessing using gcc gives:

    #> gcc -DFOO -E test.c
    [...]
    # 2 "test.c" 2
    
    int main(void) {
    
        printf("FOO defined");
    
      return 0;
    }
    

    cppcheck does evaluate the "#if FOO" condition as false:

    #> cppcheck -DFOO -E test.c
    Checking /media/sf_vmsf_VM002/test.c ...
    Checking /media/sf_vmsf_VM002/test.c: FOO=1...
    
    int main ( void ) {
    
    printf ( "FOO not defined" ) ;
    
    return 0 ;
    }
    

    Is this a error in cppcheck's preprocessing routines or some kind of undefined behavior?

    Regards
    Robert

     

    Last edit: Robert Schwarzelt 2017-05-23
  • Daniel Marjamäki

    Hello!

    Is this a error in cppcheck's preprocessing routines or some kind of undefined behavior?

    Interesting code. I don't know. But I think we should implement this.

     
    • Robert Schwarzelt

      Hi Daniel,

      i have seen your commit yesterday - works great for the simple example. :)

      unluckily the problem i initally stumbled with (code from atmel) is quite complex and uses string concatenation insde a macro (to build the macro name to check for).

      here is a minimal example, whitch shoud behave different, whether __FOO__ is defined or not:

      #include <stdio.h>
      #define macro(var) (defined(__ ## var ## __))
      
      int main(void) {
        #if macro(FOO)
          printf("__FOO__ defined\r\n");
        #else
          printf("__FOO__ not defined\r\n");
        #endif
      
        return 0;
      }
      

      some real world (atmel) code using this kind of expression:
      https://github.com/ARMmbed/mbed-hal-atmel-common/blob/master/source/utils/parts.h
      below is a short excerpt of what they are doing there.

      #define SAM_PART_IS_DEFINED(part) (defined(__ ## part ## __))
       [...]
      
      /**
       * \name SAM4S series
       * @{
       */
       [...]
      #define SAM4S16 ( \
              SAM_PART_IS_DEFINED(SAM4S16B) || \
              SAM_PART_IS_DEFINED(SAM4S16C) \
              )
      
      /** SAM4S Family */
      #define SAM4S (SAM4S2 || SAM4S4 || SAM4S8 || SAM4S16 || SAM4SA16 || SAM4SD16 || SAM4SD32)
      
      /** SAM product line */
      #define SAM (SAM3S || SAM3U || SAM3N || SAM3XA || SAM4S || SAM4L || SAM4E || \
              SAM0 || SAM4N || SAM4C || SAM4CM || SAM4CP || SAMG)
      

      For example, if we define __SAM4S16C__ (by passing it as commandline paramteter -D__SAM4S16C__). The defines SAM4S16, SAM4S and SAM should all evaluate to 1, so that #if SAM is true.
      The code for other chip families is quite similar.

      I allready tried to solve this myself by extending the code you committed, but got stuck. Seems linke i am missing something about how such function like macros are being handled in simplecpp. Maybe this needs to be done in the macro expansion or evaluation methods?

      It would be great if you could take a look at this or at least point me to the place where this should be implemented.

      Regards
      Robert

       

      Last edit: Robert Schwarzelt 2017-05-29
  • Daniel Marjamäki

    ok please report a new issue in the simplecpp issue tracker.

    if you are interested to investigate this ... please do it. It's probably not very simple. But feel free to take a look at

    https://github.com/danmar/simplecpp/commit/96ade8d9239962fa04702747ce6372b47ec24ef5

    that code should be fixed.

    you might be able to call some function that will preprocess the "defined argument". maybe you can debug and see how expandHashHash is used.

     

Log in to post a comment.