clangで相互参照の情報解析
前回の記事の続きです。ソースコードから以下の情報を取りたいです。
- 定義されている関数、変数の詳細
- 関数、変数の参照関係
前回の内容では、「定義されている関数、変数の詳細」の情報は取得できました。ですが、「関数、変数の参照関係」を取る方法がわかりませんでした。
相互参照情報の取得
ソースを色々調べてみると、clangのサンプルの中のwpaではIndexerにTranslationUnitを渡してコールグラフの生成を行うコードがありました。コールグラフには参照情報が必須です。つまりIndexerを使えば参照情報の取得ができそうです。
Indexerの定義されているファイル付近(同じディレクトリ)で定義されているクラスもきっと有益なクラスに違いないと考え色々調べてみました。
- clang/Index/
具体的には上記のディレクトリを眺めてみます。ざっくり眺めていると、以下のクラスが重要そうです。
- clang::idx::Analyzer
- clang::idx::Indexer
- clang::idx::Program
このあたりのクラスで、プログラム中に現れている概念(clangではEntityと呼ぶ)の関連を調査できそうです。
- clang::idx::Analyzer::findReferences
とかがかなりそれっぽいです。
clang::idx::Analyzerをつくろう
とりあえず、clang::idx::Analyzerをnewするところから始めたいので、コンストラクタを眺めてみます。
clang::idx::Analyzer::Analyzer ( Program & prog,IndexProvider & idxer);
clang::idx::Programとclang::idx::IndexProviderが引数みたいですね。Analyzerを作成する前に、これらを先にnewする必要がありますね。
Programクラス
Programのコンストラクタには引数がないので、何もしなくても作成できそうです。ついでにコメントに
\brief Top level object that owns and maintains information
that is common across translation units.
と書いてありますね。
IndexProvider
IndexProviderはvirtualなクラスなので、これをimplemantしているIndexerというクラスがすでにclangに用意されています。
なので、Indexerのコンストラクタを眺めてみます。…特に指定されてません。デフォルトでよさそうです。
Indexerのメンバには、Programもあります。なので、Indexerをひとつ作ってしまえば、Analyzerを作成できそうですね。また、Indexerのメソッドで興味深いものとしては
/// \brief Find all Entities and map them to the given translation unit. void IndexAST(TranslationUnit *TU);
このあたりでしょうか。
解析の流れ
ここまでの情報から、恐らくclangのAnalyzerの使い方としては以下を想定しているように見えます。
- Indexerを作る
- IndexerにTranslationUnitを複数個渡していく
- IndexerからAnalyzerを作成
- Analyzerで参照の情報を取得
Indexerを作るのは難しくないことがわかっているので、TranslationUnitを自由に作れるようにできれば、Analyzerを使えるようになるのではないかと予想できます。