前文介绍CodeChecker时,使用到了Clang-Tidy,我们来看看这个工具是什么,如何使用。主要是为了了解下背后的知识点,使用CodeChecker已经很好用了。
1、Clang-Tidy介绍
Clang-Tidy是一个基于Clang的C++ “linter” 工具。绝大部分lint工具只能在出现问题的代码地方给出提示,之后需要人为修改,而clang-tidy则能够自动修复功能。当然这个如何修复,需要该check作者提供。clang-tidy 的目的是为诊断和修复典型编程错误提供一个可扩展的框架,如样式违规、接口滥用或可以通过静态分析推断的缺陷。clang-tidy 是模块化的,提供了便利的接口来增加新的check检查器。如果用户想往clang-tidy添加一个新的检测功能,只需要编写一个clang-tidy check实现。每一个check检测一种问题,例如检测某个违反Code style的模式,检测某些API不正确使用的方法等。
2、Clang-Tidy使用入门
clang-tidy是一个基于LibTooling的工具,如果为项目设置编译命令数据库,clang-tidy更容易工作。如何设置编译命令数据的例子,请参阅如何设置 LLVM 的工具。您还可以在命令行--
符号之后指定编译选项
clang-tidy有自己的checks检查器,也可以运行Clang Static Analyzer的checks检查器。每个check检查器都有一个名称,可以使用选项-checks=选择要运行的检查,该选项指定了以逗号分隔的正和 负(前缀为-)的globs模式。正模式为要添加的检查器集合,负的模式会删除检查器集合。例如,下面的例子将禁用所有的检查(-*),并且启用除 clang-analyzer-cplusplus* 之外的所有匹配clang-analyzer-*模式的检查器。
命令行选项-list-checks会列出所有已启用的检查。当不带选项-checks=时,它会显示默认启用的检查器。使用-checks=*时,会查看所有可用的检查器;指定具体值-checks=XXX时,会查看匹配该模式值的检查器。可用自己体验下。
目前有以下检查组:
(1)具体示例
可以使用之前的hello.c,看下怎么使用。如上文所说,一般不会直接使用clang-tidy,使用CodeChecker更好一些,需要了解下即可。
执行如下命令:
选择一条命令执行,输出类似下文的输出。可以看到输出了被各种检查器诊断出来的缺陷或者告警信息。
3、检查器分组
目前有以下检查器分组。不同的分组针对不同的检查对象,不同的开源项目Android、Fuchsia等,不同的编码规范等,可以针对性启用。
Name prefix | Description |
| Checks related to Abseil library. |
| Checks related to OpenCL programming for FPGAs. |
| Checks related to Android. |
| Checks related to Boost library. |
| Checks that target bug-prone code constructs. |
| Checks related to CERT Secure Coding Guidelines. |
| Clang Static Analyzer checks. |
| Checks related to concurrent programming (including threads, fibers, coroutines, etc.). |
| Checks related to C++ Core Guidelines. |
| Checks related to Darwin coding conventions. |
| Checks related to Fuchsia coding conventions. |
| Checks related to Google coding conventions. |
| Checks related to High Integrity C++ Coding Standard. |
| Checks related to the Linux Kernel coding conventions. |
| Checks related to the LLVM coding conventions. |
| Checks related to the LLVM-libc coding standards. |
| Checks that we didn’t have a better category for. |
| Checks that advocate usage of modern (currently “modern” means “C++11”) language constructs. |
| Checks related to MPI (Message Passing Interface). |
| Checks related to Objective-C coding conventions. |
| Checks related to OpenMP API. |
| Checks that target performance-related issues. |
| Checks that target portability-related issues that don’t relate to any particular coding style. |
| Checks that target readability-related issues that don’t relate to any particular coding style. |
| Checks related to Zircon kernel coding conventions. |
Clang语言的静态分析和clang-tidy检查器的静态分析类似。Clang的静态分析会被clang-tidy展示,也会通过选项-checks=被过滤掉。然而,这些检查器的过滤不会影响编译参考,因此它不能打开已经在构建配置中关闭的Clang告警开关。-warnings-as-errors= 选项会把-checks=选项的检查器检测出的告警信息升级为错误信息。
Clang静态分析诊断的检查器名称以clang-diagnostic-开头。对应每一个告警选项的分析诊断,其名称格式为are named clang-diagnostic-<warning-option>。例如,被编译选项-Wliteral-conversion控制的Clang告警,会被名为clang-diagnostic-literal-conversion的检查器来分析并报告。
The -fix flag instructs clang-tidy to fix found errors if supported by corresponding checks.
有个比较重要的选项,--fix,开启这个选项clang-tidy会修复发现的错误,在对应的检查器支持的情况下。哪些检查器支持自动修复,可以参考下文中检查器列表中的Offers fixes字段。使用clang-tidy --help可以查看帮助信息,我们这里主要看下--fix相关的帮助信息。开启这个选项--fix,clang-tidy会修复发现的错误。没有指定--fix-errors选项时,如果发现编译错误,clang-tidy会跳过修复。在指定--fix-errors选项时,即使发现编译错误,也会继续修复。
没有亲自体验过,执行下面的命令,如果发现示例文件中的未使用的声明using declarations
的告警信息,就会自动修复删除掉。
4、检查器列表
Clang-Tidy 现在支持<mark>四五百个</mark>Checks检查器,详细列表可以访问clang-tidy - Clang-Tidy Checks — Extra Clang Tools 16.0.0git documentation获取。可以看到对于这些检查器,是否支持自动修复错误。对于这些检查器,也是很好的学习资源,可以看看这些检查器的会修复什么类型的缺陷,以后写代码的时候,避免编写这些的缺陷,提升编程能力和素养。
- Clang-Tidy Checks列表片段
Name | Offers fixes |
Yes | |
… | … |
Yes | |
… | … |
Yes | |
Yes | |
… | … |
Yes | |
… | … |
… | … |
5、学习些检查器
(1)readability-duplicate-include
详细链接在https://clang.llvm.org/extra/clang-tidy/checks/readability/duplicate-include.html。
Looks for duplicate includes and removes them. The check maintains a list of included files and looks for duplicates. If a macro is defined or undefined then the list of included files is cleared.
查找重复的include语句并删除它们。该检查器维护一个include文件列表,然后查找重复项。如果已定义或取消定义宏,include文件列表会被清理。
示例如下:
修复方法:
如下示例,因为中间出现宏定义,不会识别出重复include,代码不会被自动修复。
(2)readability-delete-null-pointer
详细链接在https://clang.llvm.org/extra/clang-tidy/checks/readability/delete-null-pointer.html。
在if语句里,如果检测指针是否存在,然后删除。这样的检查是没有必要的,因为删除空指针没有任何左右,属于可以删除的冗余代码。
(3)misc-unused-parameters
详细链接在https://clang.llvm.org/extra/clang-tidy/checks/misc/unused-parameters.html。
查找未使用的函数参数。未使用的参数可能意味着代码缺陷,例如,当使用不同的参数代替时。建议的修复要么是注释参数名称或完全删除参数,只要函数的调用方位于同一翻译单元中,并且可以修改。
该检查器类似于编译器诊断选项-Wunused-parameter,可以用于准备代码库以启用该诊断。默认情况下,该检查器比较宽松。
示例1:
示例2: