1. ホーム
  2. c++

未使用のインクルードヘッダを見つけるツール?[クローズド]

2023-12-14 18:38:01

質問

私が知っているのは PC-Lint は、含まれているが使用されていないヘッダについて教えてくれることは知っています。 できればLinuxで、これを行うことができる他のツールはありますか?

私たちには大規模なコードベースがあり、過去 15 年間を通して多くの機能が移動してきましたが、機能が 1 つの実装ファイルから別のものに移動するときに、残された #include ディレクティブが削除されることはほとんどなく、この時点でかなりの混乱を残しています。 すべての #include ディレクティブを削除して、再インクルードするディレクティブをコンパイラーに指示させるという骨の折れることをすることもできますが、私はむしろこの問題を逆に解決したいのです - 使用されたもののリストを再構築するのではなく、使用されていないものを見つけるのです。

どのように解決するのですか?

免責事項です。 私の本業は、静的解析ツールを開発する会社に勤めています。

ほとんどの (すべてではないにしても) 静的解析ツールが、何らかの形でヘッダーの使用状況をチェックしていないことに驚きを隠せません。 たとえば この wikipedia のページで利用可能なツールのリストを取得し、その会社にメールを送って聞いてみるといいでしょう。

ツールを評価する際に考慮すべき点をいくつか挙げておきます。

関数のオーバーロードについては、オーバーロードの解決によって選択された関数を含むヘッダーだけでなく、オーバーロードを含むすべてのヘッダーが表示されるようにしたい。

// 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)'
}

オーバーロードの例と同様に、ブルートフォースアプローチは、コンパイルはできるが挙動が異なるプログラムを生成する可能性があります。

あなたが注目することができる別の関連するタイプの分析は、型が前方宣言することができるかどうかをチェックすることです。 次のように考えてみてください。

// 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 &);

このようなチェックは、ヘッダの依存性を減らすことにもなります。