我最近开始尝试使用llvm的clang-tidy
工具。现在我试图压制来自第三方库代码的错误警告。为此,我想使用命令行选项
-header-filter=<string>
或-line-filter=<string>
但到目前为止还没有成功。因此,对于时间有限的人,我会在开头提出这个问题,然后再解释我已经尝试过的问题。
我需要向clang-tidy
工具提供哪些选项来取消某个行和文件的警告?
如果不可能
什么选项可以抑制来自外部头文件的警告?
我对clang-tidy的原始调用看起来像这样
clang-tidy-3.8 -checks=-*,clang-analyzer-*,-clang-analyzer-alpha* -p Generated/LinuxMakeClangNoPCH Sources/CodeAssistant/ModuleListsFileManipulator_fixtures.cpp
并且我要抑制的产生警告的第一行看起来像这样
.../gmock/gmock-spec-builders.h:1272:5: warning: Use of memory after it is freed [clang-analyzer-cplusplus.NewDelete]
return function_mocker_->AddNewExpectation(
gmock人告诉我这是假阳性,所以我想压制它。首先,我尝试使用-line-filter=<string>
选项。文档说:
-line-filter=<string> - List of files with line ranges to filter the
warnings. Can be used together with
-header-filter. The format of the list is a JSON
array of objects:
[
{"name":"file1.cpp","lines":[[1,3],[5,7]]},
{"name":"file2.h"}
]
我假设过滤掉了给定行中的警告。但是doc doesent说他们是否被过滤掉了。 在一些fiddeling arround之后,我使用内容
创建了一个.json文件[
{"name":"gmock-spec-builders.h","lines":[[1272,1272]]}
]
并将命令行修改为
clang-tidy-3.8 -checks=-*,clang-analyzer-*,-clang-analyzer-alpha* -p Generated/LinuxMakeClangNoPCH -line-filter="$(< Sources/CodeAssistant/CodeAssistant_ClangTidySuppressions.json)" Sources/CodeAssistant/ModuleListsFileManipulator_fixtures.cpp
将文件的内容写入参数。这会抑制警告,但不仅是此警告,而是来自ModuleListsFileManipulator_fixtures.cpp文件的所有警告。我尝试了更多的东西,但我无法使它工作。
所以我尝试了-header-filter=<string>
选项。这里的文档指出,必须提供一个正则表达式,该表达式匹配应显示诊断的所有头文件。好吧,我想,让我们使用一个regualar表达式来匹配与分析的.cpp文件在同一文件夹中的所有内容。虽然它可能会删除我使用外部标头错误导致的警告,但我可以接受它。
这里我不确定正则表达式是否必须匹配完整(绝对)文件名或仅是文件名的一部分。我试过了
-header-filter=.*\/CodeAssistant\/.*.h
匹配CodeAssistant文件夹中的所有绝对头文件名,但它不会抑制gmock-spec-builders.h文件中的警告。
因此,我希望单独抑制每个警告,以便我可以确定每个警告是否是真正的问题,但如果这是不可能的,我也可以抑制来自整个外部标题的警告。
感谢您的时间。
答案 0 :(得分:4)
我发现了另一种非侵入性的方法(不向第三方库中添加// NOLINT
)来抑制警告。例如,当前版本的Google测试未通过某些cppcoreguidelines-*
检查。以下代码可让您验证当前的diff,排除包含gtest宏的行:
git diff -U3 | sed '
s/^+\( *TEST(\)/ \1/;
s/^+\( *EXPECT_[A-Z]*(\)/ \1/;
s/^+\( *ASSERT_[A-Z]*(\)/ \1/;
' | recountdiff | interdiff -U0 /dev/null /dev/stdin | clang-tidy-diff.py -p1 -path build
它假定文件build/compile_commands.json
是在之前生成的,并且clang-tidy-diff.py
在您的环境中可用。 patchutils中的recountdiff
和interdiff
是用于操作补丁的标准工具。
该脚本的工作方式如下:
git diff -U3
生成具有3条上下文行的补丁。sed ...
从不需要的行中删除前缀+
,即将其转换为上下文。recountdiff
在块标题中的正确偏移量(在第一个范围内)。interdiff -U0 /dev/null /dev/stdin
只是从补丁中删除所有上下文行。结果,它拆分了最初的块。clang-tidy-diff.py
仅从块头读取第二个范围,并通过clang-tidy
选项将它们传递到-line-filter
。 UPD :为interdiff
提供足够数量的上下文行很重要,否则可能会在结果中产生一些瑕疵。请参见man interdiff
的引用:
为获得最佳结果,差异必须至少具有三行上下文。
特别是,我发现git diff -U0 | ... | interdiff
在拆分块后会生成一些虚假的文字$!otj
。
答案 1 :(得分:2)
我通过将 // NOLINT 添加到 gmock-spec-builders.h的 1790 来解决了这个问题
这是差异:
--- gmock-spec-builders.orig.h 2016-09-17 09:46:48.527313088 +0200
+++ gmock-spec-builders.h 2016-09-17 09:46:58.958353697 +0200
@@ -1787,7 +1787,7 @@
#define ON_CALL(obj, call) GMOCK_ON_CALL_IMPL_(obj, call)
#define GMOCK_EXPECT_CALL_IMPL_(obj, call) \
- ((obj).gmock_##call).InternalExpectedAt(__FILE__, __LINE__, #obj, #call)
+ ((obj).gmock_##call).InternalExpectedAt(__FILE__, __LINE__, #obj, #call) // NOLINT
#define EXPECT_CALL(obj, call) GMOCK_EXPECT_CALL_IMPL_(obj, call)
#endif // GMOCK_INCLUDE_GMOCK_GMOCK_SPEC_BUILDERS_H_
对于这个补丁的上游(我在代码中看到其他NOLINT)或发布一个与整齐的人一起发布错误报告会很好。
答案 2 :(得分:1)
我还遇到了原始补丁没有覆盖的其他一些案例。在尝试修复此问题时,我还遇到了clang-tidy(https://llvm.org/bugs/show_bug.cgi?id=30565)中的分段错误。目前我还没有成功地压制所有错误。
如果/当我找到它时,我会在这里提供更新的答案:)
答案 3 :(得分:1)
使用-isystem
而不是-I
来设置系统和第三方包含路径。 -I
仅应用于包含正在构建的项目中的代码。
这是使clang-tidy
忽略外部代码中所有错误的唯一要求。所有其他答案(在撰写本文时)都是解决问题的拙劣解决方法,这些问题可以用-isystem
完美解决。
如果您使用CMake或Meson之类的构建系统,它将自动为您正确设置-I
和-isystem
。
-isystem
也是一种用于告诉编译器(至少是GCC和Clang)不是您的代码的机制。如果您开始使用-isystem
,还可以启用更多的编译器警告,而不会从外部代码中获得“误报”。
答案 4 :(得分:0)
我无法通过命令行选项获得我想要的内容,因此我将使用cpp文件中的// NOLINT
注释,这些注释是由接受的答案提出的。
我也会尝试将修复程序推送到googletest。
我发现-line-filter
选项中的行被过滤掉了。
但是,无论如何,给出具体的线条并不能解决我的问题。
我宁愿需要像在Valgrind中实现的抑制机制。