Clang-Tidy 静态分析
Clang-Tidy 是 LLVM 的 C++ 静态分析工具,内置 500+ 检查规则,能发现潜在 bug、性能问题、代码风格问题,是 C++ 代码质量的守门人。
安装
bash
# Ubuntu
sudo apt install clang-tidy
# 验证
clang-tidy --version基本使用
bash
# 分析单个文件(需要 compile_commands.json)
clang-tidy main.cpp -- -std=c++20 -Iinclude
# 使用 compile_commands.json(推荐)
# 先生成:cmake -DCMAKE_EXPORT_COMPILE_COMMANDS=ON ..
clang-tidy -p build/ src/main.cpp
# 并行分析整个项目
run-clang-tidy -p build/ -j8
# 自动修复(部分问题)
clang-tidy -p build/ --fix src/main.cpp
run-clang-tidy -p build/ -fix.clang-tidy 配置
yaml
# .clang-tidy(放在项目根目录)
---
Checks: >
clang-diagnostic-*,
clang-analyzer-*,
cppcoreguidelines-*,
modernize-*,
performance-*,
readability-*,
bugprone-*,
misc-*,
-modernize-use-trailing-return-type,
-readability-magic-numbers,
-cppcoreguidelines-avoid-magic-numbers,
-readability-identifier-length,
-cppcoreguidelines-pro-bounds-pointer-arithmetic
WarningsAsErrors: >
clang-analyzer-*,
bugprone-*,
cppcoreguidelines-pro-type-*
HeaderFilterRegex: '(src|include)/.*'
CheckOptions:
- key: readability-identifier-naming.ClassCase
value: CamelCase
- key: readability-identifier-naming.FunctionCase
value: camelCase
- key: readability-identifier-naming.VariableCase
value: camelCase
- key: readability-identifier-naming.MemberSuffix
value: '_'
- key: modernize-use-default-member-init.UseAssignment
value: true常用检查类别
cpp
// bugprone-*:潜在 bug
// bugprone-use-after-move
std::string s = "hello";
auto s2 = std::move(s);
std::cout << s.size(); // 警告:use-after-move
// bugprone-integer-division
double result = 5 / 2; // 警告:整数除法,结果是 2 不是 2.5
// modernize-*:现代化建议
// modernize-use-nullptr
int* p = NULL; // 建议:使用 nullptr
// modernize-use-auto
std::vector<int>::iterator it = v.begin(); // 建议:auto it = v.begin()
// modernize-range-based-for
for (int i = 0; i < v.size(); ++i) { } // 建议:range-based for
// performance-*:性能问题
// performance-unnecessary-copy-initialization
void foo(const std::string& s) {
std::string copy = s; // 警告:不必要的拷贝,用 const auto& 或直接用 s
}
// performance-for-range-copy
for (auto item : container) { } // 警告:建议 const auto& item
// cppcoreguidelines-*:C++ 核心指南
// cppcoreguidelines-owning-memory
void bad() {
int* p = new int(42); // 警告:裸 new,建议 make_unique
}CI 集成
yaml
# .github/workflows/clang-tidy.yml
name: Clang-Tidy
on: [push, pull_request]
jobs:
clang-tidy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: 安装工具
run: sudo apt-get install -y clang-tidy cmake ninja-build
- name: 生成 compile_commands.json
run: |
cmake -B build -DCMAKE_EXPORT_COMPILE_COMMANDS=ON \
-DCMAKE_BUILD_TYPE=Debug -G Ninja
cmake --build build --target all
- name: 运行 Clang-Tidy
run: |
run-clang-tidy -p build -j$(nproc) \
-header-filter='(src|include)/.*' \
2>&1 | tee clang-tidy-report.txt
# 如果有警告则失败
grep -q "warning:" clang-tidy-report.txt && exit 1 || exit 0抑制特定警告
cpp
// 行内抑制
int* p = new int(42); // NOLINT(cppcoreguidelines-owning-memory)
// 范围抑制
// NOLINTBEGIN(modernize-use-auto)
std::vector<int>::iterator it = v.begin();
std::map<std::string, int>::iterator it2 = m.begin();
// NOLINTEND(modernize-use-auto)
// 整个文件抑制(在文件开头)
// NOLINTBEGIN
// ... 遗留代码 ...
// NOLINTEND关键认知
Clang-Tidy 需要 compile_commands.json 才能正确分析(CMAKE_EXPORT_COMPILE_COMMANDS=ON)。从 bugprone-* 和 clang-analyzer-* 开始,这些是最有价值的检查。modernize-* 帮助将旧代码升级到现代 C++。CI 中运行 Clang-Tidy 是代码质量的重要保障。