Clang-Tidy

If you don’t know what clang-tidy is, read the overview here:

Identifier naming

The readability-identifier-naming check ensures the identifiers matches the coding style of the project. The naming convention can be specified in the .clang-tidy configuration file.

This check is complementary to clang-format but it requires more effort to run as it needs to know the compile options for the file.

Below is a sample configuration demonstrating a few kind of identifiers and some possible values. In this example, classes and structs are CamelCase, variables and functions are lower_case, private members start with m_, etc.

Checks: '-*,readability-identifier-naming'
CheckOptions:
  - { key: readability-identifier-naming.NamespaceCase,       value: lower_case }
  - { key: readability-identifier-naming.ClassCase,           value: CamelCase  }
  - { key: readability-identifier-naming.PrivateMemberPrefix, value: m_         }
  - { key: readability-identifier-naming.StructCase,          value: CamelCase  }
  - { key: readability-identifier-naming.FunctionCase,        value: lower_case }
  - { key: readability-identifier-naming.VariableCase,        value: lower_case }
  - { key: readability-identifier-naming.GlobalConstantCase,  value: UPPER_CASE }

Here is a self-contained example to try clang-tidy out:

mkdir /tmp/tidy-test
cd  /tmp/tidy-test
cat <<'EOF' > test.cpp
class foo
{
public:
  foo() = default;

private:
  int bar_;
};
EOF
clang-tidy -checks='-*,readability-identifier-naming' \
    -config="{CheckOptions: [ {key: readability-identifier-naming.ClassCase, value: CamelCase} ]}" \
    test.cpp -- -std=c++11

CMake integration

Since CMake 3.6 [1], it is possible to run clang-tidy as a part of the build. This can be done on a per-target basis, but if you don’t want to modify the project’s CMakeLists.txt, it is possible to enable clang-tidy for the whole project by using the CMake variable CMAKE_<LANG>_CLANG_TIDY.

Please note that, clang-tidy arguments should be a CMake list, each argument separated by ; on the command line.

To use clang-tidy on a C++ project, type:

mkdir tidy-build
cd tidy-build
CC=clang CXX=clang++ cmake \
    -DCMAKE_CXX_CLANG_TIDY="clang-tidy;-warnings-as-errors=*;-header-filter=$(realpath ..)" \
    ..
make -k

This invocation is made uses -warnings-as-errors=*, this can be useful for continuous integration systems. The return code of clang-tidy is handled since CMake 3.8 [2], so this won’t work with the CMake 3.6 and 3.7 series.

What’s wrong with the CMake integration?

  • Constant overhead for compilation in developement.

    For developement linting is nice before committing, but not necessarily when iterating on the code.

  • If you want to modernize/fix your code, you need another way to run clang-tidy anyway.

    Clang has two scripts for example:

    1. run-clang-tidy.py: useful to run clang-tidy on a compilation database
    2. clang-tidy-diff.py: useful to run clang-tidy on a diff output

    CMake is still useful to generate the compilation database the tool runs on.

  • No way to force colors.

    This may actually be a missing feature in clang-tidy, which lacks something like -fdiagnostic-colors.

Todo

Footnotes

[1]https://cmake.org/cmake/help/v3.6/release/3.6.html
[2]https://cmake.org/cmake/help/v3.8/release/3.8.html