web-dev-qa-db-ja.com

clang-tidy:警告を抑制する方法は?

私は最近、llvmのclang-tidyツールの実験を始めました。現在、サードパーティのライブラリコードからの誤った警告を抑制しようとしています。このため、コマンドラインオプションを使用します

-header-filter=<string>または-line-filter=<string>

しかし、これまでのところ成功していません。ですから、時間が限られている人のために、ここで質問を最初に置き、後で私がすでに試みたことを説明します。

質問

特定の行およびファイルからの警告を抑制するために、clang-tidyツールにどのオプションを指定する必要がありますか?

これが不可能な場合

外部ヘッダーファイルからの警告を抑制するためにどのオプションが機能しますか?


これまでに行ったこと

Clang-tidyへの最初の呼び出しは次のようになります

clang-tidy-3.8 -checks=-*,clang-analyzer-*,-clang-analyzer-alpha* -p Generated/LinuxMakeClangNoPCH Sources/CodeAssistant/ModuleListsFileManipulator_fixtures.cpp

抑制したいという警告の最初の行は次のようになります

.../gmock/gmock-spec-builders.h:1272:5: warning: Use of memory after it is freed [clang-analyzer-cplusplus.NewDelete]
    return function_mocker_->AddNewExpectation(

Gmockの人々は、これは誤検知であると言ったので、抑制したいと思います。最初に、-line-filter=<string>オプションを使用しようとしました。ドキュメントは言う:

  -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"}
                                 ]

指定された行の警告は除外されると想定しました。しかし、ドキュメントはそれらがフィルターで除外されているか、またはフィルターで除外されているかについては述べていません。いくつかの回避策の後で、コンテンツを含む.jsonファイルを作成しました

[
  {"name":"gmock-spec-builders.h","lines":[[1272,1272]]}
]

コマンドラインを次のように変更しました

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

これは、ファイルの内容を引数に書き込みます。これにより、警告だけでなく、ModuleListsFileManipulator_fixtures.cppファイルからのすべての警告も抑制されます。もっと試してみましたが、うまくいきませんでした。

-header-filter=<string>オプションを試してみました。ここでは、ドキュメントには、診断が表示されるすべてのヘッダーファイルに一致する正規表現を指定する必要があると記載されています。わかりました、私は、分析された.cppファイルと同じフォルダーにあるすべてのものに一致する正規表現を使用できると思いました。私は外部ヘッダーを間違って使用したことによる警告を取り除くかもしれませんが、私はそれで生活できます。

ここで、正規表現が完全な(絶対)ファイル名と一致する必要があるのか​​、ファイル名の一部のみと一致する必要があるのか​​はわかりませんでした。私は試した

-header-filter=.*\/CodeAssistant\/.*.h

これは、CodeAssistantフォルダー内のすべての絶対ヘッダーファイル名に一致しますが、gmock-spec-builders.hファイルからの警告を抑制しませんでした。

それで、それぞれの警告を個別に抑制して、それが実際の問題であるかどうかを判断できるようにするのが望ましいですが、これが不可能な場合は、外部ヘッダー全体からの警告を抑制しても問題ありません。

お時間をいただきありがとうございます。

13
Knitschi

// NOLINT179gmock-spec-builders.hの行に追加して問題を解決しました

ここに差分があります:

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

このパッチをアップストリームする(コードに他のNOLINTが表示される)か、clang-tidyの人々にバグレポートを投稿するのがいいでしょう。

2
David Hallas

警告を抑制する別の非侵襲的な(サードパーティのライブラリに// NOLINTを追加しない)方法を見つけました。たとえば、現在のバージョンのGoogle Testは一部のcppcoreguidelines-*チェックに失敗します。次のコードでは、gtestのマクロを含む行を除いて、現在のdiffを検証できます。

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

ファイルbuild/compile_commands.jsonが前に生成され、clang-tidy-diff.pyが環境から利用可能であると想定しています。 recountdiffおよびinterdiff from patchutils は、パッチを操作するための標準ツールです。

スクリプトは次のように機能します。

  1. git diff -U3は、3つのコンテキスト行を持つパッチを生成します。
  2. sed ...は、不要な行から接頭辞+を削除します。つまり、それらをコンテキストに変換します。
  3. チャンクヘッダーのrecountdiff正しいオフセット(最初の範囲)。
  4. interdiff -U0 /dev/null /dev/stdinは、パッチからすべてのコンテキスト行を削除するだけです。その結果、最初のハンクが分割されます。
  5. clang-tidy-diff.pyは、チャンクヘッダーから2番目の範囲のみを読み取り、clang-tidyオプションを介して-line-filterに渡します。

UPD:interdiffに十分な数のコンテキスト行を提供することが重要です。そうしないと、結果にアーティファクトが生じる可能性があります。 man interdiffからの引用を参照してください:

最良の結果を得るには、diffに少なくとも3行のコンテキストが必要です。

特に、git diff -U0 | ... | interdiffは、チャンクを分割した後、偽のリテラル$!otjを生成することがわかりました。

4
olegrog

また、元のパッチが対応していない他のケースにも遭遇しました。これを修正しようとすると、clang-tidy( https://llvm.org/bugs/show_bug.cgi?id=30565 )でセグメンテーション違反も発生しました。現在、私はすべてのエラーを抑制することに成功していません。

見つけた場合は、ここで更新された回答をここに提供します:)

1
David Hallas

コマンドラインオプションでは希望どおりの結果が得られなかったため、承認された回答で提案されたcppファイルの// NOLINTコメントを使用します。

また、修正をgoogletestにプッシュしようとします。

-line-filterオプションの行がフィルター処理されていることがわかりました。しかし、具体的な行を指定することは、とにかく私の問題の実際の解決策ではありません。 Valgrindに実装されているような抑制メカニズムが必要です。

0
Knitschi