在clang-tidy中忽略系统头

Hei*_*nzi 19 c++ clang clang-static-analyzer libtooling clang-tidy

tldr;>如何在clang-tidy中隐藏系统头文件中的警告?

我有以下最小示例源文件,它会在系统标头中触发一个铿锵有力的警告:

#include <future>

int main() {
  std::promise<int> p;
  p.set_value(3);
}
Run Code Online (Sandbox Code Playgroud)

在Ubuntu 17.04上使用clang-tidy 4.0.0使用libstdc ++ 7.0.1调用它:

$ clang-tidy main.cpp -extra-arg=-std=c++14
Run Code Online (Sandbox Code Playgroud)

产量

Running without flags.
1 warning generated.
/usr/lib/gcc/x86_64-linux-gnu/7.0.1/../../../../include/c++/7.0.1/mutex:693:5: warning: Address of stack memory associated with local variable '__callable' is still referred to by the global variable '__once_callable' upon returning to the caller.  This will be a dangling reference [clang-analyzer-core.StackAddressEscape]
    }
    ^
/home/user/main.cpp:5:3: note: Calling 'promise::set_value'
  p.set_value(3);
  ^
/usr/lib/gcc/x86_64-linux-gnu/7.0.1/../../../../include/c++/7.0.1/future:1094:9: note: Calling '_State_baseV2::_M_set_result'
      { _M_future->_M_set_result(_State::__setter(this, std::move(__r))); }
        ^
/usr/lib/gcc/x86_64-linux-gnu/7.0.1/../../../../include/c++/7.0.1/future:401:2: note: Calling 'call_once'
        call_once(_M_once, &_State_baseV2::_M_do_set, this,
        ^
/usr/lib/gcc/x86_64-linux-gnu/7.0.1/../../../../include/c++/7.0.1/mutex:691:11: note: Assuming '__e' is 0
      if (__e)
          ^
/usr/lib/gcc/x86_64-linux-gnu/7.0.1/../../../../include/c++/7.0.1/mutex:691:7: note: Taking false branch
      if (__e)
      ^
/usr/lib/gcc/x86_64-linux-gnu/7.0.1/../../../../include/c++/7.0.1/mutex:693:5: note: Address of stack memory associated with local variable '__callable' is still referred to by the global variable '__once_callable' upon returning to the caller.  This will be a dangling reference
    }
Run Code Online (Sandbox Code Playgroud)

我想在系统标题中隐藏警告.我尝试了以下方法:

$ clang-tidy -extra-arg=-std=c++14 main.cpp -header-filter=$(realpath .) -system-headers=0
Run Code Online (Sandbox Code Playgroud)

但警告仍然显示.

Jas*_*ton 8

我也遇到了这个问题,并花了一些时间试图弄清楚,但我看不到在 clang-tidy 中禁用此类警告的方法。

通过阅读有关 LLVM 问题跟踪器关于类似问题的讨论,我得到的印象是,从 clang-tidy 的角度来看,警告实际上位于 中main.cpp,因为对 的调用set_value来自那里。

我的解决方法是禁用 clang-tidy 中的静态分析检查,并使用scan-build 实用程序运行 clang 的静态分析,这似乎避免了这些问题。例如,使用您的main.cpp

$ scan-build-3.9 clang++ -std=c++14 main.cpp 
scan-build: Using '/usr/lib/llvm-3.9/bin/clang' for static analysis
In file included from main.cpp:1:
In file included from /usr/lib/gcc/x86_64-linux-gnu/6.3.0/../../../../include/c++/6.3.0/future:39:
/usr/lib/gcc/x86_64-linux-gnu/6.3.0/../../../../include/c++/6.3.0/mutex:621:11: warning: Address of stack memory associated with local variable '__callable' is still referred to by the global variable '__once_callable' upon returning to the caller.  This will be a dangling reference
      if (__e)
          ^~~
1 warning generated.
scan-build: Removing directory '/tmp/scan-build-2017-12-02-112018-13035-1' because it contains no reports.
scan-build: No bugs found.
Run Code Online (Sandbox Code Playgroud)

分析器在系统标题中发现相同的错误,但它足够聪明,不会将其包含在最终报告中。(“没有发现错误”)

如果您对样式指南类型警告(如modernize-*或 )感兴趣,您仍然需要单独运行 clang-tidy readability-*


Pet*_*man 6

我最初得出的结论是这是不可能的,但我有一个非常接近的技巧。

当我编译时,我使用 CMAKE_EXPORT_COMPILE_COMMANDS=ON 生成一个compile_commands.json 文件,显示为编译的每个 cpp 文件传递​​给编译器的命令。当我运行时clang-tidy,我给它 -p 选项以指向包含该文件的目录。

该文件中的典型条目如下所示:

{
  "directory": "/project/build/package1",
  "command": "/usr/bin/clang++-9 -I/opt/thirdparty/include -isystem /usr/include . . . /project/src/package1/src/foo.cpp",
  "file": "/project/src/package1/src/foo.cpp"
},
Run Code Online (Sandbox Code Playgroud)

如果我重写此文件,则-I/opt/thirdparty/include/ -isystem /opt/thirdparty/includeopt/thirdparty/include 中先前有问题的标头将被忽略,因为 clang-tidy 会将它们视为系统标头。

我用来sed重写文件

{
  "directory": "/project/build/package1",
  "command": "/usr/bin/clang++-9 -I/opt/thirdparty/include -isystem /usr/include . . . /project/src/package1/src/foo.cpp",
  "file": "/project/src/package1/src/foo.cpp"
},
Run Code Online (Sandbox Code Playgroud)

  • 如果您使用 CMake,则在自定义第三方包含目录的“target_include_directories”调用中使用“SYSTEM”关键字应该可以执行您想要的操作,而无需编辑编译命令。https://cmake.org/cmake/help/v3.16/command/target_include_directories.html 和 https://cmake.org/cmake/help/v3.16/manual/cmake-buildsystem.7.html#target-特性 (6认同)
  • 刚刚在使用 LLVM 6.0.0 中的 clang-tidy 的测试项目上尝试过这一点;它不起作用。即使我尝试使用“-isystem”和“--system-header-prefix”,我仍然看到生成的警告。 (2认同)