# 静态代码分析工具Clang-Tidy
# 基本介绍
clang-tidy
是一个基于 clang 的 C++ “linter” 工具。其作用主要是用来检查和修正代码中的典型编程问题,像代码风格/接口误用/通过静态分析可定位到的bug
。clang-tidy
模块化功能做的很好,有预留接口,非常便于实现新的代码检查功能。
# 安装clang-tidy
直接编译安装LLVM
工程,包含子工程构建,编译安装的bin
路径下有clang-tidy
工具。
LLVM编译安装的详细步骤可以参考这里 (opens new window)
# 使用clang-tidy
clang-tidy
是一个基于 LibTooling
的工具,如果您为项目设置编译命令数据库,则使用起来会更容易(有关如何执行此操作的示例,请参阅如何为 LLVM
设置工具)。源码对应的编译命令数据库保存在compile-command.json
文件中,这个文件中其实保存的是每个可执行文件的构建命令,现在很多工具可以自动生成这个文件,例如对于使用CMake
管理的工程,只需要在编译的时候带上参数cmake -DCMAKE_EXPORT_COMPILE_COMMANDS=ON
即可在build
目录下生成compile-command.json
文件,在执行.clang-tidy
命令时设置-p={project}/build
即可。
可以在命令行添加--
符号,以不使用编译命令而时使用编译选项来定制检测规则,用来实现单个文件的格式检测:
clang-tidy test.cpp -- -Imy_project/include -DMY_DEFINES ...
-I
参数指定要包含的头文件路径
clang-tidy
有其自己的检测器,也可以使用Clang
的静态分析器,每一项检测都有其自己的名字,使用-checks
参数可以指定要进行哪些检测,它指定了逗号分隔的正向和反向规则,正向规则指定了要添加的检测子集,反向规则指定了要移除的规则。示例:
clang-tidy -checks='-*,modernize-*' test.cpp --
-checks
指定要进行哪些检测,-*
表示移除所有检测,modernize-*
表示保留modernize
开头的所有检测。-checks
支持的参数有:
checks 名称前缀 | 说明 |
---|---|
abseil- | Google Abseil 相关的检测 |
altera- | 针对FPGA 的OpenCL 相关的检测 |
android- | Android 相关检测 |
boost- | Boost 库相关检测 |
clang-analyzer- | Clang Static Analyzer 检测 |
更多检测名称前缀参考:
1.https://clang.llvm.org/extra/clang-tidy/index.html#using-clang-tidy (opens new window)
# 配置文件和格式文件
# 配置文件
clang-tidy
提供了一个配置文件,可以指定要使用的检测器、检测器的参数等。配置文件使用YAML
语法编写,一般放在当前工程目录下,文件名为.clang-tidy
。
# 指定要使用的检测器
Checks: '-*,modernize-*,performance-*'
# 指定检测器的参数
CheckOptions:
- key: 'modernize-use-nullptr.NullPtrBeforeZero'
value: '0'
# 格式文件
clang-tidy
命令的--format-style=
参数,需要.clang-format
文件作为参数来设置修复格式化代码的样式。
--format-style=
可选的值有:
- 'none',默认值,关闭格式化
- 'file',设置此值
clang-tidy
会使用最近父目录下的.clang-format
文件来设置格式化的样式 - '{
}'指定格式化选项,例如: -format-style='{BasedOnStyle: llvm, IndentWidth: 8}'
- 'llvm', 'google', 'webkit', 'mozilla'
一个简单的.clang-format
文件的内容:
Language: Cpp
AccessModifierOffset: -2
AlignAfterOpenBracket: Align
AlignConsecutiveAssignments: false
AlignConsecutiveDeclarations: false
AlignEscapedNewlinesLeft: false
AlignOperands: true
# 使用配置文件和格式化文件
对于单个文件,通过命令行可以直接来运行:
clang-tidy -format-style='file' -config-file=.clang-tidy -p ../build/debug test_clang.cpp
对于工程中有很多文件,写成shell
脚本的形式为:
#!/bin/bash
function main() {
local project_dir
project_dir=$(git rev-parse --show-toplevel)
cd "$project_dir" || exit 1
local srcs
srcs=$(git ls-files src crossdock |
grep -E -v 'thrift-gen|Test\.cpp' |
grep -E '\.cpp$')
local cmd
for src in $srcs; do
cmd="clang-tidy -p=build"
cmd+=" -checks=\"-clang-diagnostic-unused-command-line-argument\" "
cmd+=" $src"
echo "$cmd"
eval "$cmd"
done
}
main
# 在代码中设置排除clang-tidy
检测
对于工程中的代码,有时候可以确认代码是正常的,但是不满足clang-tidy
的规则,这个时候需要增加设置使目标代码免除检测。
通用抑制检测的机制:
- 对于一行,使用
NOLINT
注释:
int main(int argc, char** argv) // NOLINT
{
return 0;
}
- 下一行免除检测
// NOLINTNEXTLINE
int main(int argc, char** argv)
{
return 0;
}
- 设置一段代码免除检测
int main(int argc, char** argv)
{
// NOLINTBEGIN
int x;
int y;
// NOLINTEND
return 0;
}
上面的NOLINT
注释后可以接参数,设置具体要避免哪些规则的检测:
int main(int argc, char** argv)
{
// NOLINTBEGIN(google*)
int x;
int y;
int array[10]; // NOLINT(*-avoid-c-arrays)
// NOLINTEND(google*)
return 0;
}
# reference
1.https://clang.llvm.org/extra/clang-tidy/index.html#using-clang-tidy (opens new window)
← C++加速编译工具ccache LLVM →