Skip to main content

Clang-tidy

Clang-tidy is an LLVM native C/C++ static code analysis tool that can be used locally and on a build server. It can be integrated in Visual Studio 2019, or run from the command line.

Where to find the tool

Visual Studio 2019 contains Clang which can be included from the Visual Studio Installer. In Visual Studio Installer, choose to modify the Visual Studio installation and choose the optional individual component "Clang compiler for Windows".

LLVM has to be installed in a separate step. Inside Visual Studio 2019, open Settings in the Clang Power Tools toolbar. Open LLVM and download or add the existing LLVM version.

If not using Visual Studio 2019, clang-tidy can be installed with the LLVM installer which can be downloaded from https://releases.llvm.org/download.html . If another installation path than the default C:\Program Files\LLVM is used, manually add the \<misc path\>\LLVM\bin to the environment variable PATH.

Description

The purpose of clang-tidy is to provide an extensible framework for diagnosing and fixing typical programming errors, like style violations, interface misuse, or bugs that can be deduced via static analysis. Clang-tidy is modular and provides a convenient interface for writing new checks.

Clang format is a C++ code formatting tool that can be used to automatically format the code. It is also part of LLVM.

Motivation

Clang-tidy is easy to use with Visual Studio, and the issues can be found during the coding. Clang-tidy supports the C++ standards C++98, C++11, C++14, C++17 and partially C++20, which give a good support for static code analysis on modern C++ code.

It contains a feature for fixing up erroneous code, clang-tidy-fix.

Clang format helps to format the code.

How to analyze the code

In Visual Studio 2019 there is a 'Clang Power Tools' toolbar, with buttons for Tidy, Tidy-Fix, Format, etc. The analysis is made on a single file.

A complete project or Visual Studio solution must be analyzed from the command line.

New and changed code

A Clang-tidy analysis of a product or Visual Studio solution includes new, changed, and old code. Hence, all issues found by the enabled checkers must be handled.

Existing codebase

It is not possible to baseline the existing code base when performing a Clang analysis.

New versions

New versions can be installed using the Visual Studio Installer or LLVM installer.

A tool responsible needs to inspect the release notes to find new and changed checkers, and build locally to inspect the impact on the codebase. The tool responsible can adjust the rules to fit with the current code style, remove rules that cause too many false positives to be useful, or solve the issues in the code.

Also, current deviations can be reviewed to check if the new version might handle the code better for false positives. When the new version works as intended locally, the build servers can be updated with the new version.

Ruleset

Storage

The rule set is stored in one or several configuration files together with the code, e.g. in a git repo. A configuration file placed on the top source code folder of the project covers all code that has no local configuration.

If a local configuration file is placed on the top folder of a part of the code base, all code placed under that folder will use the local configuration file instead. If no local configuration file is found, a traverse up in the folder structure is made to find the closest configuration file.

Version control

One or several configuration files are placed and version-controlled together with the code, .clang-tidy is used for the rules and .clang-format is used for the formatting.

Add/remove rules

Rules (checkers) are modified, added, and removed by changing the .clang-tidy file. The methodology is to enable big scopes/groups like cppcoreguidelines-* (checks related to C++ Core Guidelines) and then to disable specific checkers -cppcoreguidelines-macro-usage (finds macro usage that is considered problematic because better language constructs exist for the task).

Example for disabling one check-in a group in .clang-tidy:

Checks: 'cppcoreguidelines-*, -cppcoreguidelines-macro-usage'

Some checkers have extra settings in the form of key-value-pairs. For example, the number of allowed lines in a function can be set. The actual number of lines can be set as extra information, in this case, value = 108 lines.

Example:

  - key:             readability-function-size.LineThreshold
value: 108

New rule set from new tool version

When a new version of the tool has been provided, the configuration files should be updated with a comment containing the new clang version. The pull request should be reviewed by the code responsible.

Standards

Clang is not compliant with any specific security standards.

Monitoring

When running Clang-tidy in Visual Studio, issues are displayed in the 'Error List' view. When running from the command line, the errors are displayed in the output log. A pull-request in Azure DevOps can be set up with a required Clang-tidy check that blocks the pull-request from completing while there are unhandled clang errors in the code.

Example of the result from a pull-request, with a clang-tidy error:

MyClass.cpp:344:56: error: the parameter 'myString' is copied for each invocation but only used as a const reference; consider making it a const reference [performance-unnecessary-value-param,-warnings-as-errors]
void MyClass::SomeFunction(std::string myString)
^
const &

Severity levels

Clang-tidy has the severity levels: error, warning, and remark. It is recommended to fix errors and warnings, which can be achieved by enabling the clang-tidy build option --warnings-as-errors.

How to handle deviations

Suppressions of Clang-tidy issues are handled as comments in the source code. Either with NOLINT or NOLINTNEXTLINE comments. A descriptive comment on why suppression is needed must be added.

There can be false positives where the code constructs are not understood by the tool. The default action should always be to rewrite the code to mitigate clang-tidy issues. But sometimes it is necessary to deviate and then the suppression is code reviewed like any other change going into the codebase.

Example of how to silent a clang-tidy checker for one function:

  // Silent specified diagnostics as it makes no sense to divide function.
// NOLINTNEXTLINE(readability-function-size)
NcpResult SomeFunction(const std::string& myString)
{
... //too many lines in the function
}

Owner: Software Development Team