I recently started experimenting with the clang-tidy
tool of llvm. Now I am trying to suppress false warnings from third party library code. For this I want to use the command line options
-header-filter=<string>
or -line-filter=<string>
but so far without success. So for people with limited time I will put the question here at the beginning and explain later what I already tried.
What option do I need to give to the clang-tidy
tool to suppress a warning from a certain line and file?
if this is not possible
What option works to suppress warnings from external header files?
My original call to clang-tidy looks like this
clang-tidy-3.8 -checks=-*,clang-analyzer-*,-clang-analyzer-alpha* -p Generated/LinuxMakeClangNoPCH Sources/CodeAssistant/ModuleListsFileManipulator_fixtures.cpp
and the first line of the yielded warning that I want to suppress looks like this
.../gmock/gmock-spec-builders.h:1272:5: warning: Use of memory after it is freed [clang-analyzer-cplusplus.NewDelete]
return function_mocker_->AddNewExpectation(
The gmock people told me that this is a false positive so I want to suppress it. First I tried to use the -line-filter=<string>
option. The documentation says:
-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"}
]
I assumed that warnings in the given lines are filtered out. But the doc doesent say if they are filterd out or in. After some fiddeling arround I created a .json file with the content
[
{"name":"gmock-spec-builders.h","lines":[[1272,1272]]}
]
and modified the command line to
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
which writes the content of the file into the argument. This suppresses the warning, but not only this warning, but all warnings from the ModuleListsFileManipulator_fixtures.cpp file. I tried more stuff but I could not make it work.
So I tried the -header-filter=<string>
option. Here the documentation states that one has to give a regular expression that matches all the header files from which diagnostics shall be displayed. Ok, I thought, lets use a regualar expression that matches everything that is in the same folder as the analyzed .cpp file. I can live with that although it may remove warnings that result from me using external headers wrong.
Here I was not sure if the regular expression must match the full (absolute) filename or only a part of the filename. I tried
-header-filter=.*\/CodeAssistant\/.*.h
which matches all absolute header filenames in the CodeAssistant folder but it did not suppress the warnings from the gmock-spec-builders.h file.
So preferably I would like to suppress each warning individually so I can determine for each if it is a real problem or not, but if this is not possible I could also live with suppressing warnings from entire external headers.
Thank you for your time.
I have found another non-invasive (without adding // NOLINT
to a third-party library) way to suppress warnings. For example, the current version of Google Test fails some cppcoreguidelines-*
checks. The following code allows you to validate the current diff excluding lines that contain gtest's macros:
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
It assumes that file build/compile_commands.json
is generated before and clang-tidy-diff.py
is available from your environment. recountdiff
and interdiff
from patchutils are the standard tools for manipulating patches.
The script works as follows:
git diff -U3
generates a patch with 3 context lines.sed ...
removes prefix +
from the undesired lines, i.e. transform them to the context.recountdiff
correct offsets (in first ranges) in the chunk headers.interdiff -U0 /dev/null /dev/stdin
just removes all context lines from a patch. As a result, it splits the initial hunks.clang-tidy-diff.py
reads only second ranges from chunk headers and passes them to clang-tidy
via -line-filter
option.UPD: It's important to provide interdiff
with a sufficient number of context lines, otherwise it may produce some artifacts in the result. See the citation from man interdiff
:
For best results, the diffs must have at least three lines of context.
Particularly, I have found that git diff -U0 | ... | interdiff
generates some spurious literals $!otj
after splitting chunks.