Ignore system headers in clang-tidy
Solution 1
I ran into this issue as well, and spent some time trying to figure it out, but I could not see a way to disable this type of warning in clang-tidy.
From reading this discussion on the LLVM issue tracker regarding a similar issue, I get the impression that the problem is that from clang-tidy's perspective, the warning is actually located in main.cpp
, because the call to set_value
is from there.
My workaround has been to disable the static analysis checks in clang-tidy, and use the scan-build utility to run clang's static analysis, which seems to avoid these problems. For example, using your 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.
The analyzer finds the same error in a system header, but it's smart enough not to include it in the final report. ("No bugs found")
You'll still need to run clang-tidy separately if you are interested in the style guide type warnings, like modernize-*
or readability-*
.
Solution 2
I initially came to the conclusion that this was not possible, but I've got a hack that gets pretty close.
When I compile I use CMAKE_EXPORT_COMPILE_COMMANDS=ON which generates a compile_commands.json file showing what commands were passed to the compiler for each cpp file compiled. When I run clang-tidy
I give it the -p option to point to the directory containing this file.
A typical entry in this file looks something like this:
{
"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"
},
If I re-write this file so that -I/opt/thirdparty/include
becomes -isystem /opt/thirdparty/include
the previously problematic headers in /opt/third-party/include are ignored because clang-tidy will see them as system headers.
I use sed
to rewrite the file
# Trick clang-tidy into thinking anything in /opt/thirdparty/include is a system header
sed -i 's|-I/opt/thirdparty/include|-isystem /opt/thirdparty/include|g' build/compile_commands.json
# Run clang-tidy using the run-clang-tidy python wrapper
run-clang-tidy.py -p build -header-filter .* $(find src -iname "*.cpp")
Solution 3
My solution to this problem is to execute clang-tidy
from a script and then filter all issues based on the file location because issues from user-code are located in e.g. C:\Repos\myLib
, whereas issues from system-headers are located in C:\Program Files (x86)
or similar.
The script is a powershell
script, maybe you can do something similar with bash
:
# clang-filter-user-code.ps1
Param(
[parameter(Mandatory=$true)]
[string]$CLANG_TIDY,
[parameter(Mandatory=$true)]
[string[]]$SOURCE_FILES,
[parameter(Mandatory=$true)]
[string]$SOURCE_DIR,
[parameter(Mandatory=$true)]
[string]$TARGET_DIR
)
$TMP = $TARGET_DIR + "/tmp-clang-output.txt"
$PATTERN = "(?s)(" + $SOURCE_DIR.Replace("/", "\\") + "[^\^]*\^)"
# Reading the content as Raw text, where everything is stored within one line, is only possible with specifying a path to a file.
# Therefore we store the clang-tidy output in a temporary file, that is deleted afterwards.
&($CLANG_TIDY) $SOURCE_FILES > $TMP
Get-Content -Raw -Path $TMP | Select-String -Pattern $PATTERN -AllMatches | Select-Object -ExpandProperty Matches | % {$_.Groups[1].Value }
Remove-Item $TMP
You have to pass the path to clang-tidy, your source files, the path of your source directory and the path to your target directory to the script.
Using CMAKE
, you can integrate this into your build:
# clang-dev-tools.cmake
function(PREPARE_SOURCE_FILE_LIST SOURCE_FILES OUTPUT)
# Put each entry between single quotes
foreach(SOURCE_FILE ${SOURCE_FILES})
list(APPEND SOURCE_FILES_LIST '${SOURCE_FILE}')
endforeach()
# Join all entries using comma as delimiter - based on https://stackoverflow.com/questions/7172670/best-shortest-way-to-join-a-list-in-cmake
string(REGEX REPLACE "([^\\]|^);" "\\1," TMP_STR "${SOURCE_FILES_LIST}")
string(REGEX REPLACE "[\\](.)" "\\1" TMP_STR "${TMP_STR}") #fixes escaping
set(${OUTPUT} "${TMP_STR}" PARENT_SCOPE)
endfunction()
# Detect all source files
file(GLOB_RECURSE
SOURCE_FILES
${CMAKE_SOURCE_DIR}/Src/Libs/*/Src/*.cpp
${CMAKE_SOURCE_DIR}/Src/Libs/*/Src/*.h)
find_program(CLANG_TIDY NAMES clang-tidy clang-tidy-6.0)
if (CLANG_TIDY)
PREPARE_SOURCE_FILE_LIST("${SOURCE_FILES}" SOURCE_FILES_LIST)
set(SCRIPT_ARGUMENTS "-CLANG_TIDY" '${CLANG_TIDY}' "-SOURCE_FILES" ("${SOURCE_FILES_LIST}") "-SOURCE_DIR" '${CMAKE_SOURCE_DIR}' "-TARGET_DIR" '${CMAKE_BINARY_DIR}')
# Because clang-tidy also detects warnings/errors in non-user code, we need to filter its output via this script.
add_custom_command(
OUTPUT clang-output
COMMAND PowerShell (${CMAKE_CURRENT_SOURCE_DIR}/cmake/clang-filter-user-code.ps1 ${SCRIPT_ARGUMENTS})
WORKING_DIRECTORY ${CMAKE_BINARY_DIR}
)
add_custom_target(
FilterClang ALL
DEPENDS clang-output
)
endif ()
I'm not so familiar with both CMAKE
and powershell
, so please bear with me if I did not find the most elegant solution.
There is also an open PR to an even better solution on LLVM, but since it is already open for almost 4 years now, we don't know if and when it's going to come.
Heinzi
Updated on June 15, 2022Comments
-
Heinzi almost 2 years
tldr;> How do I hide warnings from system headers in clang-tidy?
I have the following minimal example source file, which triggers a clang-tidy warning in the system headers:
#include <future> int main() { std::promise<int> p; p.set_value(3); }
Calling it with libstdc++ 7.0.1 using clang-tidy 4.0.0 on Ubuntu 17.04:
$ clang-tidy main.cpp -extra-arg=-std=c++14
yields
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 }
I want to hide warnings in system headers. I tried the following:
$ clang-tidy -extra-arg=-std=c++14 main.cpp -header-filter=$(realpath .) -system-headers=0
but the warning still shows.
-
KymikoLoco over 4 yearsIf you're using CMake, using the
SYSTEM
keyword in yourtarget_include_directories
call for your custom third party include directories should do what you want without having to edit the compile commands. cmake.org/cmake/help/v3.16/command/… and cmake.org/cmake/help/v3.16/manual/… -
Pete Baughman over 4 yearsUnfortunately, I was dealing with a build that contained many many CMake projects, some from third-parties that could not easily be changed.
-
Livne Rosenblum over 3 yearshow did
disabled the static analysis checks in clang-tidy
? -
Martin over 3 yearsJust tried this on a test project using clang-tidy from LLVM 6.0.0; it's not working. I still see the warnings being generated, even though I tried using
-isystem
and--system-header-prefix
. -
Martin over 3 years
scan-build
will still report the bug if you try to exclude a non-system header by passing it as-isystem
. -
Pete Baughman about 3 yearsSorry, that's a bummer - it worked for me but I'm not currently doing any work for the company that needed this so I can't go back and play with it to try to figure out what might be wrong when you try it. I don't even remember the clang-tidy version they were using.