私は最近、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ファイルからの警告を抑制しませんでした。
それで、それぞれの警告を個別に抑制して、それが実際の問題であるかどうかを判断できるようにするのが望ましいですが、これが不可能な場合は、外部ヘッダー全体からの警告を抑制しても問題ありません。
お時間をいただきありがとうございます。
// NOLINTを179gmock-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の人々にバグレポートを投稿するのがいいでしょう。
警告を抑制する別の非侵襲的な(サードパーティのライブラリに// 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 は、パッチを操作するための標準ツールです。
スクリプトは次のように機能します。
git diff -U3
は、3つのコンテキスト行を持つパッチを生成します。sed ...
は、不要な行から接頭辞+
を削除します。つまり、それらをコンテキストに変換します。recountdiff
正しいオフセット(最初の範囲)。interdiff -U0 /dev/null /dev/stdin
は、パッチからすべてのコンテキスト行を削除するだけです。その結果、最初のハンクが分割されます。clang-tidy-diff.py
は、チャンクヘッダーから2番目の範囲のみを読み取り、clang-tidy
オプションを介して-line-filter
に渡します。UPD:interdiff
に十分な数のコンテキスト行を提供することが重要です。そうしないと、結果にアーティファクトが生じる可能性があります。 man interdiff
からの引用を参照してください:
最良の結果を得るには、diffに少なくとも3行のコンテキストが必要です。
特に、git diff -U0 | ... | interdiff
は、チャンクを分割した後、偽のリテラル$!otj
を生成することがわかりました。
また、元のパッチが対応していない他のケースにも遭遇しました。これを修正しようとすると、clang-tidy( https://llvm.org/bugs/show_bug.cgi?id=30565 )でセグメンテーション違反も発生しました。現在、私はすべてのエラーを抑制することに成功していません。
見つけた場合は、ここで更新された回答をここに提供します:)
コマンドラインオプションでは希望どおりの結果が得られなかったため、承認された回答で提案されたcppファイルの// NOLINT
コメントを使用します。
また、修正をgoogletestにプッシュしようとします。
-line-filter
オプションの行がフィルター処理されていることがわかりました。しかし、具体的な行を指定することは、とにかく私の問題の実際の解決策ではありません。 Valgrindに実装されているような抑制メカニズムが必要です。