免責事項:私の本業は、静的分析ツールを開発する会社で働いています。
ほとんどの (すべてではないにしても) 静的分析ツールに何らかの形式のヘッダー使用状況チェックがなかったら、私は驚かれることでしょう。このウィキペディアのページを使用して、利用可能なツールのリストを取得し、企業にメールして問い合わせることができます。
ツールを評価する際に考慮すべきいくつかのポイント:
関数のオーバーロードの場合、オーバーロードの解決によって選択された関数を含むヘッダーだけでなく、オーバーロードを含むすべてのヘッダーを表示する必要があります。
// f1.h
void foo (char);
// f2.h
void foo (int);
// bar.cc
#include "f1.h"
#include "f2.h"
int main ()
{
foo (0); // Calls 'foo(int)' but all functions were in overload set
}
力ずくのアプローチを取る場合は、最初にすべてのヘッダーを削除してから、コンパイルされるまでそれらを再度追加します。「f1.h」が最初に追加された場合、コードはコンパイルされますが、プログラムのセマンティクスは変更されています。
部分的および特殊化がある場合、同様のルールが適用されます。スペシャライゼーションが選択されているかどうかは関係ありません。すべてのスペシャライゼーションが表示されていることを確認する必要があります。
// f1.h
template <typename T>
void foo (T);
// f2.h
template <>
void foo (int);
// bar.cc
#include "f1.h"
#include "f2.h"
int main ()
{
foo (0); // Calls specialization 'foo<int>(int)'
}
オーバーロードの例に関して言えば、ブルート フォース アプローチでは、コンパイルはできるが動作が異なるプログラムが生成される可能性があります。
注目できるもう 1 つの関連する分析の種類は、型を前方宣言できるかどうかを確認することです。次の点を考慮してください。
// A.h
class A { };
// foo.h
#include "A.h"
void foo (A const &);
// bar.cc
#include "foo.h"
void bar (A const & a)
{
foo (a);
}
上記の例では、'A' の定義は必要ないため、ヘッダー ファイル 'foo.h' を変更して、'A' のみの前方宣言を行うことができます。
// foo.h
class A;
void foo (A const &);
この種のチェックは、ヘッダーの依存関係も減らします。