2011年9月29日木曜日

CLangでクラスの中身を調べる(2)

CLangのプリプロセッサ実行の続き・・・の前に。CLangが提供する各クラスのドキュメントについて。
ググって出てくるドキュメントには要注意。バージョンアップでI/Fが変更されている箇所が非常に多いのだ。だから正確な情報を得るには、CLangのソースコードの.hを見たり、.hや.cppに記述されているdoxygenスタイルコメントを読む必要がある。


では続き。
ドキュメントによるとプリプロセッサの実行はclang::Preprocessor::Lex関数によるようだ。そしてLex関数の引数はclang::Tokenで戻り値はvoidなので、引数がoutなんだろうと推測される。

しかし、今まで対象のファイルやフォルダを指定していない。何も指定せずにLex関数をコールするとどうなるだろうか?
	clang::Token token;
	pp.Lex(token);
実行すると見事になにもエラーが発生しない。CLangは例外をthrowしないのか?

ということで対象ファイルを指定する方法を探す。前回ちょっと触ったクラスのうち、たぶんFileManagerあたりでファイルやフォルダを指定し、SourceManagerで読み込む、という感じではないかと推測して各クラスを調べる。
そしてFileManagerのヘッダを見ると、FileEntryとかDirectoryEntiryというのを返却するAPIがある。そしてSourceManagerのドキュメントを見ると、FileEntryを受け取るAPIとしてcreateFileID()やcreateMainFileID()がある。
createFileID()などはclang::FileIDを返す。そこでPreprocessorのヘッダを見ると、FileIDを引数に取るEnterSourceFile()や、引数はないけどFileIDとmain source fileに言及しているEnterMainSourceFile()がある。だいぶ見えてきた。

ということで、main source fileとmainじゃないsource fileの違いがよくわからないが、とりあえずmain source fileを処理しそうなコードを書いて実行してみる。
	llvm::StringRef cppPath("D:\\develop\\Clang\\temp.cpp");
	const clang::FileEntry* cppEntry = fileMgr.getFile(cppPath);
	clang::FileID fileId = srcMgr.createMainFileID(cppEntry);
	pp.EnterMainSourceFile();

	clang::Token token;
	pp.Lex(token);
ちなみにtemp.cppの中身はこんな感じ:
#include <cstdio>
int main(int, char**) { std::printf("Hello,world\n"); std::getchar(); return 0; }

そうすると、clang::Preprocessor::Lex()の実行でアサーションされてしまった。コールスタックを見るとclang::Preprocessor::HandleIncludeDirective()という関数にて「Search include directories.」とコメントされている箇所で、処理結果の診断がNGになっているようだ。なるほど。

0 件のコメント:

コメントを投稿