Clang-Tidy 是一个基于 Clang 的 C++ 静态代码分析工具,旨在帮助开发者发现和修复代码中的潜在问题。它不仅能够检查代码风格、潜在的错误,还能提供自动修复建议,从而提高代码质量和可维护性。本文将介绍 Clang-Tidy 的基本概念、安装方法以及如何使用它来改进你的 C++ 代码。
基本概念
Clang-Tidy 是基于 LLVM 项目的一部分,它利用 Clang 的前端来解析和分析 C++ 代码。Clang-Tidy 提供了丰富的检查器(checks),可以检测多种问题,包括但不限于:
- 代码风格问题
- 潜在的编程错误
- 性能问题
- 现代 C++ 特性使用建议
安装 Clang-Tidy
Clang-Tidy 通常与 Clang 编译器一起发布。你可以通过以下几种方式安装 Clang-Tidy:
通过包管理器安装
Ubuntu/Debian
sudo apt-get install clang-tidy
macOS
brew install llvm
通过源码编译安装
如果你需要最新的功能和修复,可以通过源码编译安装 Clang-Tidy:
-
克隆 LLVM 仓库:
git clone https://github.com/llvm/llvm-project.git
-
创建构建目录并进行配置:
mkdir llvm-project/build cd llvm-project/build cmake -G "Unix Makefiles" ../llvm
-
编译并安装:
make clang-tidy sudo make install
windows
在windows下这个clang-tidy.exe一般随工具链发布,不用单独安装。可以直接搜索到这个clang-tidy.exe可执行程序。
使用 Clang-Tidy
基本用法
Clang-Tidy 的基本用法非常简单,只需在命令行中指定要检查的文件即可:
clang-tidy your_file.cpp
配置文件
Clang-Tidy 支持通过配置文件来定制检查规则。你可以在项目根目录下创建一个 .clang-tidy
文件,并在其中指定要启用或禁用的检查器。例如:
Checks: '-*,modernize-*,cppcoreguidelines-*,clang-analyzer-*'
自动修复
Clang-Tidy 不仅可以检测问题,还可以提供自动修复建议。使用 -fix
选项可以自动应用修复:
clang-tidy -fix your_file.cpp
集成到构建系统
为了更方便地使用 Clang-Tidy,你可以将其集成到你的构建系统中。以下是一些常见的构建系统的集成方法:
CMake
在 CMake 项目中,你可以使用 add_custom_command
和 add_custom_target
来集成 Clang-Tidy:
find_program(CLANG_TIDY_EXE NAMES clang-tidy)
if(CLANG_TIDY_EXE)
set(CMAKE_CXX_CLANG_TIDY ${CLANG_TIDY_EXE})
endif()
Makefile
在 Makefile 中,你可以添加一个目标来运行 Clang-Tidy:
CLANG_TIDY = clang-tidy
tidy:
$(CLANG_TIDY) your_file.cpp --
示例
假设你有一个简单的 C++ 文件 example.cpp
:
#include <iostream>
int main() {
int a = 10;
int b = 0;
int result = a / b; // 除零错误
std::cout << "Result: " << result << std::endl;
return 0;
}
运行 Clang-Tidy 进行检查:
clang-tidy example.cpp
Clang-Tidy 会报告除零错误,并建议修复:
example.cpp:6:16: warning: division by zero is undefined [clang-diagnostic-division-by-zero]
int result = a / b; // 除零错误
^
Cmake中手动使用步骤
1.生成编译数据库:
确保你已经创建了编译数据库。可以使用 CMake 或手动创建 compile_commands.json 文件。
compile_commands.json 文件示例如下:
[
{
"directory": "D:/test",
"command": "cl.exe /c /nologo /O2 /W3 /std:c++17 test.cpp",
"file": "D:/test/test.cpp"
}
]
可用CMake 命令自动生成:
mkdir build
cd build
cmake -DCMAKE_EXPORT_COMPILE_COMMANDS=ON ..
2.配置 .clang-tidy 文件
创建一个 .clang-tidy 文件,启用相应的检查规则:
Checks: 'cppcoreguidelines-*,
performance-*,
modernize-*,
google-*,
misc-*
cert-*,
readability-*,
clang-analyzer-*,
-performance-unnecessary-value-param,
-modernize-use-trailing-return-type,
-google-runtime-references,
-misc-non-private-member-variables-in-classes,
-readability-braces-around-statements,
-google-readability-braces-around-statements,
-cppcoreguidelines-avoid-magic-numbers,
-readability-magic-numbers,
-readability-magic-numbers,
-cppcoreguidelines-pro-type-vararg,
-cppcoreguidelines-pro-bounds-pointer-arithmetic,
-cppcoreguidelines-avoid-c-arrays,
-modernize-avoid-c-arrays,
-cppcoreguidelines-pro-bounds-array-to-pointer-decay,
-readability-named-parameter,
-cert-env33-c
'
3.运行 Clang-Tidy:
使用编译数据库运行 Clang-Tidy。
clang-tidy -p=D:/test/build test.cpp
经过以上三步,即完成了对一个文件的手动使用完整过程。
详细介绍
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-<警告选项>,例如,由-Wliteral-conversion控制的Clang警告将以检查名称clang-diagnostic-literal-conversion报告。
-fix标志指示clang-tidy在相应检查支持的情况下修复发现的错误。
所有命令行选项的概览:
$ clang-tidy --help
通用选项:
--help | 显示可用选项(--help-hidden显示更多)
--help-list | 显示可用选项列表(--help-list-hidden显示更多)
--version | 显示程序的版本
clang-tidy选项:
--checks=<string> | 逗号分隔的全局匹配列表,可选的'-'前缀。全局匹配按在列表中出现的顺序处理。没有'-'前缀的全局匹配将匹配名称的检查添加到集合中,带有'-'前缀的全局匹配从启用的检查集合中移除检查。此选项的值将追加到.clang-tidy文件中的'Checks'选项的值,如果有的话。
--config=<string> | 指定YAML/JSON格式的配置: --config="{Checks: '*', CheckOptions: {x: y}}" 当值为空时,clang-tidy将尝试为其父目录中的每个源文件找到一个名为.clang-tidy的文件。
--config-file=<string> | 指定.clang-tidy或自定义配置文件的路径: 例如 --config-file=/some/path/myTidyConfigFile 此选项在内部的工作方式与读取指定配置文件后的--config选项完全相同。使用--config-file或--config,不要同时使用两者。
--dump-config | 将配置以YAML格式转储到stdout。此选项可以与文件名一起使用(如果文件在配置了编译数据库的项目外部,则使用'--')。 用于此文件的配置将被打印出来。 与-checks=*一起使用,以包括所有检查的配置。
--enable-check-profile | 启用每个检查的时间配置文件,并在stderr上打印报告。
--enable-module-headers-parsing | 为C++20及以上版本启用预处理器级别的模块头解析,使特定检查能够检测模块内的宏定义。此功能可能会导致性能和解析问题,因此被认为是实验性的。
--exclude-header-filter=<string> | 正则表达式,匹配要排除诊断的头文件名称。每个翻译单元的主文件的诊断总是显示的。 必须与--header-filter一起使用。 可以与--line-filter一起使用。 此选项覆盖.clang-tidy文件中的'ExcludeHeaderFilterRegex'选项,如果有的话。
--explain-config | 对于每个启用的检查解释它在哪里启用,即在clang-tidy二进制文件、命令行或特定配置文件中。
--export-fixes=<filename> | YAML文件,用于存储建议的修复。可以使用clang-apply-replacements将存储的修复应用到输入源代码中。
--extra-arg=<string> | 附加参数,添加到编译器命令行 --extra-arg-before=<string> | 附加参数,预置于编译器命令行 --fix | 应用建议的修复。如果没有-fix-errors,如果发现任何编译错误,clang-tidy将退出。
--fix-errors | 即使发现编译错误,也应用建议的修复。如果编译错误有附加的修复,clang-tidy也将应用它们。
--fix-notes | 如果警告没有修复,但可以通过关联的诊断说明找到一个单一的修复,应用该修复。 指定此标志将隐式启用'--fix'标志。
--format-style=<string> | 应用修复周围代码的样式:
- 'none'(默认)关闭格式化
- 'file'(字面意思是'file',不是占位符) 使用最接近父目录中的.clang-format文件
- '{ <json> }' 内联指定选项,例如-format-style='{BasedOnStyle: llvm, IndentWidth: 8}'
总结
Clang-Tidy 是一个强大的 C++ 静态代码分析工具,能够帮助开发者发现和修复代码中的潜在问题。通过配置文件和自动修复功能,你可以更高效地改进代码质量。将其集成到你的构建系统中,可以进一步提高开发效率和代码可靠性。希望本文能帮助你更好地理解和使用 Clang-Tidy,提升你的 C++ 编程技能。