clang-tidy配置
前言
介绍
Clang-Tidy 是一个由 LLVM 项目提供的开源静态分析工具,用于进行静态代码分析和代码质量改进。利用 Clang 编译器强大的功能来对 C++ 代码进行静态分析,并且提供一系列代码改进建议和警告
Clang-Tidy 是基于 Clang 的 AST 抽象语法树进行分析的,并且能检测到许多常见的编码错误和代码风格问题,包括语法,逻辑,性能问题和风格问题等
安装
windows
直接从上述网站上找到一个对应的发行版安装即可
然后在命令行中输入如下指令来查看是否安装完成,一般来说安装完成之后需要重新启动一下
1 | clang-tidy -version |
ubuntu
根据该文章的内容来安装
安装最新版 LLVM,需要注意,该指令只能在 bash 中使用
1 | sudo bash -c "$(wget -O - https://apt.llvm.org/llvm.sh)" |
安装 Clang-format
1 | apt-get install clang-18 clang-tools-18 clang-18-doc libclang-common-18-dev libclang-18-dev libclang1-18 clang-format-18 python3-clang-18 clangd-18 clang-tidy-18 |
之后可以验证
1 | llvm-config-18 --version |
原理
Clang-Tidy 的工作原理是将源代码传递给 Clang 编译器,然后通过静态分析找到代码中的问题。Clang 编译器是一个基于 LLVM 的项目,它提供了一个强大的 C++ 前端,能解析,编译和优化 C++ 代码。而 Clang-Tidy 则利用了 Clang 编译器这些功能,对源代码进行深度分析,并且找出其中可能存在的问题
原文地址
clang-tidy - Clang-Tidy Checks — Extra Clang Tools 20.0.0git documentation (llvm.org)
配置文件
编写规则
- 配置文件名必须为
.clang-tidy - 该文件必须位于项目的根目录或者编译目录下
- 文件采用
YAML语法 - 每个
YAML条目包含一下几个关键字ChecksWarningsAsErrorsIncludePathsUserCheckOptions
Checks
- 静态分析器
clang-analyzer-coreBitwiseShift查找由按位左移和右移运算符引起的未定义行为,对整数类型进行操作。默认此检查器仅报告右操作数为负数或左操作数右操作数类型的位宽CallAndMessage检查函数调用和 ObjC 消息表达式的逻辑错误,主要是未初始化的参数,空函数指针DivideZero检查是否除以 0NonNullParamChecker检查作为参数传递给标记为nonnull属性的函数的是否为null指针NullDereference检查null指针的非法使用,野指针StackAddressEscape检查栈的内存地址不会被外部引用,栈的内存会在函数结束时被释放,所以如果被外部引用,就会引发安全漏洞UndefinedBinaryOperatorResult检查二元运算是否有未定义的结果,一般是未初始化VLASize检查数组定义时,数组的长度是否为 0,负数和未定义。还会对未知的长度做出警告(除非做判断保证为正数)uninitialized.ArraySubscript检查定义数组长度的变量是否未定义uninitialized.Assign检查并避免为变量分配未初始化的值uninitialized.Branch检查未初始化的值是否用于分支控制语句uninitialized.CapturedBlockVariable检查在代码块中是否使用未初始化的值uninitialized.UndefReturn返回未初始化的值uninitialized.NewArraySize在new array中是否使用未初始化的值
clang-analyzer-cpluspluscplusplus.ArrayDelete使用父类指针指向new array子类的结构体,然后试图delete array这个父类指针。对类型不正确的指针使用delete arraycplusplus.InnerPointer检查 C++ 容器内部指针在realloc或者dealloc之后使用。C++标准库中的许多容器方法都已知会使指向容器元素的引用(包括实际的引用,迭代器和原始指针)失效,这是 C++ 常见的内存错误来源cplusplus.Move检查 C++ 中是否出现变量移动之后使用,也就是对象被移动之后依旧对对象做一些不当行为cplusplus.NewDelete检查是否有二次delete和delete之后再次使用的问题cplusplus.NewDeleteLeaks检查是否内存被申请之后未被释放,应当通过new/delete进行内存管理cplusplus.PlacementNew检查是否提供了默认的new操作符,并且是否以指向足够内存空间的指针作为参数cplusplus.SelfAssignment检查 C++ 中的拷贝和移动运算符是否存在自赋值cplusplus.StringChecker字符串检查,检查用于构造字符串的参数是否有效
clang-analyzer-deadcodeDeadStores检查是否存在赋值给一个从未被读取的变量
clang-analyzer-nullabilityNullPassedToNonnull当向一个被标记为_Nonnull类型的指针传递一个空指针(null pointer)时,编译器或静态分析工具会发出警告NullReturnedFromNonnull当一个函数的返回类型被标记为_Nonnull(即不允许返回空指针),但该函数实际上返回了一个空指针时,编译器或静态分析工具会发出警告。NullableDereferenced当尝试访问(或“解引用”)一个可能为null的指针时,会发出警告NullablePassedToNonnull当一个可能为空的指针(即可空指针)被传递给一个期望非空指针(通过_Nonnull标记)的函数或方法时,编译器或静态分析工具会发出警告NullableReturnedFromNonnull在编程时,如果某个函数被声明为返回一个非空_Nonnull指针,但是该函数实际上返回了一个可能为空的指针(即nullable指针),编译器或静态分析工具会发出警告
clang-analyzer-optincore.EnumCastOutOfRange在检查将整数转换为枚举(enumeration)类型时,是否存在转换成了一个没有对应枚举量的值的情况,即超出了枚举的范围cplusplus.UninitializedObject此检查器报告在构造函数调用后创建的对象中未初始化的字段。它不仅查找直接的未初始化字段,而且对对象进行深入检查,分析其字段的所有子字段。检查器将继承字段视为直接字段,因此也会收到未初始化继承数据成员的警告cplusplus.VirtualCall在构造或销毁过程中检查是否虚函数调用mpi.MPI-Checker检查 MPI 代码osx.cocoa.localizability.EmptyLocalizationContextChecker检查NSLocalizedString宏是否包含上下文注释osx.cocoa.localizability.NonLocalizedStringChecker警告使用传递给期望本地化nsstring的 UI 方法的非本地化nsstringperformance.GCDAntipattern在使用 Grand Central Dispatch 时检查性能反模式performance.Padding检查过度填充的结构。此检查器检测具有过多填充的结构,这可能导致内存浪费,从而通过降低处理器缓存的有效性来降低性能。填充字节由编译器添加以对齐数据访问,因为某些处理器需要将数据对齐到某些边界。在其他情况下,不对齐的数据访问是可能的,但会带来更大的延迟。portability.UnixAPI在 UNIX/Posix 函数中查找实现定义的行为。taint.TaintedAlloc当无法证明申请分配的内存在合法范围内时警告
clang-analyzer-securitycert.env.InvalidPtr对应 SEI CERT 规则 ENV31-C 和 ENV34-CFloatLoopCounter警告使用浮点值作为循环计数器insecureAPI.UncheckedReturn对必须始终检查返回值的函数的使用发出警告insecureAPI.bcmp对使用bcmp函数发出警告insecureAPI.bcopy对使用bcopy函数发出警告insecureAPI.bzero对使用bzero函数发出警告insecureAPI.getpw对使用getpw函数发出警告insecureAPI.gets对使用gets函数发出警告insecureAPI.mkstemp当传入函数mkstemp的格式字符串少于 6 个 X 时发出警告insecureAPI.mktemp对使用mktemp函数发出警告insecureAPI.rand警告使用劣质随机数生成函数insecureAPI.strcpy对使用strcpy函数发出警告insecureAPI.vfork对使用vfork函数发出警告insecureAPI.DeprecatedOrUnsafeBufferHandling警告不安全或已弃用的缓冲区处理函数,这些函数现在有一个安全的变体MmapWriteExec对具有可写和可执行权限的mmap函数调用发出警告PutenvStackArray查找对传递指向堆栈分配(自动)数组的指针作为参数的函数的调用。函数不复制传递的字符串,只存储指向数据的指针,并且该数据甚至可以被其他线程读取。从函数putenvputenv退出后,堆栈分配数组的内容可能会被覆盖。这个问题可以通过使用静态数组变量或动态分配内存来解决。更好的方法是避免使用putenvputenv(它有其他与内存泄漏相关的问题),而是使用putenvsetenvSetgidSetuidOrder当通过使用和调用来删除程序中的用户级和组级特权时,首先重置组级特权是很重要的。如果超级用户权限已经被删除,函数可能会失败检查器检查和调用的序列(按此顺序)。如果找到这样一个序列,并且中间没有其他改变特权的函数调用(和它们的 GID 版本),则会生成一个警告
clang-analyzer-unixAPI检查对各种 UNIX/Posix 函数的调用BlockInCriticalSection检查临界区内对阻塞函数的调用Errno检查使用不当Malloc检查内存泄漏、双重自由和自由后使用问题。跟踪由malloc()/free()管理的内存。MallocSizeof检查涉及malloc(sizeof())的可疑参数MismatchedDeallocator检查不匹配的析构函数Vfork检查vfork函数的正确使用cstring.BadSizeArg检查传入 C 字符串函数的size参数是否存在常见的错误模式。使用编译器选项来静音其他相关的编译器警告cstring.NullArg检查作为参数传递给C字符串函数的空指针StdCLibraryFunctions检查标准库函数的调用是否违反预定义的参数约束Stream检查 C 流处理函数
clang-analyzer-osxAPI检查各种 Apple api 的正确使用NumberObjectConversion检查表示数字的对象转换到数字的错误转换ObjCProperty检查对 ObjC 属性的正确使用SecKeychainAPI检查安全钥匙链 api 的正确使用cocoa.AtSync检查 ObjC 中@synchronized中用作互斥锁的nil指针cocoa.AutoreleaseWrite警告在 ObjC 中从不同的自动释放池写入自动释放对象可能会崩溃cocoa.ClassRelease检查是否将retain,release或autorelease直接发送给类cocoa.Dealloc警告缺少-dealloc正确实现的 ObjC 类cocoa.IncompatibleMethodTypes警告带有类型不兼容的 ObjC 方法签名cocoa.Loops使用 Cocoa 集合类型改进循环建模cocoa.MissingSuperCall警告缺少必要的 super 调用的 ObjC 方法cocoa.NSAutoreleasePool在 ObjC GC 模式下对NSAutoreleasePool的次优使用发出警告cocoa.NSError检查 NSError 参数的使用情况cocoa.NilArg检查 ObjC 方法调用中禁止的 nil 参数cocoa.NonNilReturnValue对保证返回非 nil 值的 api 进行建模cocoa.ObjCGenerics在使用 ObjC 泛型时检查类型错误cocoa.RetainCount检查泄漏和不适当的参考计数管理cocoa.RunLoopAutoreleaseLeak检查自动释放池中永远不会耗尽的泄漏内存cocoa.SelfInit检查’ self '是否在初始化方法中被正确初始化cocoa.SuperDealloc警告在 ObjC 中不正确使用[super dealloc]cocoa.UnusedIvars警告永远不会使用的私有变量cocoa.VariadicMethodTypes检查是否将非 ObjC 类型传递给只期望 ObjC 类型的可变集合初始化方法coreFoundation.CFError检查 CFErrorRef 参数的使用情况coreFoundation.CFNumber检查 CFNumber api 的正确使用coreFoundation.CFRetainRelease检查 CFRetain/CFRelease/CFMakeCollectable 的空参数coreFoundation.containers.OutOfBounds当使用 CFArray api 时检查索引越界coreFoundation.containers.PointerSizedValues如果 CFArray, CFDictionary, CFSet 使用非指针大小的值创建,则发出警告
clang-analyzer-FuchsiaHandleChecker句柄标识资源。与指针类似,它们可以泄漏、双重释放或在释放后使用。此检查试图查找此类问题
clang-analyzer-WebKitRefCntblBaseVirtualDtor所有用作基类的未计数类型都必须具有虚析构函数。引用计数类型通过原始指针保存其可引用的数据,并允许从引用计数的派生类型指针隐式向上转换为指向基类型的引用计数指针。这可能导致(动态)派生类型的对象通过指向基类类型(C++标准定义为 UB)的指针被删除,如果基类没有虚析构函数NoUncountedMemberChecker未计数类型的原始指针和引用不能用作类成员。只允许重新计数的类型UncountedLambdaCapturesChecker在lambdas中无法捕获未计数类型的原始指针和引用。只允许重新计数的类型
- 现代化
modernize-avoid-bind使用lambda替换std::bindingmodernize-deprecated-headers将 C 标准库的头文件include替换成 C++style,#include <assert.h>=>#include <cassert>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++98modernize-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_backmodernize-use-equals-delete在 C++98 中,类设计为了实现禁止调用某些特殊的成员函数,通常把它们声明成private。在 C++11 中,只需要在声明中添加=delete,找出所有private的特殊成员函数,并将它们标记成=deletemodernize-use-nullptr用nullptr代替NULLmodernize-use-override对于子类改写父类的virtual方法,在方法后面添加override,并删掉virtual前缀modernize-use-using用using代替typedefmodernize-use-equals-default此检查将特殊成员函数的默认体替换为= default。显式默认的函数声明为优化提供了更多的机会,因为编译器可能会将显式默认的函数视为微不足道的
- Google 代码风格
google-explicit-constructor检查并建议在单参数构造函数中使用explicit关键字。防止隐式转换带来的意外行为google-readability-casting检查并建议使用 C++ 风格的类型转换(如static_cast,dynamic_cast,const_cast和reinterpret_cast)代替 C 风格的类型转换。提高类型转换的安全性和可读性google-build-explicit-make-pair检查make_pair的模板参数是否推导出来了。google-build-namespaces在标头中查找匿名名称空间google-default-arguments检查虚拟方法是否给出默认参数。google-readability-avoid-underscore-in-googletest-name检查在 googletest 测试套件名称和测试宏中的测试名称中是否有下划线google-runtime-int查找有符号整型,并且尝试使用对应的无符号整型代替google-runtime-operator查找一元操作符 & 的重载
- 可读性
readability-braces-around-statements检查判断语句和循环语句的代码提是否在大括号内readability-non-const-parameter该检查查找指针类型的函数形参,可以将其更改为const类型的指针,也就是常量指针readability-avoid-const-params-in-decls检查函数声明是否具有顶层const形参readability-const-return-type检查具有const限定返回类型的函数,并建议删除const关键字。这样使用const通常是多余的,并且会妨碍有价值的编译器优化readability-container-size-empty检查对size()/length()方法的调用是否可以替换为对empty()的调用。readability-convert-member-functions-to-static查找可以设置为静态的非静态成员函数,因为这些函数不使用thisreadability-delete-null-pointer在检查指针是否存在的if语句中检查,然后删除该指针。该检查是不必要的,因为删除空指针没有效果readability-deleted-default检查标记为= default的构造函数和赋值操作符是否被编译器实际删除readability-make-member-function-const查找可以设置为const的非静态成员函数,因为这些函数没有以非const的方式使用它readability-misplaced-array-index此检查警告不寻常的数组索引语法readability-qualified-auto向推导为指针的自动类型化变量添加指针限定条件。LLVM 编码标准建议,如果自动类型化变量是指针,则应明确表示。当类型被推断为指针时,此检查将auto转换为auto *readability-redundant-access-specifiers查找包含冗余成员(字段和方法)访问说明符的类,结构和联合readability-redundant-control-flow查找在不返回值的函数末尾有返回语句,这样的返回语句是多余的readability-redundant-function-ptr-dereference查找函数指针的冗余解引用readability-redundant-smartptr-get查找并删除对智能指针的get()方法的冗余调用readability-redundant-string-cstr查找对std::string::c_str()和std::string::data()的不必要调用readability-redundant-string-init查找不必要的字符串初始化readability-static-definition-in-anonymous-namespace在匿名命名空间中查找静态函数和变量定义,不能存在静态函数和变量readability-string-compare使用compare方法查找字符串比较,不再使用compare来比较字符串,而是直接使用=,!=来比较readability-uniqueptr-delete-release将delete和<unique_ptr>.release()替换为<unique_ptr> = nullptr。后者更短,更简单,并且不需要使用原始指针 apireadability-redundant-member-init查找不必要的成员初始化,因为如果不存在相同的默认构造函数,则会调用这些初始化readability-simplify-subscript-expr这种检查简化了下标表达式。目前这包括调用.data()并立即执行数组下标操作以获取单个元素,在这种情况下,只需调用operator[]就足够了readability-simplify-boolean-expr查找包含布尔常量的布尔表达式,并将其简化为直接使用适当的布尔表达式。应用德摩根定理简化布尔表达式readability-inconsistent-declaration-parameter-name查找参数名称不同的函数声明,在不同文件中函数声明中的形参不一样的情况readability-identifier-naming此检查将尝试在标识符命名上强制执行编码准则。它支持以下一种套管类型,并在检测到不匹配时尝试从一种转换为另一种lower_case小写下划线UPPER_CASE大写下划线camelBack小写开头驼峰CamelCase大驼峰camel_Snake_Back小驼峰+下划线Camel_Snake_Case大驼峰+下划线aNy_CasELeading_upper_snake_case大写开头+小写下划线
- CERT 安全编码标准
cert-dcl21-cppcert-dcl50-cpp此检查标记c风格可变函数的所有函数定义(但不标记声明)cert-env33-c此检查标记对system(),popen()和_popen()的调用,它们执行命令处理程序。它不会用空指针参数标记对system()的调用,因为这样的调用会检查是否存在命令处理器,但实际上不会尝试执行命令cert-err34-c此检查标记对字符串到数字转换函数的调用,这些函数不验证转换的有效性,例如atoi()或scanf()。它不标记对strtol()或其他相关转换函数的调用,这些函数确实执行了更好的错误检查cert-err52-cpp此检查标记所有涉及setjmp()和longjmp()的调用表达式。cert-flp30-c此检查标记归纳表达式为浮点类型的循环cert-mem57-cpp当类型具有扩展对齐(大于基本对齐)时,此检查标记使用默认操作符new。(如果请求的对齐小于或等于基本对齐,则默认操作符new保证提供正确的对齐)。只有在操作符new不是用户定义的并且不是位置new的情况下(原因是在这些情况下,我们假设用户提供了正确的内存分配)才会检测到cert-msc50-cpp伪随机数生成器使用数学算法生成具有良好统计特性的数字序列,但生成的数字并不是真正随机的。rand()函数接受一个种子(数字),对其进行数学运算并返回结果。通过操纵种子,结果是可以预测的。这个检查警告std::rand()的使用cert-oop58-cpp在复制构造函数和复制赋值操作符中查找对复制对象及其直接或间接成员的赋值
- Bug 检测
bugprone-undelegated-constructor查找构造函数中临时对象的创建,这些对象看起来像对同一类的另一个构造函数的函数调用,用户最有可能使用委托构造函数或基类初始化项。bugprone-macro-parentheses查找由于缺少括号而可能产生意外行为的宏bugprone-macro-repeated-side-effects检查宏中具有副作用的重复参数bugprone-forward-declaration-namespace检查未使用的前向声明是否在错误的命名空间中。该检查检查所有未使用的前向声明,并检查是否存在同名的声明/定义,这可能表明前向声明位于可能错误的名称空间中bugprone-bool-pointer-implicit-conversion根据从bool指针到bool指针的隐式转换检查条件bugprone-misplaced-widening-cast当将计算结果强制转换为更大的类型时,此检查将发出警告。如果cast的目的是为了避免精度的损失,那么cast是错位的,并且可能会有精度的损失。否则cast是无效的bugprone-argument-comment检查实参注释是否与形参名称匹配bugprone-bad-signal-to-kill-thread当线程通过引发SIGTERM信号终止时,查找pthread_kill函数调用,该信号会终止整个进程,而不仅仅是单个线程。使用除SIGTERM以外的任何信号bugprone-copy-constructor-init查找未调用基类复制构造函数的复制构造函数bugprone-dangling-handle检测值句柄中的悬空引用,如std::string_view。这些悬空引用可能是由临时值构造句柄的结果,其中临时句柄在创建后很快被销毁bugprone-fold-init-type在像std::accumulate这样的折叠中,检查标志类型不匹配可能导致精度损失。std::accumulate使用后者的类型将输入范围折叠成初始值,默认情况下使用操作符+。bugprone-inaccurate-erase检查erase()方法的不正确使用。像remove()这样的算法实际上并没有从容器中删除任何元素,而是返回一个迭代器,指向容器末尾的第一个冗余元素。这些多余的元素必须使用erase()方法删除。当由于使用不适当的重载而不能删除所有元素时,此检查将发出警告bugprone-incorrect-roundings检查已知会产生不正确舍入的模式的使用情况bugprone-integer-division查找浮点上下文中整数除法可能导致意外精度损失的情况bugprone-misplaced-operator-in-strlen-in-alloc查找在strlen(),strnlen(),strnlen_s(),wcslen(),wcsnlen()和wcsnlen_s()的参数中添加1的字符串而不是结果的情况,并且该值用作内存分配函数(malloc(),calloc(),realloc(),alloca())或 C++ 中的新[]运算符的参数。即使这些函数中的一个(new[]操作符除外)被常量函数指针调用,该检查也会检测错误情况。将参数加 1 和strlen()类函数的结果的情况将被忽略,整个加法被额外的圆括号包围的情况也是如此bugprone-misplaced-pointer-arithmetic-in-alloc查找在内存分配函数(malloc(),calloc(),realloc(),alloca())的结果中添加或减去整数表达式而不是其参数的情况。即使这些函数中的一个被常量函数指针调用,检查也会检测错误情况bugprone-move-forwarding-reference如果在转发引用上调用std::move,则发出警告bugprone-multiple-statement-macro检测在无括号条件中使用的多个语句宏。只有宏的第一个语句将在条件语句中,其他语句将无条件执行bugprone-parent-virtual-call检测并修复对父类虚拟方法的调用,而不是对重写父类虚拟方法的调用bugprone-posix-return检查是否有任何调用pthread_*或posix_*函数(posix_openpt除外)期望负返回值。这些函数成功时返回 0,失败时返回errno,但是他们返回值仅为正数bugprone-reserved-identifier检查为实现保留使用的标识符的用法。C 标准还保留了以双下划线开头的名称,而 C++ 标准加强了这一点,保留了出现在任何地方的双下划线名称。所以不能使用这些标识符bugprone-signed-char-misuse查找可能指示编程错误的signed char -> int转换。带符号字符的基本问题是,它可能将非 ascii 字符存储为负值。当显式转换和隐式转换发生时,这种行为都可能导致对所编写代码的误解bugprone-sizeof-container该检查在 STL 容器类型的表达式中查找sizeof的用法。*sizeof() doesn't return the size of the container.*bugprone-sizeof-expression检查查找sizeof表达式的用法,这些用法最有可能是错误的。sizeof操作符产生其操作数的大小(以字节为单位),该操作数可以是表达式或类型的括号名称。误用此操作符可能会导致错误和可能的软件漏洞bugprone-string-constructor查找可疑且可能错误的字符串构造函数bugprone-string-integer-assignment查找用整形对std::basic_string<CharT>(std::string,std::wstring等)的赋值bugprone-string-literal-with-embedded-nul查找包含NULL字符的字符串字面值并验证其用法bugprone-suspicious-enum-usage检查器检测枚举可能被滥用的各种情况(作为位掩码)bugprone-suspicious-include当包含引用了看起来像是源文件的内容时,检查会检测到各种情况,这通常会导致难以跟踪的 ODR 违规bugprone-suspicious-memset-usage此检查查找参数中可能存在错误的memset()调用bugprone-suspicious-missing-comma并排放置的字符串字面值在翻译阶段6(在预处理器之后)被连接起来。此特性用于表示多行上的长字符串文字bugprone-suspicious-string-compare查找运行时字符串比较函数的可疑用法。该检查在 C 和 C++ 中有效bugprone-swapped-arguments通过检查隐式转换查找可能交换的参数。它分析传递给函数的参数类型,并将它们与相应参数的预期类型进行比较。如果存在不匹配或指示潜在交换的隐式转换,则会引发警告bugprone-terminating-continue检测带有continue语句的条件总是求值为false的do while循环,因为该continue语句有效地终止了循环bugprone-throw-keyword-missing警告可能缺少throw关键字。如果创建了一个临时对象,但该对象的类型派生于一个名称中包含EXCEPTION,EXCEPTION或EXCEPTION的类相同,我们可以假设程序员的意图是抛出该对象bugprone-too-small-loop-variable检测那些具有太小类型的循环变量的for循环,这意味着该类型不能表示迭代范围内的所有值。也就是循环使用的数据类型大小小于循环次数bugprone-undefined-memory-manipulation查找对non-TriviallyCopyable对象调用内存操作函数memset(),memcpy()和memmove()导致未定义行为bugprone-unhandled-self-assignment查找用户定义的复制赋值操作符,这些操作符不通过显式检查自赋值或使用复制-交换或复制-移动方法来保护代码免受自赋值。默认情况下,这个检查只搜索那些有指针或C数组字段的类,以避免误报。在指针或C数组的情况下,如果没有小心地编写复制赋值操作符,则自复制赋值很可能会破坏对象bugprone-unused-raii查找看起来像 RAII 对象的临时对象bugprone-unused-return-value警告未使用的函数返回值。带有赋值语义的操作符重载将被忽略bugprone-use-after-move如果对象在移动后被使用,则发出警告bugprone-virtual-near-miss如果函数与基类中的虚函数近似(即名称非常相似且函数签名相同),则发出警告
- C++ 核心指南
cppcoreguidelines-narrowing-conversionscppcoreguidelines-pro-type-reinterpret-cast该检查标记 C++ 代码中所有reinterpret_cast的使用。cppcoreguidelines-pro-type-member-init****该检查标记了用户提供的构造函数定义,这些定义没有初始化所有字段,这些字段将在默认构造函数中处于未定义状态,例如内置函数,指针和记录类型,而用户提供的默认构造函数中至少包含一个这样的类型。如果这些字段没有初始化,构造函数将使一些内存处于未定义状态
- 杂项
misc-unconventional-assign-operator查找返回值或参数类型错误的赋值操作符声明,以及返回值类型良好但返回语句错误的赋值操作符定义misc-unused-parameters查找未使用的函数参数。未使用的参数可能表示代码中存在错误(例如,当使用不同的参数时)。如果函数的所有调用者都在相同的翻译单元中并且可以更新,则建议修复注释参数名称或完全删除参数misc-throw-by-value-catch-by-reference查找违反按值抛出,按引用捕获规则的情况misc-misplaced-const当const限定符应用于类型定义/使用指针类型而不是指针类型时,该检查会进行诊断,因为这样的结构通常会误导开发人员,因为const应用于指针而不是指针数据misc-redundant-expression检测多余的表达式,这些表达式通常是由于复制粘贴而导致的错误misc-static-assert如果条件在编译时可求值,则将assert()替换为static_assert()misc-uniqueptr-reset-release查找并替换unique_ptr::reset(release())为std::move()misc-unused-alias-decls查找未使用的命名空间别名声明misc-unused-using-decls查找未使用的using声明
hicpphicpp-exception-baseclass确保throw表达式中的每个值都是std::exception的实例hicpp-ignored-remove-result确保std::remove,std::remove_if和std::unique的结果不会被忽略。变异算法std::remove,std::remove_if和std::unique都是通过交换或移动它们所操作的范围内的元素来进行操作的。完成后,它们返回一个指向最后一个有效元素的迭代器。在大多数情况下,正确的做法是将此结果用作调用std::erase的第一个操作数hicpp-multiway-paths-covered此检查发现代码路径未完全覆盖的情况。此外,如果代码更清晰,建议使用if而不是switch。缺失最后一个else分支的if-else if链可能会导致意外的程序执行,并成为逻辑错误的结果。如果遗漏的else分支是有意的,可以将其保留为空,并添加澄清注释。在某些代码库中,此警告可能会产生噪声,因此默认情况下禁用此警告hicpp-no-assembler检查汇编语句。应该避免使用内联汇编,因为它限制了代码的可移植性hicpp-signed-bitwise查找对有符号整数类型的位操作的使用,这可能导致未定义或实现定义的行为
performanceperformance-faster-string-find优化调用std::string::find()和友元,当传递的指针是单个字符串字面值时。字符文字重载更有效performance-for-range-copy查找 C++11 中循环变量在每次迭代中复制的范围,但通过const引用获得它就足够了。这个检查仅适用于复制成本较高的类型的循环变量,这意味着它们不是普通的可复制的,或者具有非普通的复制构造函数或析构函数performance-implicit-conversion-in-loop此警告出现在具有const ref类型循环变量的基于范围的循环中,其中变量的类型与迭代器返回的类型不匹配。这意味着会发生隐式转换,例如,这可能导致代价高昂的深度拷贝performance-inefficient-algorithm警告在关联容器上低效地使用 STL 算法。关联容器将一些算法作为方法实现,这些方法应该优先于算法头中的算法。这些方法可以利用元素的顺序performance-inefficient-vector-operation查找可能导致不必要内存重新分配的低效std::vector操作(例如push_back, emplace_back)performance-move-constructor-init检查标志用户定义的移动构造函数,这些构造函数具有通过复制构造函数而不是移动构造函数初始化成员或基类的变量初始化器performance-no-automatic-move在某些条件下,从函数返回时将自动移出局部值。一个常见的错误是将局部左值变量声明为const,这会阻止移动performance-trivially-destructible查找可以通过删除外部默认析构函数声明而使其成为trivially destructible类型的析构函数。trivially destructible类型就是那些其析构函数不执行任何操作的类型,这在资源管理性能优化与 C 语言接口等方面很重要,这种类型允许编译器进行更加高效的内存管理和数据传递。performance-unnecessary-copy-initialization查找使用非平凡可复制类型的复制构造函数初始化的局部变量声明,但它足以获得const引用。非平凡可复制类型是指那些具有自定义拷贝构造函数,拷贝赋值运算符,析构函数或移动构造函数/赋值运算符之一的类型。这些类型在复制时可能需要执行额外的操作,比如内存分配,资源管理等,这些操作可能会比简单地获取一个引用要昂贵得多
boostboost-use-to-string该检查查找使用boost::lexical_cast从整数类型到std::string或std::wstring的转换,并将其替换为对std::to_string和std::to_wstring的调用。boost-use-ranges检测对标准库迭代器算法的调用,这些调用可以替换为 Boost 范围版本
- 一般来说会添加额外的一项为
-*,意为未提到的都默认不生效
WarningsAsErrors
这个就是将对应的警告设置为错误,参数与上述的 Checks 中的一致
CheckOptions
这里面可以添加一些参数,主要是一些用户个性化定义的参数
readability-identifier-namingAbstractClassCase抽象类名称的命名规则ClassCase类名称的命名规则ClassConstantCase类常量名大小写命名规则ClassMemberCase类成员大小写命名规则ClassMethodCase类方法命名规则ConceptCaseconcept修饰符修饰的变量的命名规则ConstantCase常量变量的命名规则ConstantMemberCase常量成员的命名规则ConstantParameterCase常量形式参数的命名规则ConstantPointerParameterCase常量指针形式参数的命名规则ConstexprFunctionCaseconstexpr修饰的函数的命名规则ConstexprMethodCaseconstexpr修饰的方法的命名规则ConstexprVariableCaseconstexpr修饰的变量的命名规则EnumCase枚举名称的命名规则EnumConstantCase枚举常量的命名规则FunctionCase函数命名规则GlobalConstantCase全局常量命名规则GlobalConstantPointerCase全局指针常量命名规则GlobalFunctionCase全局函数命名规则GlobalPointerCase全局指针命名规则GlobalVariableCase全局变量命名规则InlineNamespaceCase内联命名空间名称命名规则LocalConstantCase局部常量名称命名规则LocalConstantPointerCase局部常量指针名称命名规则LocalPointerCase局部指针名称命名规则LocalVariableCase局部变量名称命名规则MacroDefinitionCase宏定义命名规则MemberCase成员名命名规则MethodCase方法名命名规则NamespaceCase命名空间命名规则ParameterCase形式参数名命名规则ParameterPackCase参数包名命名规则,也就是多可变参数类型的参数名PointerParameterCase指针形参命名规则PrivateMemberCase私有成员命名规则PrivateMethodCase私有方法命名规则ProtectedMemberCase保护成员命名规则ProtectedMethodCase保护方法命名规则PublicMemberCase公开成员命名规则PublicMethodCase公开方法命名规则ScopedEnumConstantCase限定范围的枚举常量名命名规则StaticConstantCase静态常量命名规则StaticVariableCase静态变量命名规则StructCase结构体命名规则TemplateParameterCase模板参数命名规则TemplateTemplateParameterCase模板模板参数命名规则TypeAliasCase类型别名命名规则TypedefCasetypedef名称命名规则TypeTemplateParameterCase类型模板参数名称命名规则UnionCase联合体名称命名规则ValueTemplateParameterCase值模板参数名称命名规则VariableCase变量名称命名规则VirtualMethodCase虚方法命名规则*IgnoredRegexp对于匹配此正则表达式的对应名称标识符,不会强制执行标识符命名检查*HungarianPrefix启用后,检查将确保声明的标识符具有基于声明类型的匈牙利符号前缀*Prefix对应标识符的前缀*Suffix对应标识符的后缀AggressiveDependentMemberLookup当设置为true时,检查将在依赖基类中查找需要更改的依赖成员引用。这可能导致模板专门化出错,因此默认值为falseCheckAnonFieldInParent当设置为true时,匿名记录中的字段(即匿名联合和结构体)将被视为封闭作用域中的名称,而不是匿名记录的公共成员,以进行名称检查GetConfigPerFile当为true时,检查将查找声明标识符的配置。当包含的头文件使用不同的样式时非常有用。默认值为trueIgnoreMainLikeFunctions当设置为true时,与main或wmain具有相似签名的函数将不会对其参数的名称进行检查。默认值为false
一个可供参考的版本
1 | Checks: '-*, |
本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 LuosBlog!



