Clang-Tidy静态代码分析框架
描述
clang-tidy是一个基于clang的静态代码分析框架,支持C++/C/Objective-C;
clang-tidy不仅可以做静态检查,还可以做一些自动修复工作。
安装clang-tidy和clang编译工具
1.ubantu20安装(默认安装clang-tidy-10版本)
sudo apt install clang-tidy clang
2.centos安装(只有clang-tidy)
# 安装 SCL 的 yum 源
# (它可以支持系统同时安装多个版本的软件,然后通过scl enable命令来激活相应软件环境,而不会对原始的软件环境产生影响。)
sudo yum install centos-release-scl
sudo yum install llvm-toolset-7
sudo yum install llvm-toolset-7-clang-analyzer llvm-toolset-7-clang-tools-extra
scl enable llvm-toolset-7 "clang -v"
scl enable llvm-toolset-7 "lldb -v"
# 在新的 Bash 中启用 llvm-toolset-7
#(注意,SCL 是在保证不与原有软件冲突的情况下运行的,也就意味着用户默认 Bash 是无法调用 SCL 的)
scl enable llvm-toolset-7 bash
2.1.centos如果需要系统重启后,能够自动启动最新版本软件环境
# 通过bash环境来设定,对当前用户启用
vim ~/.bashrc
# 加入
source scl_source enable llvm-toolset-7
2.2.centos如果需要批量检查
下载 run-clang-tidy.py
建议放在/opt/rh/llvm-toolset-7/root/usr/bin/
命令使用
列出默认执行的检查
clang-tidy -list-checks
列出它可以执行的所有检查
clang-tidy -list-checks -checks="*"
使用默认启用的所有检查来检查文件
clang-tidy test.cpp
使用默认启用的所有检查来检查文件并使用建议的修复来修复错误
clang-tidy -fix test.cpp
clang-tidy -fix-errors test.cpp
后面的--表示这个文件不在compilation database(compile_commands.json)里面,可以直接单独编译;
clang-tidy -checks="-*,modernize-use-nullptr" src/test.cpp --
找出test.cpp中指向NULL/0的指针,并自动转化为nullptr)
clang-tidy -checks="-*,misc-unused-nullptr" -fix src/test.cpp --
run-clang-tidy.py脚本能够对每个compilation database中的每个文件都运行clang-tidy(使用多进程方法)
# 这里的"-*"就是要使目前所有的默认规则失效(只做modernize-use-nullptr检查并修复)
/usr/bin/run-clang-tidy.py -checks="-*,modernize-use-nullptr" -fix
cmake使用
1 | |
支持的check
| 规则 | 描述 |
|---|---|
| abseil- | 与 Abseil 库相关的检查 |
| altera- | 与 FPGA 的 OpenCL 编程相关的检查 |
| android- | 与 Android 相关的检查 |
| boost- | 与 Boost 库相关的检查 |
| bugprone- | 检查目标容易出错的代码结构 |
| cert- | 与 CERT 安全编码指南相关的检查 |
| clang-analyzer- | Clang 静态分析器检查 |
| concurrency- | 与并发编程相关的检查(包括线程、纤程、协程等) |
| cppcoreguidelines- | 与 C++ 核心指南相关的检查 |
| 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 内核编码约定相关的检查 |
自动检查转换C++代码
自动地把老的C++03代码替换成C++11代码
需要指定 -fix
| 标志 | 描述 |
|---|---|
| modernize-avoid-bind | 使用lambda替换std::binding |
| modernize-deprecated-headers | 将C标准库的头文件include替换成C++style,#include <assert.h> => #include |
| modernize-loop-convert | 使用for-range loop替换for(…;…;…;), 并更新for语句的相关变量 |
| modernize-make-shared | 找出所有显式创建std::shared_ptr变量的表达式,并使用make_shared替换 |
| modernize-make-unique | 跟make-shared一样,使用std::make_unique替换所有std::unique_ptr显式创建表达式 |
| modernize-pass-by-value | 在构造函数中使用move语义 |
| modernize-raw-string-literal | 用C++11的raw string literal(R”…”)替换原来的string literal, 这样的好处就是不用再添加转义符\了 |
| modernize-redundant-void-arg | 去掉void函数参数 |
| modernize-replace-auto-ptr | 用std::unique_ptr替换std::shared_ptr, std::shared_ptr是不推荐使用的,即使在C++98 |
| modernize-shrink-to-fit | 在C++03中,如果我们想修改STL容器的capacity,只能通过copy & swap的方式,C++11提供了shink_to_fit的方法 |
| modernize-use-auto | 在变量定义的时候,使用auto代替显式的类型声明,这个在定义STL容器类的Iterator特别方便 |
| modernize-use-bool-literals | 找出所有隐式从int转成bool的literal, 使用true或者false代替 |
| modernize-use-default | 对于没有任何自定义行为(定义为{})的特殊的成员函数,构造函数,析构函数,移动/复制构造函数,用=default代替掉{} |
| modernize-use-emplace | 使用STL容器中的emplace代替push_back |
| modernize-use-equals-delete | 在C++98中,类设计为了实现禁止调用某些特殊的成员函数,通常把它们声明成private;在C++11中,只需要在声明中体检=delete,找出所有private的特殊成员函数,并将它们标记成=delete |
| modernize-use-nullptr | 用nullptr代替NULL |
| modernize-use-override | 对于子类改写父类的virtual方法,在方法后面添加override, 并删掉virtual前缀,即virtual void NewOveride() => void NewOverride() override {} |
| modernize-use-using | 用using代替typedef, 如typedef int V => using V = int |
注意
cmake使用clang-tidy时需要把CMAKE_CXX_CLANG_TIDY赋值,放在add_executable或add_library前面
CMAKE_CXX_CLANG_TIDY是 cmake 3.6版本之后的功能
详细检查项
| 规则 | 描述 |
|---|---|
| boost-use-to-string | 从整数类型转换为字符串默认使用std::to_string |
| bugprone-argument-comment | 参数注释 |
| bugprone-branch-clone | 要求相同分支合并 |
| bugprone-copy-constructor-init | 基类拷贝构造函数初始化 |
| bugprone-dynamic-static-initializers | 禁止返回动态初始化的静态变量 |
| bugprone-exception-escape | 禁止在一些函数内抛出异常,避免带来一些风险(析构函数、移动构造函数、移动赋值运算符、main函数、swap函数等) |
| bugprone-fold-init-type | 检查截断和溢出的情况 |
| bugprone-forward-declaration-namespace | 检查同名但未定义的命名空间 |
| bugprone-incorrect-roundings | 排除不正确舍入问题 |
| bugprone-infinite-loop | 检查容易出错的无限循环 |
| bugprone-integer-division | 检查会导致精度损失的整数除法 |
| bugprone-macro-parentheses | 查找由于缺少括号而可能具有意外行为的宏 |
| bugprone-misplaced-operator-in-strlen-in-alloc | 检查字符串操作的不当行为 |
| bugprone-misplaced-pointer-arithmetic-in-alloc | 检查错误的指针动态分配内存 |
| bugprone-misplaced-widening-cast | 类型转换造成的精度损失 |
| bugprone-move-forwarding-reference | 检查std::move()的错误使用 |
| bugprone-multiple-statement-macro | 检查多语句宏定义 |
| bugprone-no-escape | 查找容易出错的noescape |
| bugprone-not-null-terminated-result | 检查可能导致非空终止结果的函数调用,使用strcpy()、strncpy()、strcpy_s()、 strncpy_s()代替memcpy()和memcpy_s() |
| bugprone-parent-virtual-call | 检查对父虚函数的调用 |
| bugprone-posix-return | 检查对pthread_*或posix_*函数调用是否判断负返回值 |
| bugprone-redundant-branch-condition | 检查逻辑if的重复判断冗余 |
| bugprone-reserved-identifier | 检查不规范的下划线使用 |
| bugprone-signal-handler | 检查容易出错的信号处理程序 |
| bugprone-signed-char-misuse | 检查错误的字符型与字符型、整型之间的强制转换和比较 |
| bugprone-sizeof-container | 检查可能出错的sizeof使用 |
| bugprone-sizeof-expression | |
| bugprone-spuriously-wake-up-functions | 检查唤醒函数的错误使用 |
| bugprone-string-constructor | 检查容易出错的字符串初始化 |
| bugprone-string-integer-assignment | 检查容易出错的字符串赋值(可能导致误判) |
| bugprone-string-literal-with-embedded-nul | 检查带有嵌入\0字符的字符串 |
| bugprone-suspicious-enum-usage | 容易出错的枚举用法 |
| bugprone-suspicious-include.HeaderFileExtensions | 检查错误的文件包含(只包含头文件) |
| bugprone-suspicious-memset-usage | 检查错误的memset的使用 |
| bugprone-suspicious-missing-comma | 检查可疑的逗号丢失 |
| bugprone-suspicious-semicolon | 检查容易出错的可以分号 |
| bugprone-suspicious-string-compare | 检查可疑的字符串比较 |
| bugprone-swapped-arguments | 检查容易出错的交换参数 |
| bugprone-terminating-continue | 检查do-while常为false时的continue使用 |
| bugprone-throw-keyword-missing | 检查可能缺失的throw关键字 |
| bugprone-too-small-loop-variable | 检查容易出错的循环变量 |
| bugprone-undefined-memory-manipulation | 查找容易出错的未定义内存操作 |
| bugprone-undelegated-constructor | 检查容易出错的委托构造函数 |
| bugprone-unhandled-exception-at-new | 检查未对new进行异常处理 |
| bugprone-unhandled-self-assignment | 检查容易出错的未处理自赋值 |
| bugprone-unused-raii | 检查看起来像RAII对象的临时对象。 |
| bugprone-unused-return-value | 检查未使用的一些返回值(如返回指针) |
| bugprone-use-after-move | 禁止使用std::move之后的对象仍被使用 |
| bugprone-virtual-near-miss | 检查函数名与基类虚函数类似的函数声明 |
| cert-dcl21-cpp | 会报未知的警告 |
| cert-dcl50-cpp | |
| cert-env33-c | |
| cert-dcl58-cpp | 检查对std posix等命名空间的修改 |
| cert-err34-c | 检查不验证转换字符串到数字的有效性的代码,如c语言atoi() |
| cert-flp30-c | 检查浮点类型的循环 |
| clang-analyzer-core.DynamicTypePropagation | 生成动态类型信息 |
| clang-analyzer-core.uninitialized.CapturedBlockVariable | 检查未初始化的块 |
| clang-analyzer-cplusplus.InnerPointer | 检查释放后的内部指针的使用 |
| clang-analyzer-nullability.NullableReturnedFromNonnull | 检查从非空返回类型 返回 可能空的指针 |
| clang-analyzer-optin.osx.OSObjectCStyleCast | |
| clang-analyzer-optin.performance.GCDAntipattern | |
| clang-analyzer-osx.MIG | |
| clang-analyzer-optin.performance.Padding | 检查过度填充的结构 |
| clang-analyzer-osx.OSObjectRetainCount | |
| clang-analyzer-osx.ObjCProperty | 检查objc |
| clang-analyzer-osx.cocoa | AutoreleaseWrite |
| -clang-analyzer-osx.cocoa-* | cocoa相关 |
| clang-analyzer-valist- | va_lists相关 |
| concurrency-mt-unsafe | mt安全 |
| concurrency-thread-canceltype-asynchronous | 并发线程 |
| cppcoreguidelines-avoid-goto | 避免使用goto |
| cppcoreguidelines-avoid-non-const-global-variables | 禁止非常量全局变量 |
| cppcoreguidelines-interfaces-global-init | 检查extern对象的全局变量的初始值设定项初始化顺序问题 |
| -cppcoreguidelines-macro-usage | 检查可能被认为有问题的宏用法 |
| -cppcoreguidelines-narrowing-conversions | |
| cppcoreguidelines-no-malloc | 对c风格内存分配的检查 |
| -cppcoreguidelines-owning-memory | 检查内存分配时是否使用gsl的方法 |
| cppcoreguidelines-prefer-member-initializer | |
| cppcoreguidelines-pro-bounds-array-to-pointer-decay | |
| cppcoreguidelines-pro-bounds-constant-array-index | |
| -cppcoreguidelines-pro-bounds-pointer-arithmetic | 标记指针的算法使用 |
| -cppcoreguidelines-pro-type-const-cast | 标记const_cast的使用 |
| -cppcoreguidelines-pro-type-cstyle-cast | |
| -cppcoreguidelines-pro-type-member-init | |
| -cppcoreguidelines-pro-type-reinterpret-cast | 标记reinterpret_cast的使用 |
| -cppcoreguidelines-pro-type-static-cast-downcast | 标记static_cast的使用 |
| -cppcoreguidelines-pro-type-union-access | 标记union成员的访问权限 |
| cppcoreguidelines-pro-type-vararg | 标记对c样式可变参数函数调用以及对va_arg的使用 |
| cppcoreguidelines-slicing | 检查导致slice的情况 |
| cppcoreguidelines-special-member-functions | |
| darwin-avoid-spinlock | |
| darwin-dispatch-once-nonstatic | |
| -fuchsia-default-arguments-calls | 使用默认参数时发出警告 |
| -fuchsia-default-arguments-declarations | 函数定义默认参数时发出警告 |
| -fuchsia-multiple-inheritance | 继承自多个非纯虚类发出警告 |
| -fuchsia-overloaded-operator | 检查已被重载的运算符 |
| fuchsia-statically-constructed-objects | 限制创建静态对象(除非构造函数是constexpr类型或没有显式构造函数) |
| fuchsia-trailing-return | |
| fuchsia-virtual-inheritance | 对虚继承类发出警告(报错) |
| google-build-explicit-make-pair | 检查make_pair是否推断出模板类型 |
| google-build-using-namespace | 检查是否使用using namespace |
| google-default-arguments | 为虚函数参数添加默认值 |
| -google-explicit-constructor | 检查显式构造函数,避免隐式转换带来的风险 |
| google-global-names-in-headers | 在头文件中标记全局命名空间污染 |
| -google-objc-avoid-nsobject-new | objc |
| -google-objc-avoid-throwing-exception | |
| -google-objc-function-naming | |
| -google-objc-global-variable-declaration | |
| google-readability-avoid-underscore-in-googletest-name | 检查googletest的测试以及测试示例名称是否有下划线(测试名称和测试用例名称中不允许使用下划线) |
| google-readability-casting | 查找 C 风格强制转换的用法 |
| google-readability-todo | 查找TODO有没有署用户名、邮件等 |
| -google-runtime-int | 检查整数定义,将short, long,long long改为intxx_类型 |
| google-runtime-operator | 检查用户自定义表述的重载运算符 |
| google-upgrade-googletest-case | 用户自定义函数名中,将带有case字符改为suite |
| -hicpp-avoid-goto | 要求goto只跳过块的一部分(不使用goto) |
| hicpp-exception-baseclass | 确保throw表达式中的每个值都是std::exception的实例 |
| hicpp-multiway-paths-covered | 有if和else if一定要包含else(即使内容为空),有switch要包含default,少量case用if代替。 |
| hicpp-no-assembler | 检查汇编语句 |
| hicpp-signed-bitwise | 检查对有符号整数类型的按位运算的使用,避免风险 |
| linuxkernel-must-use-errs | 检查linux内核代码 |
| llvm-header-guard | 检查不符合LLVM风格的头文件 |
| llvm-include-order | 检查include的正确顺序(llvm风格) |
| llvm-namespace-comment | 长命名空间结束注释 |
| llvm-prefer-isa-or-dyn-cast-in-conditionals | cast的一些变换 |
| llvm-prefer-register-over-unsigned | unsigned用Register代替 |
| llvm-twine-local | Twine方法使用后面加.str() |
| llvmlibc-callee-namespace | 检查调用解析为__llvm_libc命名空间内的函数 |
| llvmlibc-implementation-in-namespace | |
| llvmlibc-restrict-system-libc-headers | 查找编译器未提供的系统 libc 头文件,如stdio.h |
| -misc-definitions-in-headers | 在头文件中查找非 extern 非内联函数和变量定义 |
| misc-misplaced-const | 检查const的错误使用 |
| misc-new-delete-overloads | 检查new和delete |
| misc-no-recursion | 检查函数递归错误 |
| misc-non-copyable-objects | 检查一些对象,不允许复制,比如FILE |
| -misc-non-private-member-variables-in-classes | 规定类成员变量必须为private |
| misc-redundant-expression | 检查冗余表达式 |
| misc-static-assert | 用static_assert()代替assert() |
| misc-throw-by-value-catch-by-reference | 查找违反“按值抛出,按引用捕捉”的规则 |
| misc-unconventional-assign-operator | 检查重载运算符的错误返回类型 |
| misc-uniqueptr-reset-release | 将unique_ptr::reset(release())替换为std::move() |
| misc-unused-alias-decls | 查找未使用的命名空间别名声明 |
| misc-unused-parameters | 查找未使用的参数并报错(可能代码有误) |
| misc-unused-using-decls | 查找未使用的using声明 |
| modernize-avoid-bind | 替换std::bind()的使用 |
| modernize-avoid-c-arrays | 避免使用c语言的array |
| modernize-concat-nested-namespaces | 嵌套命名空间的简化(可以简化时) |
| modernize-deprecated-headers | 检查c++中弃用的c头文件 |
| modernize-deprecated-ios-base-aliases | 检查弃用的类方法 |
| modernize-loop-convert | 避免有风险的循环,替换为c++11风格 |
| modernize-make-shared | 对于share_ptr的一些更改 |
| modernize-make-unique | 对于unique_ptr的一些更改 |
| modernize-pass-by-value | |
| modernize-raw-string-literal | 字符串初始化的风格检查 |
| modernize-redundant-void-arg | 检查冗余的void |
| modernize-replace-auto-ptr | 用unique_ptr替换auto_ptr |
| modernize-replace-disallow-copy-and-assign-macro | |
| modernize-replace-random-shuffle | 将std::random_shuffle替换为std::shuffle |
| modernize-return-braced-init-list | 用花括号初始化器列表替换返回中对构造函数的显式调用 |
| modernize-shrink-to-fit | 关于缩放的使用 |
| modernize-unary-static-assert | 关于static_assert空字符串的检查 |
| modernize-use-auto | 检查auto的使用风格 |
| modernize-use-bool-literals | 检查bool类型,用true和false表示 |
| modernize-use-default-member-init | 构造函数初始化的设定值风格 |
| -modernize-use-emplace | 在std::vector、std::deque、std::list中插入的使用限制 |
| modernize-use-equals-default | 将特殊成员函数的默认主体替换为显式默认函数声明 |
| modernize-use-equals-delete | 将删除的特殊成员函数显式表示 |
| -modernize-use-nodiscard | const成员函数的使用风格 |
| modernize-use-noexcept | 函数定义的throw替换为noexcept |
| -modernize-use-nullptr | 将空指针NULL改为nullptr |
| modernize-use-override | 在重载虚函数中添加override声明 |
| -modernize-use-trailing-return-type | 使用尾随返回类型 |
| modernize-use-transparent-functors | |
| modernize-use-uncaught-exceptions | |
| modernize-use-using | 将typedef转换为using |
| mpi-buffer-deref | 关于消息传递接口的检查 |
| mpi-type-mismatch | 检查消息传递接口不匹配问题 |
| objc-avoid-nserror-init | objc相关 |
| objc-dealloc-in-category | |
| objc-forbidden-subclassing | |
| objc-missing-hash | |
| objc-nsinvocation-argument-lifetime | |
| objc-property-declaration | |
| objc-super-self | |
| openmp-exception-escape | openmp相关 |
| openmp-use-default-none | |
| performance-faster-string-find | 优化find的效率 |
| performance-for-range-copy | 不使用for循环里使用auto的警告 |
| performance-implicit-conversion-in-loop | for循环中,变量的隐式表示(auto)代替显式表示 |
| performance-inefficient-algorithm | 检查关联容器中的低效使用 |
| performance-inefficient-string-concatenation | 检查性能低效的字符串连接,字符串拼接改为append,而不是操作符+ |
| -performance-inefficient-vector-operation | 查找可能导致不必要的内存重新分配的低效vector操作 |
| performance-move-const-arg | 关于std::move的一些警告 |
| performance-move-constructor-init | 标记移动构造函数初始化 |
| performance-no-automatic-move | |
| performance-no-int-to-ptr | 限制整数到指针的转换 |
| performance-noexcept-move-constructor | 检查移动构造函数没有标记noexcept或者为false的情况 |
| performance-trivially-destructible | 检查外部可破坏析构函数的情况 |
| performance-type-promotion-in-math-fn | 数学库,从c到c++的转换 |
| performance-unnecessary-copy-initialization | |
| performance-unnecessary-value-param | 使用参数的移动(std::move),而不是复制 |
| portability-restrict-system-includes | 检查以选择性地允许或禁止系统标头的可配置列表 |
| portability-simd-intrinsics | |
| -readability-avoid-const-params-in-decls | 检查函数声明是否具有顶级参数 const |
| readability-braces-around-statements | 在逻辑语句是否添加大括号 |
| readability-const-return-type | 常量返回值的限制 |
| readability-container-size-empty | 检查对size()调用是否可以用empty()来代替 |
| readability-convert-member-functions-to-static | 将不使用this的非静态成员函数转换为静态成员函数 |
| -readability-delete-null-pointer | 查找检查指针是否存在的语句 |
| readability-else-after-return | 检查多余的else使用 |
| readability-function-cognitive-complexity | 检查功能认知复杂性指标 |
| readability-function-size | 根据各种指标检查大型函数 |
| readability-identifier-naming | 标识符命名方式限制 |
| readability-implicit-bool-conversion | 检查bool与int之间的转换 |
| readability-inconsistent-declaration-parameter-name | 查找参数名称不一致的声明 |
| readability-isolate-declaration | 将连续的变量声明拆分成逐一声明 |
| readability-magic-numbers | magic numbers检查 |
| readability-make-member-function-const | 检查可以被定义为const的非静态成员函数 |
| readability-misleading-indentation | 检查误导性缩进 |
| readability-misplaced-array-index | 检查出错的索引 |
| readability-named-parameter | 查找带有未命名参数的函数 |
| readability-non-const-parameter | 检查可以更改为指向常量类型的指针类型的函数参数 |
| readability-qualified-auto | 将指针限定添加到auto推导为指针的类型变量 |
| readability-redundant-access-specifiers | 删除冗余的访问类型说明 |
| readability-redundant-control-flow | 删除无用的return和continue |
| readability-redundant-declaration | 删除冗余的变量和函数声明 |
| readability-redundant-function-ptr-dereference | 删除多余的指针冗余 |
| readability-redundant-member-init | 查找多余的成员初始化 |
| readability-redundant-preprocessor | 查找潜在的冗余预处理器指令 |
| readability-redundant-smartptr-get | 删除对智能指针.get()方法的冗余调用 |
| readability-redundant-string-cstr | 检查不必要的调用:std::string::c_str()和std::string::data() |
| readability-redundant-string-init | 查找不必要的字符串初始化 |
| readability-simplify-boolean-expr | 简化对bool类型的使用 |
| readability-simplify-subscript-expr | 简化下标表达式 |
| readability-static-accessed-through-instance | 优化类静态成员的访问方式 |
| readability-static-definition-in-anonymous-namespace | 检查匿名命名空间中的静态成员定义 |
| readability-string-compare | 优化字符串比较的使用,尽量使用==或者!= |
| readability-suspicious-call-argument | 传参缩写检查 |
| readability-uniqueptr-delete-release | 替换 |
| readability-uppercase-literal-suffix | 要求整数后缀为大写字符 |
| readability-use-anyofallof |
Clang-Tidy静态代码分析框架
https://www.inktea.eu.org/2022/b47a.html