靜態分析工具Clang Static Analyzer (4) Clang-Tidy
前文介紹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: