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 库相关的检查。 |
|
与用于 FPGA 的 OpenCL 编程相关的检查。 |
|
与 Android 相关的检查。 |
|
与 Boost 库相关的检查。 |
|
针对容易出现错误的代码结构的检查。 |
|
与 CERT 安全编码指南相关的检查。 |
|
Clang 静态分析器检查。 |
|
与并发编程(包括线程、纤程、协程等)相关的检查。 |
|
与 C++ 核心指南相关的检查。 |
|
与 Darwin 代码约定相关的检查。 |
|
与 Fuchsia 代码约定相关的检查。 |
|
与 Google 代码约定相关的检查。 |
|
与高完整性 C++ 编码标准相关的检查。 |
|
与 Linux 内核代码约定相关的检查。 |
|
与 LLVM 代码约定相关的检查。 |
|
与 LLVM-libc 代码标准相关的检查。 |
|
我们没有更好的分类的检查。 |
|
倡导使用现代(目前“现代”是指“C++11”)语言结构的检查。 |
|
与 MPI(消息传递接口)相关的检查。 |
|
与 Objective-C 代码约定相关的检查。 |
|
与 OpenMP API 相关的检查。 |
|
针对性能相关问题的检查。 |
|
针对与任何特定代码风格无关的移植性相关问题的检查。 |
|
针对与任何特定代码风格无关的可读性相关问题的检查。 |
|
与 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 具有一个通用机制来使用 NOLINT
、NOLINTNEXTLINE
和 NOLINTBEGIN
… NOLINTEND
注释抑制诊断。
NOLINT
注释指示 clang-tidy 忽略同一行上的警告(它不适用于函数、代码块或任何其他语言结构;它适用于它所在的代码行)。如果在同一行引入注释会以不希望的方式更改格式,则 NOLINTNEXTLINE
注释允许抑制下一行的 clang-tidy 警告。 NOLINTBEGIN
和 NOLINTEND
注释允许抑制多行的 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)
};
NOLINT
、NOLINTNEXTLINE
和 NOLINTBEGIN
… NOLINTEND
的正式语法如下
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
错误诊断。