静态分析工具Clang Static Analyzer (4) Clang-Tidy

系统 OpenHarmony
Clang-Tidy是一个基于Clang的C++ “linter” 工具。绝大部分lint工具只能在出现问题的代码地方给出提示,之后需要人为修改,而clang-tidy则能够自动修复功能。

想了解更多关于开源的内容,请访问:

​51CTO 开源基础软件社区​

​https://ost.51cto.com​

前文介绍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 test.cpp -- -Imy_project/include -DMY_DEFINES ...

clang-tidy有自己的checks检查器,也可以运行Clang Static Analyzer的checks检查器。每个check检查器都有一个名称,可以使用选项-checks=选择要运行的检查,该选项指定了以逗号分隔的正和 负(前缀为-)的globs模式。正模式为要添加的检查器集合,负的模式会删除检查器集合。例如,下面的例子将禁用所有的检查(-*),并且启用除 clang-analyzer-cplusplus* 之外的所有匹配clang-analyzer-*模式的检查器。

$ clang-tidy test.cpp -checks=-*,clang-analyzer-*,-clang-analyzer-cplusplus*

命令行选项-list-checks会列出所有已启用的检查。当不带选项-checks=时,它会显示默认启用的检查器。使用-checks=*时,会查看所有可用的检查器;指定具体值-checks=XXX时,会查看匹配该模式值的检查器。可用自己体验下。

clang-tidy -list-checks
clang-tidy -list-checks -checks=*
clang-tidy -list-checks -checks=-*,clang-analyzer-*,-clang-analyzer-cplusplus*

目前有以下检查组:

(1)具体示例

可以使用之前的hello.c,看下怎么使用。如上文所说,一般不会直接使用clang-tidy,使用CodeChecker更好一些,需要了解下即可。

int main() {
int x = 7 / 0; // bug here
return 0;
}

执行如下命令:

clang-tidy hello.c
clang-tidy --checks=* hello.c

选择一条命令执行,输出类似下文的输出。可以看到输出了被各种检查器诊断出来的缺陷或者告警信息。

zhushangyuan@DESKTOP-RPE9R4O:~/CSA$ clang-tidy --checks=* hello.c
5 warnings generated.
/home/zhushangyuan/CSA/hello.c:2:7: warning: Value stored to 'x' during its initialization is never read [clang-analyzer-deadcode.DeadStores]
int x = 7 / 0; // bug here
^
/home/zhushangyuan/CSA/hello.c:2:7: note: Value stored to 'x' during its initialization is never read
/home/zhushangyuan/CSA/hello.c:2:11: warning: 7 is a magic number; consider replacing it with a named constant [cppcoreguidelines-avoid-magic-numbers,readability-magic-numbers]
int x = 7 / 0; // bug here
^
/home/zhushangyuan/CSA/hello.c:2:13: warning: Division by zero [clang-analyzer-core.DivideZero]
int x = 7 / 0; // bug here
^
/home/zhushangyuan/CSA/hello.c:2:13: note: Division by zero
/home/zhushangyuan/CSA/hello.c:2:13: warning: division by zero is undefined [clang-diagnostic-division-by-zero]
int x = 7 / 0; // bug here
^

3、检查器分组

目前有以下检查器分组。不同的分组针对不同的检查对象,不同的开源项目Android、Fuchsia等,不同的编码规范等,可以针对性启用。

Name prefix

Description

​abseil-​

Checks related to Abseil library.

​altera-​

Checks related to OpenCL programming for FPGAs.

​android-​

Checks related to Android.

​boost-​

Checks related to Boost library.

​bugprone-​

Checks that target bug-prone code constructs.

​cert-​

Checks related to CERT Secure Coding Guidelines.

​clang-analyzer-​

Clang Static Analyzer checks.

​concurrency-​

Checks related to concurrent programming (including threads, fibers, coroutines, etc.).

​cppcoreguidelines-​

Checks related to C++ Core Guidelines.

​darwin-​

Checks related to Darwin coding conventions.

​fuchsia-​

Checks related to Fuchsia coding conventions.

​google-​

Checks related to Google coding conventions.

​hicpp-​

Checks related to High Integrity C++ Coding Standard.

​linuxkernel-​

Checks related to the Linux Kernel coding conventions.

​llvm-​

Checks related to the LLVM coding conventions.

​llvmlibc-​

Checks related to the LLVM-libc coding standards.

​misc-​

Checks that we didn’t have a better category for.

​modernize-​

Checks that advocate usage of modern (currently “modern” means “C++11”) language constructs.

​mpi-​

Checks related to MPI (Message Passing Interface).

​objc-​

Checks related to Objective-C coding conventions.

​openmp-​

Checks related to OpenMP API.

​performance-​

Checks that target performance-related issues.

​portability-​

Checks that target portability-related issues that don’t relate to any particular coding style.

​readability-​

Checks that target readability-related issues that don’t relate to any particular coding style.

​zircon-​

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选项时,即使发现编译错误,也会继续修复。

--fix                          -
Apply suggested fixes. Without -fix-errors
clang-tidy will bail out if any compilation
errors were found.
--fix-errors -
Apply suggested fixes even if compilation
errors were found. If compiler errors have
attached fix-its, clang-tidy will apply them as
well.

没有亲自体验过,执行下面的命令,如果发现示例文件中的未使用的声明​​using declarations​​的告警信息,就会自动修复删除掉。

// 找出simple.cc中所有没有用到的using declarations并自动fix(删除掉)
$ clang-tidy -checks="-*,misc-unused-using-decls" -fix path/to/simple.cc --

4、检查器列表

Clang-Tidy 现在支持<mark>四五百个</mark>Checks检查器,详细列表可以访问​​clang-tidy - Clang-Tidy Checks — Extra Clang Tools 16.0.0git documentation​​获取。可以看到对于这些检查器,是否支持自动修复错误。对于这些检查器,也是很好的学习资源,可以看看这些检查器的会修复什么类型的缺陷,以后写代码的时候,避免编写这些的缺陷,提升编程能力和素养。

  • Clang-Tidy Checks列表片段

Name

Offers fixes

​abseil-cleanup-ctad​

Yes

​android-cloexec-creat​

Yes

​android-comparison-in-temp-failure-retry​

​boost-use-to-string​

Yes

​bugprone-argument-comment​

Yes

​cert-dcl21-cpp​

Yes

​clang-analyzer-core.DynamicTypePropagation​

5、学习些检查器

在使用clang-tidy检查报告,可以详细了解下检查器的知识,可以有助于我们理解这些检查规则,有助于如何修复。挑选几个。

(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 <memory>
#include <vector>
#include <memory>

修复方法:

#include <memory>
#include <vector>

如下示例,因为中间出现宏定义,不会识别出重复include,代码不会被自动修复。

#undef NDEBUG
#include "assertion.h"
// ...code with assertions enabled

#define NDEBUG
#include "assertion.h"
// ...code with assertions disabled

(2)readability-delete-null-pointer

详细链接在https://clang.llvm.org/extra/clang-tidy/checks/readability/delete-null-pointer.html。

在if语句里,如果检测指针是否存在,然后删除。这样的检查是没有必要的,因为删除空指针没有任何左右,属于可以删除的冗余代码。

int *p;
if (p)
delete p;

(3)misc-unused-parameters

详细链接在https://clang.llvm.org/extra/clang-tidy/checks/misc/unused-parameters.html。

查找未使用的函数参数。未使用的参数可能意味着代码缺陷,例如,当使用不同的参数代替时。建议的修复要么是注释参数名称或完全删除参数,只要函数的调用方位于同一翻译单元中,并且可以修改。

该检查器类似于编译器诊断选项-Wunused-parameter,可以用于准备代码库以启用该诊断。默认情况下,该检查器比较宽松。

示例1:

void a(int i) { /*some code that doesn't use `i`*/ }

// becomes

void a(int /*i*/) { /*some code that doesn't use `i`*/ }

示例2:

static void staticFunctionA(int i);
static void staticFunctionA(int i) { /*some code that doesn't use `i`*/ }

// becomes

static void staticFunctionA()
static void staticFunctionA() { /*some code that doesn't use `i`*/ }

想了解更多关于开源的内容,请访问:

​51CTO 开源基础软件社区​

​https://ost.51cto.com​​。

责任编辑:jianghua 来源: 51CTO 开源基础软件社区
相关推荐

2022-12-13 15:42:56

Clang-Tidy静态分析工具

2022-12-09 15:38:54

Cppcheck静态分析工具

2022-12-08 15:25:10

Clang分析工具CSA

2021-12-27 11:11:30

LLVMSPIR-V后端

2016-12-12 14:19:59

LLVMClangApple

2022-11-24 13:05:27

ClangiOS

2021-01-14 15:49:10

Linux 5.12GCC编译器

2018-04-13 10:56:14

编译器工具开发者

2012-05-22 00:28:21

JavaJava开源开源工具

2021-04-25 18:09:53

Fedora 35编译器开发

2018-03-06 14:33:21

Windows微软编译器

2011-04-11 13:58:09

TCP

2015-07-30 11:36:48

Xcode7ClangAddress San

2018-12-17 16:54:50

开发者技能 Firefox

2020-11-03 10:32:22

编译器工具代码

2021-06-08 13:56:34

工具静态代码

2018-02-25 10:33:46

LLVMSwiftRust

2017-04-19 12:05:59

2021-07-29 06:37:55

KubernetesKubeLinter工具

2016-05-17 13:54:05

点赞
收藏

51CTO技术栈公众号