How to use Clang static analyzer with a Cortex-M project?

Viewed 4152

I'm developing a "bare-metal" C/C++ application for an ARM Cortex-M based MCU. I'd like to incorporate the Clang static analyzer to my build system.

So instead of

arm-none-eabi-g++ ....

I now use

scan-build arm-none-eabi-g++ ...

This seems to work okay, but I get a bunch of messages about the CMSIS header files and the stuff that I got from the chip manufacturer:

  • error: cast from pointer to smaller type 'uint32_t' (aka 'unsigned int') loses information

I agree that they should have used uintptr_t instead of int32_t but can't rewrite their entire code base and the CMSIS headers as well. Can I tell scan-build that pointers on this platform are actually 32-bit so there is no loss of information?

I tried to tell it to consider which platform I use. But if I use scan-build --analyzer-target=arm-none-eabi, I get:

  • fatal error: 'cstring' file not found
  • error: unknown register name 'vfpcc' in asm

Again, in the CMSIS headers.

My questions are:

  • Why can't the analyzer find the cstring header when I use --analyzer-target=arm-none-eabi?
  • How can I tell the analyzer that my pointers are truly 32-bit?
  • Why does it give me that error about that unknown register?

Or alternatively:

  • How can I silence those warnings for the CMSIS headers?

EDIT

I also tried the following suggestion but it didn't work, it resulted in the same errros:

scan-build
    --use-cc=/usr/bin/arm-none-eabi-gcc
    --use-c++=/usr/bin/arm-none-eabi-g++
    --analyzer-target=arm-none-eabi
    arm-none-eabi-g++ ...

Note: I use the qbs build system, and generated the scan-build calls using the cpp.compilerWrapper property in my .qbs file.

A typical command looks like this:

/usr/bin/scan-build --use-cc=/usr/bin/arm-none-eabi-gcc --use-c++=/usr/bin/arm-none-eabi-g++ --analyzer-target=arm-none-eabi /usr/bin/arm-none-eabi-g++ -g -O0 -Wall -Wextra -mcpu=cortex-m4 -mfloat-abi=hard -mthumb -mabi=aapcs -mno-sched-prolog -mabort-on-noreturn -fdata-sections -ffunction-sections -fno-strict-aliasing -fno-builtin -specs=nosys.specs -specs=nano.specs -static -nodefaultlibs -Wdouble-promotion -ggdb -g3 -mfpu=fpv4-sp-d16 -pipe -frandom-seed=0x633bf14c -Wdate-time -fno-exceptions -fno-rtti -fvisibility=default -Wall -Wextra -Wpedantic -Wno-unused-function -DS1_USE_SEGGER_RTT -DEFM32WG940F256 -D__HEAP_SIZE=0 -I/home/Timur/Projects/MyProject/my-software/dependencies/platform/emdrv/common/inc -I/home/Timur/Projects/MyProject/my-software/dependencies/platform/emdrv/config -I/home/Timur/Projects/MyProject/my-software/dependencies/platform/emdrv/dmadrv/inc -I/home/Timur/Projects/MyProject/my-software/dependencies/platform/emdrv/dmadrv/config -I/home/Timur/Projects/MyProject/my-software/dependencies/hardware/kit/common/drivers -I/home/Timur/Projects/MyProject/my-software/dependencies/platform/emdrv/gpiointerrupt/inc -I/home/Timur/Projects/MyProject/my-software/dependencies/platform/emdrv/nvm/inc -I/home/Timur/Projects/MyProject/my-software/dependencies/platform/emdrv/nvm/config -I/home/Timur/Projects/MyProject/my-software/dependencies/platform/emdrv/rtcdrv/inc -I/home/Timur/Projects/MyProject/my-software/dependencies/platform/emdrv/rtcdrv/config -I/home/Timur/Projects/MyProject/my-software/dependencies/platform/emdrv/sleep/inc -I/home/Timur/Projects/MyProject/my-software/dependencies/platform/emdrv/spidrv/inc -I/home/Timur/Projects/MyProject/my-software/dependencies/platform/emdrv/spidrv/config -I/home/Timur/Projects/MyProject/my-software/dependencies/platform/emdrv/uartdrv/inc -I/home/Timur/Projects/MyProject/my-software/dependencies/platform/emdrv/uartdrv/config -I/home/Timur/Projects/MyProject/my-software/dependencies/platform/emdrv/ustimer/inc -I/home/Timur/Projects/MyProject/my-software/dependencies/platform/emdrv/ustimer/config -I/home/Timur/Projects/MyProject/my-software/dependencies/platform/emlib/inc -I/home/Timur/Projects/MyProject/my-software/dependencies/platform/CMSIS/Include -I/home/Timur/Projects/MyProject/my-software/dependencies/platform/Device/SiliconLabs/EFM32WG/Include -I/home/Timur/Projects/MyProject/my-software/dependencies/RTT -std=c++0x -o /home/Timur/Projects/MyProject/build-myproject-my-software-arm_none_eabi-Debug/qtc_arm_none_a793425c-debug/myproject-my-software.qtc-arm-none-a793425c.7e216384/.obj/e6c416981c959a66/efm32-serial-port.cpp.o -c /home/Timur/Projects/MyProject/my-software/source/utilities/hal/efm32-serial-port.cpp
In file included from /home/Timur/Projects/MyProject/my-software/source/utilities/hal/efm32-serial-port.cpp:24:
In file included from /home/Timur/Projects/MyProject/my-software/source/utilities/hal/efm32-serial-port.h:27:
In file included from /home/Timur/Projects/MyProject/my-software/source/utilities/hal/abstract-serial-port.h:32:
/home/Timur/Projects/MyProject/my-software/source/utilities/hal/../core/callback.h:32:10: fatal error: 'cstddef' file not found
#include <cstddef>
         ^~~~~~~~~
1 error generated.
scan-build: Using '/usr/bin/clang-4.0' for static analysis
scan-build: 0 bugs found.
scan-build: The analyzer encountered problems on some source files.
scan-build: Preprocessed versions of these sources were deposited in '/tmp/scan-build-2017-07-27-194505-8969-1/failures'.
scan-build: Please consider submitting a bug report using these files:
scan-build:   http://clang-analyzer.llvm.org/filing_bugs.html
2 Answers

The missing "cstring" is because clang do not include STL headers. I had the same issue and adding -I<path_to_st_includes> fixed it.

So in my QBS I have something like that:

property string repoDir: "C:/Program Files (x86)/Atmel/Studio/7.0/packs"
cpp.includePaths: [
        repoDir + "/arm/CMSIS/4.2.0/CMSIS/Include",
        "C:/Program Files (x86)/Atmel/Studio/7.0/toolchain/arm/arm-gnu-toolchain/arm-none-eabi/include/c++/6.3.1",
        "C:/Program Files (x86)/Atmel/Studio/7.0/toolchain/arm/arm-gnu-toolchain/arm-none-eabi/include"
        ]

For vfpcc it seems to be a problem from clang. The Chromium project even had a fix to remove uses of vfpcc: https://codereview.chromium.org/411803002/

The only solution I have found so far is to disable the hardware FPU for the static analysis.

One way to do it is to use -mfpu=none on clang. But then gcc will complain that none is not valid... And since Qt Creator build the project before the analysis, the build will fail and the analysis will not start.

The other way is to define __SOFTFP__. This will force __FPU_USED to be 0 and disable all the functions that use vfpcc.

Related