Clang-Tidy

另请参阅

clang-tidy 是一个基于 clang 的 C++ “代码风格检查器” 工具。它的目的是提供一个可扩展的框架来诊断和修复常见的编程错误,例如代码风格违反、接口误用或可以通过静态分析推断出的错误。clang-tidy 是模块化的,并为编写新的检查提供了方便的接口。

使用 clang-tidy

clang-tidy 是一个基于 LibTooling 的工具,如果您为您的项目设置了编译命令数据库,它将更容易使用(有关如何执行此操作的示例,请参阅 如何为 LLVM 设置工具)。您也可以在 -- 之后在命令行中指定编译选项

$ clang-tidy test.cpp -- -Imy_project/include -DMY_DEFINES ...

clang-tidy 有自己的检查,也可以运行 Clang 静态分析器检查。每个检查都有一个名称,可以使用 -checks= 选项选择要运行的检查,该选项指定一个以逗号分隔的正负(以 - 为前缀)通配符列表。正通配符添加检查子集,负通配符删除它们。例如,

$ clang-tidy test.cpp -checks=-*,clang-analyzer-*,-clang-analyzer-cplusplus*

将禁用所有默认检查 (-*) 并启用所有 clang-analyzer-* 检查,除了 clang-analyzer-cplusplus* 检查。

-list-checks 选项列出所有启用的检查。在没有 -checks= 的情况下使用时,它将显示默认启用的检查。使用 -checks=* 查看所有可用检查,或者使用 -checks= 的任何其他值查看此值启用了哪些检查。

目前有以下几组检查

名称前缀

描述

abseil-

与 Abseil 库相关的检查。

altera-

与用于 FPGA 的 OpenCL 编程相关的检查。

android-

与 Android 相关的检查。

boost-

与 Boost 库相关的检查。

bugprone-

针对容易出现错误的代码结构的检查。

cert-

与 CERT 安全编码指南相关的检查。

clang-analyzer-

Clang 静态分析器检查。

concurrency-

与并发编程(包括线程、纤程、协程等)相关的检查。

cppcoreguidelines-

与 C++ 核心指南相关的检查。

darwin-

与 Darwin 代码约定相关的检查。

fuchsia-

与 Fuchsia 代码约定相关的检查。

google-

与 Google 代码约定相关的检查。

hicpp-

与高完整性 C++ 编码标准相关的检查。

linuxkernel-

与 Linux 内核代码约定相关的检查。

llvm-

与 LLVM 代码约定相关的检查。

llvmlibc-

与 LLVM-libc 代码标准相关的检查。

misc-

我们没有更好的分类的检查。

modernize-

倡导使用现代(目前“现代”是指“C++11”)语言结构的检查。

mpi-

与 MPI(消息传递接口)相关的检查。

objc-

与 Objective-C 代码约定相关的检查。

openmp-

与 OpenMP API 相关的检查。

performance-

针对性能相关问题的检查。

portability-

针对与任何特定代码风格无关的移植性相关问题的检查。

readability-

针对与任何特定代码风格无关的可读性相关问题的检查。

zircon-

与 Zircon 内核代码约定相关的检查。

Clang 诊断以类似于检查诊断的方式处理。Clang 诊断由 clang-tidy 显示,可以使用 -checks= 选项过滤掉。但是,-checks= 选项不会影响编译参数,因此它无法打开构建配置中尚未打开的 Clang 警告。 -warnings-as-errors= 选项将 -checks= 标志下发出的任何警告升级为错误(但它本身不会启用任何检查)。

Clang 诊断的检查名称以 clang-diagnostic- 开头。具有对应警告选项的诊断命名为 clang-diagnostic-<warning-option>,例如,由 -Wliteral-conversion 控制的 Clang 警告将以检查名称 clang-diagnostic-literal-conversion 报告。

-fix 标志指示 clang-tidy 在对应检查支持的情况下修复发现的错误。

所有命令行选项的概述

$ clang-tidy --help
USAGE: clang-tidy [options] <source0> [... <sourceN>]

OPTIONS:

Generic Options:

  --help                           - Display available options (--help-hidden for more)
  --help-list                      - Display list of available options (--help-list-hidden for more)
  --version                        - Display the version of this program

clang-tidy options:

  --checks=<string>                - Comma-separated list of globs with optional '-'
                                     prefix. Globs are processed in order of
                                     appearance in the list. Globs without '-'
                                     prefix add checks with matching names to the
                                     set, globs with the '-' prefix remove checks
                                     with matching names from the set of enabled
                                     checks. This option's value is appended to the
                                     value of the 'Checks' option in .clang-tidy
                                     file, if any.
  --config=<string>                - Specifies a configuration in YAML/JSON format:
                                       -config="{Checks: '*',
                                                 CheckOptions: {x: y}}"
                                     When the value is empty, clang-tidy will
                                     attempt to find a file named .clang-tidy for
                                     each source file in its parent directories.
  --config-file=<string>           - Specify the path of .clang-tidy or custom config file:
                                      e.g. --config-file=/some/path/myTidyConfigFile
                                     This option internally works exactly the same way as
                                      --config option after reading specified config file.
                                     Use either --config-file or --config, not both.
  --dump-config                    - Dumps configuration in the YAML format to
                                     stdout. This option can be used along with a
                                     file name (and '--' if the file is outside of a
                                     project with configured compilation database).
                                     The configuration used for this file will be
                                     printed.
                                     Use along with -checks=* to include
                                     configuration of all checks.
  --enable-check-profile           - Enable per-check timing profiles, and print a
                                     report to stderr.
  --enable-module-headers-parsing  - Enables preprocessor-level module header parsing
                                     for C++20 and above, empowering specific checks
                                     to detect macro definitions within modules. This
                                     feature may cause performance and parsing issues
                                     and is therefore considered experimental.
  --exclude-header-filter=<string> - Regular expression matching the names of the
                                     headers to exclude diagnostics from. Diagnostics
                                     from the main file of each translation unit are
                                     always displayed.
                                     Must be used together with --header-filter.
                                     Can be used together with -line-filter.
                                     This option overrides the 'ExcludeHeaderFilterRegex'
                                     option in .clang-tidy file, if any.
  --explain-config                 - For each enabled check explains, where it is
                                     enabled, i.e. in clang-tidy binary, command
                                     line or a specific configuration file.
  --export-fixes=<filename>        - YAML file to store suggested fixes in. The
                                     stored fixes can be applied to the input source
                                     code with clang-apply-replacements.
  --extra-arg=<string>             - Additional argument to append to the compiler command line
  --extra-arg-before=<string>      - Additional argument to prepend to the compiler command line
  --fix                            - Apply suggested fixes. Without -fix-errors
                                     clang-tidy will bail out if any compilation
                                     errors were found.
  --fix-errors                     - Apply suggested fixes even if compilation
                                     errors were found. If compiler errors have
                                     attached fix-its, clang-tidy will apply them as
                                     well.
  --fix-notes                      - If a warning has no fix, but a single fix can
                                     be found through an associated diagnostic note,
                                     apply the fix.
                                     Specifying this flag will implicitly enable the
                                     '--fix' flag.
  --format-style=<string>          - Style for formatting code around applied fixes:
                                       - 'none' (default) turns off formatting
                                       - 'file' (literally 'file', not a placeholder)
                                         uses .clang-format file in the closest parent
                                         directory
                                       - '{ <json> }' specifies options inline, e.g.
                                         -format-style='{BasedOnStyle: llvm, IndentWidth: 8}'
                                       - 'llvm', 'google', 'webkit', 'mozilla'
                                     See clang-format documentation for the up-to-date
                                     information about formatting styles and options.
                                     This option overrides the 'FormatStyle` option in
                                     .clang-tidy file, if any.
  --header-filter=<string>         - Regular expression matching the names of the
                                     headers to output diagnostics from. Diagnostics
                                     from the main file of each translation unit are
                                     always displayed.
                                     Can be used together with -line-filter.
                                     This option overrides the 'HeaderFilterRegex'
                                     option in .clang-tidy file, if any.
  --line-filter=<string>           - List of files with line ranges to filter the
                                     warnings. Can be used together with
                                     -header-filter. The format of the list is a
                                     JSON array of objects:
                                       [
                                         {"name":"file1.cpp","lines":[[1,3],[5,7]]},
                                         {"name":"file2.h"}
                                       ]
  --list-checks                    - List all enabled checks and exit. Use with
                                     -checks=* to list all available checks.
  --load=<pluginfilename>          - Load the specified plugin
  -p <string>                      - Build path
  --quiet                          - Run clang-tidy in quiet mode. This suppresses
                                     printing statistics about ignored warnings and
                                     warnings treated as errors if the respective
                                     options are specified.
  --store-check-profile=<prefix>   - By default reports are printed in tabulated
                                     format to stderr. When this option is passed,
                                     these per-TU profiles are instead stored as JSON.
  --system-headers                 - Display the errors from system headers.
                                     This option overrides the 'SystemHeaders' option
                                     in .clang-tidy file, if any.
  --use-color                      - Use colors in diagnostics. If not set, colors
                                     will be used if the terminal connected to
                                     standard output supports colors.
                                     This option overrides the 'UseColor' option in
                                     .clang-tidy file, if any.
  --verify-config                  - Check the config files to ensure each check and
                                     option is recognized.
  --vfsoverlay=<filename>          - Overlay the virtual filesystem described by file
                                     over the real file system.
  --warnings-as-errors=<string>    - Upgrades warnings to errors. Same format as
                                     '-checks'.
                                     This option's value is appended to the value of
                                     the 'WarningsAsErrors' option in .clang-tidy
                                     file, if any.
  --allow-no-checks                - Allow empty enabled checks. This suppresses
                                     the "no checks enabled" error when disabling
                                     all of the checks.

-p <build-path> is used to read a compile command database.

  For example, it can be a CMake build directory in which a file named
  compile_commands.json exists (use -DCMAKE_EXPORT_COMPILE_COMMANDS=ON
  CMake option to get this output). When no build path is specified,
  a search for compile_commands.json will be attempted through all
  parent paths of the first input file . See:
  https://clang.llvm.net.cn/docs/HowToSetupToolingForLLVM.html for an
  example of setting up Clang Tooling on a source tree.

<source0> ... specify the paths of source files. These paths are
  looked up in the compile command database. If the path of a file is
  absolute, it needs to point into CMake's source tree. If the path is
  relative, the current working directory needs to be in the CMake
  source tree and the file must be in a subdirectory of the current
  working directory. "./" prefixes in the relative files will be
  automatically removed, but the rest of a relative path must be a
  suffix of a path in the compile command database.


Configuration files:
  clang-tidy attempts to read configuration for each source file from a
  .clang-tidy file located in the closest parent directory of the source
  file. The .clang-tidy file is specified in YAML format. If any configuration
  options have a corresponding command-line option, command-line option takes
  precedence.

  The following configuration options may be used in a .clang-tidy file:

  CheckOptions                 - List of key-value pairs defining check-specific
                                 options. Example:
                                   CheckOptions:
                                     some-check.SomeOption: 'some value'
  Checks                       - Same as '--checks'. Additionally, the list of
                                 globs can be specified as a list instead of a
                                 string.
  ExcludeHeaderFilterRegex     - Same as '--exclude-header-filter'.
  ExtraArgs                    - Same as '--extra-args'.
  ExtraArgsBefore              - Same as '--extra-args-before'.
  FormatStyle                  - Same as '--format-style'.
  HeaderFileExtensions         - File extensions to consider to determine if a
                                 given diagnostic is located in a header file.
  HeaderFilterRegex            - Same as '--header-filter'.
  ImplementationFileExtensions - File extensions to consider to determine if a
                                 given diagnostic is located in an
                                 implementation file.
  InheritParentConfig          - If this option is true in a config file, the
                                 configuration file in the parent directory
                                 (if any exists) will be taken and the current
                                 config file will be applied on top of the
                                 parent one.
  SystemHeaders                - Same as '--system-headers'.
  UseColor                     - Same as '--use-color'.
  User                         - Specifies the name or e-mail of the user
                                 running clang-tidy. This option is used, for
                                 example, to place the correct user name in
                                 TODO() comments in the relevant check.
  WarningsAsErrors             - Same as '--warnings-as-errors'.

  The effective configuration can be inspected using --dump-config:

    $ clang-tidy --dump-config
    ---
    Checks:              '-*,some-check'
    WarningsAsErrors:    ''
    HeaderFileExtensions:         ['', 'h','hh','hpp','hxx']
    ImplementationFileExtensions: ['c','cc','cpp','cxx']
    HeaderFilterRegex:   ''
    FormatStyle:         none
    InheritParentConfig: true
    User:                user
    CheckOptions:
      some-check.SomeOption: 'some value'
    ...

抑制不需要的诊断

clang-tidy 诊断旨在指出不符合编码标准的代码,或以其他方式存在问题的代码。但是,如果已知代码是正确的,则可能需要静默警告。一些 clang-tidy 检查提供了一种检查特定的方法来静默诊断,例如,bugprone-use-after-move 可以通过在移动变量后重新初始化变量来静默,bugprone-string-integer-assignment 可以通过将整数显式转换为 char 来抑制,readability-implicit-bool-conversion 也可以通过使用显式转换来抑制等。

如果某个警告没有提供特定的抑制机制,或者由于某种原因不希望使用该机制,clang-tidy 具有一个通用机制来使用 NOLINTNOLINTNEXTLINENOLINTBEGINNOLINTEND 注释抑制诊断。

NOLINT 注释指示 clang-tidy 忽略同一行上的警告(它不适用于函数、代码块或任何其他语言结构;它适用于它所在的代码行)。如果在同一行引入注释会以不希望的方式更改格式,则 NOLINTNEXTLINE 注释允许抑制下一行的 clang-tidy 警告。 NOLINTBEGINNOLINTEND 注释允许抑制多行的 clang-tidy 警告(影响这两个注释之间的所有行)。

所有注释都可以后跟一个可选的检查名称列表,括在括号中(有关正式语法,请参见下文)。检查名称列表支持通配符,格式和语义与启用检查相同。注意:此处忽略负通配符,因为它们实际上会重新激活警告。

例如

class Foo {
  // Suppress all the diagnostics for the line
  Foo(int param); // NOLINT

  // Consider explaining the motivation to suppress the warning
  Foo(char param); // NOLINT: Allow implicit conversion from `char`, because <some valid reason>

  // Silence only the specified checks for the line
  Foo(double param); // NOLINT(google-explicit-constructor, google-runtime-int)

  // Silence all checks from the `google` module
  Foo(bool param); // NOLINT(google*)

  // Silence all checks ending with `-avoid-c-arrays`
  int array[10]; // NOLINT(*-avoid-c-arrays)

  // Silence only the specified diagnostics for the next line
  // NOLINTNEXTLINE(google-explicit-constructor, google-runtime-int)
  Foo(bool param);

  // Silence all checks from the `google` module for the next line
  // NOLINTNEXTLINE(google*)
  Foo(bool param);

  // Silence all checks ending with `-avoid-c-arrays` for the next line
  // NOLINTNEXTLINE(*-avoid-c-arrays)
  int array[10];

  // Silence only the specified checks for all lines between the BEGIN and END
  // NOLINTBEGIN(google-explicit-constructor, google-runtime-int)
  Foo(short param);
  Foo(long param);
  // NOLINTEND(google-explicit-constructor, google-runtime-int)

  // Silence all checks from the `google` module for all lines between the BEGIN and END
  // NOLINTBEGIN(google*)
  Foo(bool param);
  // NOLINTEND(google*)

  // Silence all checks ending with `-avoid-c-arrays` for all lines between the BEGIN and END
  // NOLINTBEGIN(*-avoid-c-arrays)
  int array[10];
  // NOLINTEND(*-avoid-c-arrays)
};

NOLINTNOLINTNEXTLINENOLINTBEGINNOLINTEND 的正式语法如下

lint-comment:
  lint-command
  lint-command lint-args

lint-args:
  ( check-name-list )

check-name-list:
  check-name
  check-name-list , check-name

lint-command:
  NOLINT
  NOLINTNEXTLINE
  NOLINTBEGIN
  NOLINTEND

请注意,NOLINT/NOLINTNEXTLINE/NOLINTBEGIN/NOLINTEND 和左括号之间的空格是不允许的(在这种情况下,注释将被视为 NOLINT/NOLINTNEXTLINE/NOLINTBEGIN/NOLINTEND),而在检查名称列表(括号内)中,可以使用空格,并且空格将被忽略。

所有 NOLINTBEGIN 注释都必须与相同数量的 NOLINTEND 注释配对。此外,一对注释必须具有匹配的参数——例如,NOLINTBEGIN(check-name) 可以与 NOLINTEND(check-name) 配对,但不能与 NOLINTEND (零个参数) 配对。如果任何 NOLINTBEGIN/NOLINTEND 注释违反这些要求,clang-tidy 将生成一个 clang-tidy-nolint 错误诊断。