Menu

format types missmatch between newlib and cppcheck

2017-08-28
2017-09-16
  • Robert Schwarzelt

    Hi together,

    i am using cppcheck in a embedded c project targeting an arm microcontroller (Cortex-M4). The used compiler is a standard arm-none-eabi-gcc, as found in Debian package repository. Standrard library is provided by newlib (headers are not included, when running cppcheck).

    so i set up the following platform to define data types - please note int and long are of same width :

    <?xml version="1"?>
    <platform>
      <char_bit>8</char_bit>
      <default-sign>unsigned</default-sign>
      <sizeof>
        <short>2</short>
        <int>4</int>
        <long>4</long>
        <long-long>8</long-long>
        <float>4</float>
        <double>8</double>
        <long-double>8</long-double>
        <pointer>4</pointer>
        <size_t>4</size_t>
        <wchar_t>4</wchar_t>
      </sizeof>
    </platform>
    

    when checking the folliwing code:

    #include <stdio.h>
    #include <stdint.h>
    #include <inttypes.h>
    int main (void) {
      printf("test1:  %ld\r\n",(int32_t) 5);
      return 0;
    }
    

    i get:

    #>cppcheck --std=c99 --platform=platform.xml --enable=all test.c
    Checking test.c ...
    [test.c:5]: (warning) %ld in format string (no. 1) requires 'long' but the argument type is 'signed int'.
    (information) Cppcheck cannot find all the include files (use --check-config for details)
    

    As int and long are 4 Bytes each, the compiler is happy with both types. Interestingly the toolchain defines the PRId32 macro as ld (found in inttypes.h). So it expects us to use ld to print a variable of type int32_t.
    This means cppcheck wants me to use a different type, than recomended by the toolchain. Is there a way to work around this (cppcheck library, etc.)?

    by the way: cppcheck does not understand the PRI* and SCN* macros defined in inttypes.h (not covered by std.cfg). Sure, i can extend the library, but this wouldn't be very portable.

    Regards Robert

     
  • Daniel Marjamäki

    Replacing PRId32 with %ld is not a good idea for Cppcheck.

    I am not very familiar about how it's used.. I hope I got it right here below...

    I can see testcases where we handle PRId64. But I don't see how it is handled in the checkers.

    Cppcheck does handle I32. As far as I know it's an MS extension. This piece of code seems to work as expected as far as I see..

    #define PRId32   "I32u"
    int main (void) {
        printf("test1:  %" PRId32 "\r\n", (uint32_t)x);
        return 0;
    }
    

    Cppcheck does not warn about it however if you change the cast type you will see warnings.

    So would it work correctly if we added something like this in std.cfg?

    <define name="PRId32" value="I32u"/>
    

    Or do we need some better handling for PRId32 in the checker?

     
  • Robert Schwarzelt

    Replacing PRId32 with %ld is not a good idea for Cppcheck.

    Well this is exactly what my toolchain is doing during comiplation (PRId32 definition from standard header inttypes.h).

    I Think we have two problems here:
    1) cppcheck seems not to understand PRI... and SCN... Makros. This might be fixable by including system headers in the analysis (did not try this so far) or adding the definitions in a library. As the needed definitions might vary (depending on the used data model, processor width, etc.) std.cfg seems to be no good place to do this. I am ok with adding those definitions to my custom lib.

    2) PRId32 is defined as ld on my platform (standard header inttypes.h). So the toolchain expects me to print out int32_t variables using the %ld format-type. Now cppcheck will complain about a format-type missmatch, as it interprets int32_t as type int. I think this is a false positive and might be caused by int and long having the same width on this platform.

    BTW: is it possible to include additional include search paths (for system headers) in the analysis, while using project based checking (cmake compile database)?

     

    Last edit: Robert Schwarzelt 2017-09-07
  • Daniel Marjamäki

    you should not include the standard headers in cppcheck analysis. They are not designed for proper analysis.

    adding handling of PRI/SCN to cppcheck sounds good.

    As the needed definitions might vary

    not sure what you mean.. doesn't PRId32 => "I32d" work always?

    converting it to %ld is wrong on all platforms from cppcheck perspective.

    I think this is a false positive and might be caused by int and long having the same width on this platform.

    Cppcheck is pedantic. I think the message should be splitted so it just complains about portability problems when the type size match.

    So you will get (warning) if the type sizes mismatch. and (portability) if the type sizes match.

    Then you can easily suppress or disable the portability results if you don't like those. and keep the warnings about "real bugs".

    I have wanted to split it this way for years .. but never get the time.. so if anybody wants to do this feel free to do it.

     

    Last edit: Daniel Marjamäki 2017-09-08
  • Robert Reif

    Robert Reif - 2017-09-16

    Adding a typedef for uint32_t fixes the problem.

    I copy the system stdint.h and inttypes.h header files to a special directory and simplify them so thay are correct for my platform. I then add that path to the command line so they are used.

    You can probably use the system headers directly for C if you also add the special defines needed for your platform but it is tricky to set up and will make checking take a LOT longer.

     

Log in to post a comment.

Want the latest updates on software, tech news, and AI?
Get latest updates about software, tech news, and AI from SourceForge directly in your inbox once a month.