clang-tidy: 如何抑制警告?

21

最近我开始尝试使用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"}
                                 ]

我假设给出的代码行中的警告信息被过滤掉了。但是文档并没有说明它们是否被过滤掉。

经过一些尝试,我创建了一个包含内容的 .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>选项。文档中指出,必须提供一个正则表达式,该表达式匹配要显示诊断信息的所有头文件。好吧,我想,让我们使用一个正则表达式,它与分析的.cpp文件所在文件夹中的所有内容匹配。虽然这可能会消除由于我错误地使用外部标头而产生的警告,但我可以接受这一点。
在这里,我不确定正则表达式是否必须与完整(绝对)文件名匹配,还是只需与文件名的一部分匹配。我尝试了:
-header-filter=.*\/CodeAssistant\/.*.h

该模式匹配CodeAssistant文件夹中所有绝对标头文件名,但未抑制gmock-spec-builders.h文件中的警告。

因此,最好逐个抑制每个警告,这样我可以确定每个警告是否是真正的问题,但如果不可能,我也可以抑制整个外部标头文件的警告。

感谢您的时间。

4个回答

6

我找到了另一种不侵入式(无需向第三方库添加// NOLINT)的方法来抑制警告。例如,当前版本的Google Test未通过一些cppcoreguidelines-*检查。以下代码允许您验证当前差异,但排除包含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 已经可从您的环境中获得。用于操作补丁的标准工具是来自patchutilsrecountdiffinterdiff
该脚本的工作流程如下:
  1. git diff -U3 生成具有 3 行上下文的补丁。
  2. sed ... 删除不需要的行的前缀 +,即将其转换为上下文。
  3. recountdiff 在块标题中纠正了第一个范围内的偏移量。
  4. interdiff -U0 /dev/null /dev/stdin 只是从补丁中删除所有上下文行。结果是,它将初始块分割。
  5. clang-tidy-diff.py 只读取块标题中的第二个范围,并通过 -line-filter 选项将它们传递给 clang-tidy
更新: 提供 interdiff 充足的上下文行很重要,否则可能会在结果中产生一些人为痕迹。请参见 man interdiff 中的引用:

为了获得最佳结果,差异必须具有至少三行上下文。

特别是,我发现 git diff -U0 | ... | interdiff 在分割块后生成一些伪文字 $!otj

6

我通过在gmock-spec-builders.h文件的第1790行添加// NOLINT解决了这个问题。

下面是差异:

--- 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)或者向clang-tidy社区提交bug报告。


这是我在Github上与googletest团队的讨论。他们本可以提到他们已经抑制了警告。我太懒了,没有注册llvm邮件列表来发布误报。哪些工具能理解// NOLINT注释? - Knitschi
// NOLINT被clang工具检测到。 从讨论中我认为这不是真正的误报,更像是一件“永远”不可能发生的事情。因此,我认为最好的方法是使用NOLINT解决方案。 - David Hallas
奇怪的是,你的修复并没有在所有情况下解决我的问题。我还必须在第1272行后面加上// NOLINTreturn function_mocker_->AddNewExpectation( // NOLINT - Knitschi
我认为我会提出一个更改googletest的建议,因为我无法通过命令行选项来抑制警告。但是如果依赖关系无法更改怎么办?那么你就必须在各个地方放置// NOLINT,这有点丑陋。 - Knitschi

4

使用-isystem代替-I设置系统和第三方包含路径,-I只应用于包含正在构建的项目中的代码。

这是使clang-tidy忽略外部代码中所有错误所需的唯一操作。所有其他答案(在撰写本文时)只是对可以通过-isystem完美解决的问题的不良解决方法。

如果您使用像CMake或Meson这样的构建系统,则会自动为您正确地设置-I-isystem

-isystem也是告诉编译器(至少是GCC和Clang)哪些不是您的代码的机制。如果开始使用-isystem,则还可以启用更多的编译器警告,而不会从外部代码中获得“误报”。


这听起来很有趣。我无法立即检查是否有效。但也许在圣诞节假期期间可以。 - Knitschi
我唯一遇到的问题是如何禁用那些系统头文件中扩展宏的错误和警告。 - Arsenal

0

我无法通过命令行选项实现我想要的功能,因此我将使用在cpp文件中提出的// NOLINT注释,这是被接受的答案提出的。

我还将尝试将修复推送到googletest。

我发现-line-filter选项中的行被过滤掉了。 但是给出具体的行并不是解决我的问题的真正方法。 我更需要像Valgrind中实现的抑制机制。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接