clang-tidy: How to suppress warnings?

烈酒焚心 提交于 2019-11-29 17:40:55

问题


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.

Question

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?


What I did so far

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.


回答1:


I solved the problem by adding // NOLINT to line 1790 of gmock-spec-builders.h

Here is the diff:

--- 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_

It would be nice to either upstream this patch (I see other NOLINT in the code) or post a bug report with the clang-tidy folks.




回答2:


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:

  1. git diff -U3 generates a patch with 3 context lines.
  2. sed ... removes prefix + from the undesired lines, i.e. transform them to the context.
  3. recountdiff correct offsets (in first ranges) in the chunk headers.
  4. interdiff -U0 /dev/null /dev/stdin just removes all context lines from a patch. As a result, it splits the initial hunks.
  5. 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.




回答3:


I couldn't achive what I wanted with the commmand line options, so I will use the // NOLINT comments in the cpp files which was proposed by the accepted answer.

I will also try to push the the fix to googletest.

I found out that lines in the -line-filter options are filtered in. But giving concrete lines is no real solution for my problem anyways. I rather need a suppression mechanism like it is implemented in Valgrind.



来源:https://stackoverflow.com/questions/39527160/clang-tidy-how-to-suppress-warnings

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!