Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

clang-tidy: How to suppress warnings?

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.

like image 231
Knitschi Avatar asked Sep 16 '16 08:09

Knitschi


People also ask

How do I disable clang tidy warnings?

To suppress a Clang-Tidy check for a particular line, use the Suppress "check_name" for line option.

How does clang tidy work?

clang-tidy is a clang-based C++ “linter” tool. Its purpose is to provide an extensible framework for diagnosing and fixing typical programming errors, like style violations, interface misuse, or bugs that can be deduced via static analysis.

Does clang tidy work with C?

Clang-tidy is a standalone linter tool for checking C and C++ source code files. It provides an additional set of compiler warnings—called checks—that go above and beyond what is typically included in a C or C++ compiler.


2 Answers

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.

like image 190
olegrog Avatar answered Sep 19 '22 19:09

olegrog


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.

like image 21
David Hallas Avatar answered Sep 20 '22 19:09

David Hallas