2011年11月30日水曜日

Clangでマクロの展開箇所を調べる

C++ソースコード上にマクロで表現されたDSLをclangで調べるために、マクロ展開箇所を調べたくなった。

マクロはclang::Preprocessorの範疇であるが、Preprocessorはマクロの展開情報を直接扱わない。clangにはPreprocessingRecordおよびPreprocessedEntryというクラスがあり、これらを利用する。

まず、Preprocessorが処理においてPreprocessingEntryを保存してくれるよう、PreprocessingRecordをセットアップする。
clang::InitializePreprocessor(pp, ppOpts, headerSearchOpts, frontendOpts);
pp.createPreprocessingRecord(true);

そうすると、プリプロセッシングの後でPreprocessorに設定されたPreprocessingRecordが、PreprocessedEntryを反復してくれる。PreprocessedEntryの派生クラスとしてMacroExpansionがあるので、キャストして情報を得ればよい。
clang::PreprocessingRecord* ppRecord = pp.getPreprocessingRecord();
clang::PreprocessingRecord::iterator ppr = ppRecord->begin();
clang::PreprocessingRecord::iterator eoppr = ppRecord->end();
for(; ppr != eoppr; ++ppr)
{
    if((*ppr)->getKind() == clang::PreprocessedEntity::MacroExpansionKind)
    {
        clang::MacroExpansion* expansion
            = llvm::dyn_cast<clang::MacroExpansion>(*ppr);
        if(expansion->getName()->getName() == "MY_MACRO")
        {
            clang::SourceRange range = expansion->getSourceRange();
            range.getBegin().dump(srcMgr);
        }
    }
}

0 件のコメント:

コメントを投稿