Adding a new checker to the clang static analyzer – Debugging Using LLVM Tools-5

  1. Finally, we need to declare the version of the static analyzer API we are using, which enables the system to determine if the plugin is compatible:
    extern “C” const char clang_analyzerAPIVersionString[] =
    CLANG_ANALYZER_API_VERSION_STRING;

This finishes the implementation of the new checker. To build the plugin, we also need to create a build description in the CMakeLists.txt file which lives in the same directory as IconvChecker.cpp:

  1. Begin by defining the required CMake version and the name of the project:
    cmake_minimum_required(VERSION 3.20.0)
    project(iconvchecker)
  1. Next, include the LLVM files. If CMake can’t find the files automatically, then you have to set the LLVM_DIR variable so that it points to the LLVM directory containing the CMake files:
    find_package(LLVM REQUIRED CONFIG)
  1. Append the LLVM directory with the CMake files to the search path, and include the required modules from LLVM:
    list(APPEND CMAKE_MODULE_PATH ${LLVM_DIR})
    include(AddLLVM)
    include(HandleLLVMOptions)
  1. Then, load the CMake definitions for clang. If CMake can’t find the files automatically, then you have to set the Clang_DIR variable so that it points to the clang directory containing the CMake files:
    find_package(Clang REQUIRED)
  1. Next, append the Clang directory with the CMake files to the search path, and include the required modules from Clang:
    list(APPEND CMAKE_MODULE_PATH ${Clang_DIR})
    include(AddClang)
  1. Then, define where the header files and the library files are located, and which definitions to use:
    include_directories(“${LLVM_INCLUDE_DIR}”
    “${CLANG_INCLUDE_DIRS}”)
    add_definitions(“${LLVM_DEFINITIONS}”)
    link_directories(“${LLVM_LIBRARY_DIR}”)
  1. The previous definitions set up the build environment. Insert the following command, which defines the name of your plugin, the source file(s) of the plugin, and that it is a clang plugin:
    add_llvm_library(IconvChecker MODULE IconvChecker.cpp
    PLUGIN_TOOL clang)
  1. On Windows, the plugin support is different from Unix, and the required LLVM and clang libraries must be linked in. The following code ensures this:
    if(WIN32 OR CYGWIN)
    set(LLVM_LINK_COMPONENTS Support)
    clang_target_link_libraries(IconvChecker PRIVATE
    clangAnalysis
    clangAST
    clangStaticAnalyzerCore
    clangStaticAnalyzerFrontend)
    endif()

Now, we can configure and build the plugin, assuming that the CMAKE_GENERATOR and CMAKE_BUILD_TYPE environment variables are set:
$ cmake -DLLVM_DIR=~/LLVM/llvm-17/lib/cmake/llvm \
-DClang_DIR=~/LLVM/llvm-17/lib/cmake/clang \
-B build
$ cmake –build build

You can test the new checker with the following source saved in the conv.c file, which has two calls to the iconv_close() function:
include
void doconv() {
iconv_t id = iconv_open(“Latin1”, “UTF-16”);
iconv_close(id);
iconv_close(id);
}

To use the plugin with the scan-build script, you need to specify the path to the plugin via the -load-plugin option. A run with the conv.c file looks like:
$ scan-build -load-plugin build/IconvChecker.so clang-17 \
-c conv.c
scan-build: Using ‘/home/kai/LLVM/llvm-17/bin/clang-17’ for static analysis
conv.c:6:3: warning: Closing a previous closed iconv descriptor [unix.IconvChecker]
6 | iconv_close(id);
| ^~~~~~~
1 warning generated.
scan-build: Analysis run complete.
scan-build: 1 bug found.
scan-build: Run ‘scan-view /tmp/scan-build-2023-08-08-114154-12451-1’ to examine bug reports.

With that, you’ve learned how to extend the clang static analyzer with your own checker. You can use this knowledge to either create new general checkers and contribute them to the community or create checkers specifically built for your needs, to raise the quality of your product.
The static analyzer is built by leveraging the clang infrastructure. The next section introduces you to how can build your own plugin extending clang.

Leave a Reply

Your email address will not be published. Required fields are marked *