Cppcheck reports

    From The Document Foundation Wiki


    This page documents how to generate cppcheck reports in the form of a browseable tree of sources files.

    What's cppcheck

    Cppcheck is an open source static code analyzer tool for C/C++ programming languages. So its goal is to detect some bugs (other than syntax errors).

    Example results

    Example generated results can be found here: https://dev-builds.libreoffice.org/cppcheck_reports/

    Generated by this script: https://git.libreoffice.org/dev-tools/+/master/cppcheck/cppcheck-report.sh

    Preparation

    Retrieve LibreOffice sources

    Retrieve LibreOffice sources in a <LO sources> directory with this command:

    $ git clone https://gerrit.libreoffice.org/core libreoffice

    (see Development/Native Build for more details)

    Retrieve and build cppcheck sources

    You can install cppcheck from distribution packages but it's better to retrieve last sources with git since there are improvements everyday. So choose and go into <cppcheck directory> then run these commands to retrieve sources and build cppcheck:

    $ git clone https://github.com/danmar/cppcheck.git
    $ cd cppcheck
    $ make

    Building takes less than a minute, but it can be sped up with -j4 make option.

    Finally install python-pygments required by cppcheck-htmlreport report builder.

    Generate reports

    To summarize, you've got to generate an xml file containing all the warnings/errors detected by cppcheck. Then you must launch a script to generate a browseable tree from the xml file + LibreOffice sources. Cppcheck allows a lot of options but here are some simple steps: - go to <LO sources> directory - create a file named "cppcheck_supp.txt" which contains only unusedFunction - run this command to launch cppcheck detection:

    $ <cppcheck directory>/cppcheck  -i external/ -i workdir/ --xml --suppressions-list=cppcheck_supp.txt --enable=all --max-configs=25 ./ 2> ./err.xml

    (-i option allows to remove some directories to check, --suppressions-list allows to disable some types of detection, --enable=all allows to detect every types of detections, removing it allows to have only errors) Notice that on i5 with 6Gb, it takes several hours to have the result, however the -j and -l options can be used to run jobs in parallel to greatly speed it up on larger machines.

    - run this command to generate the browseable tree:

    $ <cppcheck directory>/htmlreport/cppcheck-htmlreport  --file=err.xml --title=LibreOffice --report-dir=cppcheck_reports --source-dir=.

    You'll get a new directory called cppcheck_reports in your LO sources. The main page to browse in it is index.html With the configuration mentioned above, this part only takes a few minutes.

    Future Work

    Checking cppcheck's configuration

    The above starter example reports ~9000 errors, nearly all of which are false positives. To see why you can add the --check-config parameter to analyse includes. The resulting report shows that cppcheck cannot find any of our header files.

    Include paths

    Headers can be included 2 ways

    1) -I include/ Adding this parameter alone, eliminates ~ 1 thousand false positives, but it leaves out all of the headers in inc/

    2) --includes-file=inc.txt with something like this: find . -type d \( -name "inc" -o -name "include" \) |sort > inc.txt

    Teaching cppcheck about all of our header locations drops the number of errors found from 7K to a few hundred. However it also creates 2 new problems: speed and ~10K "toomanyconfigs" warnings. This may be fixed switching to project files to teach cppcheck about include folders and preprocessor defines.

    Defines

    An example of 2 configurations defined by A is this:

    #ifdef A
        x = y;
    #else
        x = z;
    #endif

    By default cppcheck will check all preprocessor configurations (except those that have #error in them). So the above code will be analyzed both when A is defined and when it is not

    We can speed things up by not checking our DEBUG configurations. We can also eliminate even more false positives by not checking configurations that are missing the system header files. For example on Linux, we should add -U_WIN32 to not check Windows configs.

    Here is the result of my tweaking:

    $ cppcheck -DNDEBUG -U_WIN32 -i external/ -i workdir/ --includes-file=inc.txt --xml --suppressions-list=cppcheck_supp.txt --enable=all --max-configs=100  ./  2> ./err.xml

    This command is not perfect, but it greatly improved the signal-to-noise ratio, only showing a few hundred errors. The run time went from about from approx. 2 hours to 8, but I'm sure that can be by further by reducing the number of configurations checked (-D and -U).

    Project Files

    In Windows, you can generate a `LibreOffice.sln` to eliminate the need to configure anything.

    $ ../cppcheck/bin/cppcheck -j 4 --xml --enable=style --project=LibreOffice.sln --cppcheck-build-dir=cppcheck-tmp 2> ./e
    rr.xml

    The problem with this route is that it only tests the Windows configuration and is very slow.

    After you run any IDE integration, you'll find in workdir/GbuildToJson/Executable/soffice.bin

       "DEFS": "-DBOOST_ERROR_CODE_HEADER_ONLY -DBOOST_SYSTEM_NO_DEPRECATED -DCPPU_ENV=gcc3 -DLINUX -DNDEBUG -DOSL_DEBUG_LEVEL=0 -DUNIX -DUNX -DX86_64 -D_PTHREADS -D_REENTRANT ",
       "INCLUDE": "-I/core/include  -I/usr/lib/jvm/java-11-openjdk-amd64/include -I/usr/lib/jvm/java-11-openjdk-amd64/include/linux -I/core/config_host  -I/core/desktop/source/inc ", 
    


    These configurations and include paths could be passed to cppcheck.

    All of these commands are explained in detail on the cppcheck manual: http://cppcheck.sourceforge.net/manual.pdf

    Gotchas

    • cppcheck doesn't understand libreoffice's overloading of a >>= b as an assignment to b, and gets confused in many cases thinking that b hasn't been assigned or has the same value as previously assigned.