ClangのlibToolingでASTをダンプするツールを作ってみた

C++の構文解析ライブラリが欲しい！！
---
　C++の構文解析ライブラリが欲しくて、いろいろ調べたところ、[clang](http://ja.wikipedia.org/wiki/Clang "Wiki") / [LLVM](http://ja.wikipedia.org/wiki/LLVM "Wiki")のlibToolingが正にぴったりです。しかも、BSDライクなライセンスのオープン・ソース！！　そこで、これを使ってC++の[AST](http://ja.wikipedia.org/wiki/%E6%8A%BD%E8%B1%A1%E6%A7%8B%E6%96%87%E6%9C%A8 "Wiki")(の最低限)をダンプするごく小さなツールを作ってみました。(200行ちょっとのcppを１つだけ)

　AST簡易ダンプ・ツールは32bitsアプリとしてビルドしています。
　Windows 7 Professionalの64bit版で動作確認しましたが、Windows 7 32bit版でも動くと思います。

##1.使用ツールのインストール
　LLVMは[Windows上ではVisual Studioのみ動作確認されている](http://llvm.org/docs/GettingStarted.html#requirements "LLVM is known to work on the following host platforms")ようですので、[Visual Studio](http://www.buildinsider.net/hub/insidersbreak/2014112101 "「Pro相当機能が無料！」と話題になった「Visual Studio Community」の光と“影”")を使った方がよいのですが、今回はMinGW+QtCreatorを使いました。（Visual Studioはまだインストールしてないとです。）

|ツール|使用目的|
|:-------|:-------|
|[MinGW-w64](http://ja.wikipedia.org/wiki/MinGW "Wiki")|今回はgccをコンパイラとして使いました|
|[QtCreator](http://qiita.com/task_jp/items/098319a33bd946955c0a "Qiita")|[Qt](http://ja.wikipedia.org/wiki/Qt "Wiki")という強力な[RADツール](http://ja.wikipedia.org/wiki/RAD_(%E8%A8%88%E7%AE%97%E6%A9%9F%E3%83%97%E3%83%AD%E3%82%B0%E3%83%A9%E3%83%9F%E3%83%B3%E3%82%B0%E7%92%B0%E5%A2%83) "Wiki")の[IDE](http://ja.wikipedia.org/wiki/%E7%B5%B1%E5%90%88%E9%96%8B%E7%99%BA%E7%92%B0%E5%A2%83 "Wiki") と [jom](http://snipsnipsnip.tumblr.com/post/1714380919/jom-nmake "jom: 並列nmake")|
|[Subversion](http://ja.wikipedia.org/wiki/Apache_Subversion "Wiki")|clang / LLVMをダウンロードするのに使いました(clang指定)|
|[CMake](http://ja.wikipedia.org/wiki/CMake "Wiki")|Makefileの構成(clang指定)|

　下記ようにインストールしました。

|ソフトウェア|ダウンロードするファイル|インストール方法|
|:-----------|:------------|:-----------|
|[Qt5.4.0](http://www.qt.io/download-open-source/#section-6 "オープンソース版Qt")|[qt-opensource-windows-x86-1.6.0-7-online.exe](http://download.qt-project.org/official_releases/online_installers/qt-opensource-windows-x86-online.exe "Click to download")|[ここ](http://qiita.com/Chironian/items/2da05e9df4db9ba0d8ec#2-qt540-32bit%E3%81%AE%E3%82%A4%E3%83%B3%E3%82%B9%E3%83%88%E3%83%BC%E3%83%AB "私のQtに関する投稿です")を参考にインストールして下さい。MinGWもインストールされます。|
|[TortoiseSVN](http://sourceforge.jp/projects/tortoisesvn/releases/ "http://sourceforge.jp/")(*1)|[TortoiseSVN-1.8.10.26129-win32-svn-1.8.11.msi](http://sourceforge.jp/projects/sfnet_tortoisesvn/downloads/1.8.10/Application/TortoiseSVN-1.8.10.26129-win32-svn-1.8.11.msi/ "Click to download")|普通にインストールして下さい。（私が使ったバージョンは1.8.8の64bits版ですが、最新32bits版のこれも問題ない筈です。）|
|[CMake](http://www.cmake.org/download/ "Get the Software")|[cmake-3.1.1-win32-x86.exe](http://www.cmake.org/files/v3.1/cmake-3.1.1-win32-x86.exe "Click to download")|普通にインストールして下さい。（私が使ったバージョンは3.0.2ですが、最新版のこれも問題ない筈です。）|
(*1)SubversionをExplorerから呼び出せるようにした非常に便利なツールです。これにSubversionも含まれています。
　同じ所に日本語パック（[LanguagePack_1.8.10.26129-win32-ja.msi](http://sourceforge.jp/projects/sfnet_tortoisesvn/downloads/1.8.10/Language%20Packs/LanguagePack_1.8.10.26129-win32-ja.msi/ "Click to download")）もあります。インストールすると日本語化されます。

##2.clang / LLVMのダウンロードとビルド
###2.1 [ここ](http://clang.llvm.org/get_started.html "公式")に従ってSubversionでソース群をダウンロード
　ダウンロードするバッチ・ファイルを作りました。clangをダウンロードするフォルダで実行して下さい。

```bat:checkout.bat
rem Checkout LLVM
	svn co http://llvm.org/svn/llvm-project/llvm/trunk llvm

rem Checkout Clang:
	cd llvm/tools
	svn co http://llvm.org/svn/llvm-project/cfe/trunk clang
	cd ../..

rem Checkout extra Clang Tools: (optional)
	cd llvm/tools/clang/tools
	svn co http://llvm.org/svn/llvm-project/clang-tools-extra/trunk extra
	cd ../../../..

rem Checkout Compiler-RT:
	cd llvm/projects
	svn co http://llvm.org/svn/llvm-project/compiler-rt/trunk compiler-rt
	cd ../..
```

###2.2 [ここ](http://llvm.org/docs/CMake.html "公式")を参考にしつつ、clang / LLVMをビルド
　手順としては下記となります。
　　1.MinGWとQtCreatorにパスを通しておく。
　　2.ビルド用フォルダを作り、そこへ移動する
　　3.構成し、ビルドし、インストールする

　パスを通し、clangをダウンロードしたフォルダにいるとして、2と3の手順をbatファイル形式で示します。

```bat
rem デバッグ・ビルドする
	mkdir build-llvm-debug
	cd build-llvm-debug
	CMake -G "MinGW Makefiles" -DCMAKE_C_FLAGS:STRING="-static -static-libgcc -static-libstdc++" -DCMAKE_CXX_FLAGS:STRING="-static -static-libgcc -static-libstdc++" -DCMAKE_CXX_FLAGS=-Og -DCMAKE_BUILD_TYPE:STRING=Debug -DCMAKE_INSTALL_PREFIX:PATH="../install/debug" ..\llvm\
	jom
	jom install

rem リリース・ビルドする
	mkdir build-llvm-release
	cd build-llvm-release
	CMake -G "MinGW Makefiles" -DCMAKE_C_FLAGS:STRING="-static -static-libgcc -static-libstdc++" -DCMAKE_CXX_FLAGS:STRING="-static -static-libgcc -static-libstdc++" -DCMAKE_BUILD_TYPE:STRING=Release -DCMAKE_INSTALL_PREFIX:PATH="../install/release" ..\llvm\
	jom
	jom install
```
　デバッグ・ビルドのポイントは-Ogオプションです。これを付けないとファイルが大きすぎると怒られます。
　デバッグ・ビルドはビルドに60分以上、インストールにも10分以上かかりました。
　リリース・ビルドはそれぞれ35分と数分でした。（Core™ i7-3820 3.60 GHzのパソコンを使ってます。）

```text:Note
　libToolingをリンクしたアプリケーションのデバッグ・ビルドに時間がかかります。今回のごく小さなソースでも数十秒かかります。リリース・ビルドなら数秒です。しかし、リリース・ビルドではブレークを張っても止まってくれません。
　なので、デバッグ・ビルドとリリース・ビルドの両方を使った方が楽と思います。
```

##3.AST簡易ダンプ・ツールのソースとビルド
　主に[ここ](https://kevinaboos.wordpress.com/2013/07/23/clang-tutorial-part-ii-libtooling-example/ "CLANG TUTORIAL PART II: LIBTOOLING EXAMPLE")を参考にしました。
　プリプロセス周りはclangソースの"llvm\tools\clang\tools\extra\pp-trace\"を参考にしました。

###3.1.ソースとその概要説明
　ASTをウォークスルーするために必要なことは意外に簡単です。（なのに大抵のことができそう。凄い！！）

　　・プリプロセス追跡をするなら、PPCallbacksを継承して、必要なコールバック関数をオーバーライドする。
　　・ASTウォークスルーのため、DeclVisitorを継承して、必要なVisit関数をオーバーライドする。
　　・定番の記述（mainとFrontendActionとASTConsumer。全部で30行くらい。）

　200行ちょっとですので、AST簡易ダンプ・ツールのソースを下記に載せます。main.cpp１つだけです。

```Cpp:main.cpp
#include "clang/AST/AST.h"
#include "clang/AST/ASTContext.h"
#include "clang/AST/ASTConsumer.h"
#include "clang/AST/DeclVisitor.h"
#include "clang/Frontend/ASTConsumers.h"
#include "clang/Frontend/FrontendActions.h"
#include "clang/Frontend/CompilerInstance.h"
#include "clang/Lex/Preprocessor.h"
#include "clang/Tooling/CommonOptionsParser.h"
#include "clang/Tooling/Tooling.h"

using namespace std;
using namespace clang;
using namespace clang::tooling;
using namespace llvm;

// ***************************************************************************
//          プリプロセッサからのコールバック処理
// ***************************************************************************

class PPCallbacksTracker : public PPCallbacks {
private:
    Preprocessor &PP;
public:
    PPCallbacksTracker(Preprocessor &pp) : PP(pp) {}
    void InclusionDirective(SourceLocation HashLoc,
                          const Token &IncludeTok,
                          llvm::StringRef FileName, 
                          bool IsAngled,
                          CharSourceRange FilenameRange,
                          const FileEntry *File,
                          llvm::StringRef SearchPath,
                          llvm::StringRef RelativePath,
                          const Module *Imported) override {
        errs() << "InclusionDirective : ";
        if (File) {
	        if (IsAngled)   errs() << "<" << File->getName() << ">\n";
	        else            errs() << "\"" << File->getName() << "\"\n";
	    } else {
			errs() << "not found file ";
	        if (IsAngled)   errs() << "<" << FileName << ">\n";
	        else            errs() << "\"" << FileName << "\"\n";
		}
    }
};

// ***************************************************************************
//          ASTウォークスルー
// ***************************************************************************

//llvm\tools\clang\include\clang\AST\DeclVisitor.hの36行目参照↓voidは指定できない。
class ExampleVisitor : public DeclVisitor<ExampleVisitor, bool> {
private:
    PrintingPolicy      Policy;
    const SourceManager &SM;
public:
    ExampleVisitor(CompilerInstance *CI) : Policy(PrintingPolicy(CI->getASTContext().getPrintingPolicy())),
                                           SM(CI->getASTContext().getSourceManager()) {
        Policy.Bool = 1;    // print()にてboolが_Boolと表示されないようにする
    }   //↑http://clang.llvm.org/doxygen/structclang_1_1PrintingPolicy.html#a4a4cff4f89cc3ec50381d9d44bedfdab
private:
    // インデント制御
    struct CIndentation {
        int             IndentLevel;
        CIndentation() : IndentLevel(0) { }
        void Indentation(raw_ostream &OS) const {
            for (int i=0; i < IndentLevel; ++i) OS << "  ";
        }
        // raw_ostream<<演算子定義
        friend raw_ostream &operator<<(raw_ostream &OS, const CIndentation &aCIndentation) {
            aCIndentation.Indentation(OS);
            return OS;
        }
    } indentation;
    class CIndentationHelper {
    private:
        ExampleVisitor  *parent;
    public:
        CIndentationHelper(ExampleVisitor *aExampleVisitor) : parent(aExampleVisitor) {
            parent->indentation.IndentLevel++;
        }
        ~CIndentationHelper() { parent->indentation.IndentLevel--; }
    };
    #define INDENTATION CIndentationHelper CIndentationHelper(this)
public:
    // DeclContextメンバーの1レベルの枚挙処理
    void EnumerateDecl(DeclContext *aDeclContext) {
        for (DeclContext::decl_iterator i = aDeclContext->decls_begin(), e = aDeclContext->decls_end(); i != e; i++) {
            Decl *D = *i;
            if (indentation.IndentLevel == 0) {
                errs() << "TopLevel : " << D->getDeclKindName();                                    // Declの型表示
                if (NamedDecl *N = dyn_cast<NamedDecl>(D))  errs() << " " << N->getNameAsString();  // NamedDeclなら名前表示
                errs() << " (" << D->getLocation().printToString(SM) << ")\n";                      // ソース上の場所表示
            }
            Visit(D);       // llvm\tools\clang\include\clang\AST\DeclVisitor.hの38行目
        }
    }

    // class/struct/unionの処理
    virtual bool VisitCXXRecordDecl(CXXRecordDecl *aCXXRecordDecl, bool aForce=false) {
        // 参照用(class foo;のような宣言)なら追跡しない
        if (!aCXXRecordDecl->isCompleteDefinition()) {
    return true;
        }

        // 名前無しなら表示しない(ただし、強制表示されたら表示する:Elaborated用)
        if (!aCXXRecordDecl->getIdentifier() && !aForce) {
    return true;
        }

        errs() << indentation << "<<<====================================\n";

        // TopLevelなら参考のためlibToolingでも表示する
        if (indentation.IndentLevel == 0) {
            aCXXRecordDecl->print(errs(), Policy);
            errs() << "\n";
            errs() << indentation << "--------------------\n";
        }

        // クラス定義の処理
        errs() << indentation << "CXXRecordDecl : " << aCXXRecordDecl->getNameAsString() << " {\n";
        {
            INDENTATION;

            // 基底クラスの枚挙処理
            for (CXXRecordDecl::base_class_iterator Base = aCXXRecordDecl->bases_begin(), BaseEnd = aCXXRecordDecl->bases_end();
                 Base != BaseEnd;
                 ++Base) {                                          // ↓型名を取り出す(例えば、Policy.Bool=0の時、bool型は"_Bool"となる)
                errs() << indentation << "Base : " << Base->getType().getAsString(Policy) << "\n";
            }

            // メンバーの枚挙処理
            EnumerateDecl(aCXXRecordDecl);
        }
        errs() << indentation << "}\n";
        errs() << indentation << "====================================>>>\n";
        return true;
    }

    // メンバー変数の処理
    virtual bool VisitFieldDecl(FieldDecl *aFieldDecl) {
        // 名前無しclass/struct/unionでメンバー変数が直接定義されている時の対応
        CXXRecordDecl *R=NULL;      // 名前無しの時、内容を表示するためにCXXRecordDeclをポイントする
        const Type *T = aFieldDecl->getType().split().Ty;
        if (T->getTypeClass() == Type::Elaborated) {
            R = cast<ElaboratedType>(T)->getNamedType()->getAsCXXRecordDecl();
            if (R && (R->getIdentifier()))  R = NULL;
        }
        // 内容表示
        if (R) {
            errs() << indentation << "FieldDecl : <no-name-type> " << aFieldDecl->getNameAsString() << "\n";
            VisitCXXRecordDecl(R, true);    // 名前無しclass/struct/unionの内容表示
        } else {
            errs() << indentation << "FieldDecl : " << aFieldDecl->getType().getAsString(Policy) << " " << aFieldDecl->getNameAsString() << "\n";
        }
        return true;
    }

    // namespaceの処理(配下を追跡する)
    virtual bool VisitNamespaceDecl(NamespaceDecl *aNamespaceDecl) {
        errs() << "NamespaceDecl : namespace " << aNamespaceDecl->getNameAsString() << " {\n";
        EnumerateDecl(aNamespaceDecl);
        errs() << "} end of namespace " << aNamespaceDecl->getNameAsString() << "\n";
        return true;
    }

    // extern "C"/"C++"の処理(配下を追跡する)
    virtual bool VisitLinkageSpecDecl(LinkageSpecDecl*aLinkageSpecDecl) {
        string lang;
        switch (aLinkageSpecDecl->getLanguage()) {
        case LinkageSpecDecl::lang_c:   lang="C"; break;
        case LinkageSpecDecl::lang_cxx: lang="C++"; break;
        }
        errs() << "LinkageSpecDecl : extern \"" << lang << "\" {\n";
        EnumerateDecl(aLinkageSpecDecl);
        errs() << "} end of extern \"" << lang << "\"\n";
        return true;
    }
};

// ***************************************************************************
//          定番の処理
// ***************************************************************************

class ExampleASTConsumer : public ASTConsumer {
private:
    ExampleVisitor *visitor; // doesn't have to be private
public:
    explicit ExampleASTConsumer(CompilerInstance *CI) : visitor(new ExampleVisitor(CI)) {
        // プリプロセッサからのコールバック登録
        Preprocessor &PP = CI->getPreprocessor();
        PP.addPPCallbacks(llvm::make_unique<PPCallbacksTracker>(PP));
    }
    // AST解析結果の受取
    virtual void HandleTranslationUnit(ASTContext &Context) {
        errs() << "\n\nHandleTranslationUnit()\n";
        visitor->EnumerateDecl(Context.getTranslationUnitDecl());
    }
};

class ExampleFrontendAction : public SyntaxOnlyAction /*ASTFrontendAction*/ {
public:
    virtual std::unique_ptr<ASTConsumer> CreateASTConsumer(CompilerInstance &CI, StringRef file) {
        return llvm::make_unique<ExampleASTConsumer>(&CI); // pass CI pointer to ASTConsumer
    }
};

static cl::OptionCategory MyToolCategory("My tool options");
int main(int argc, const char **argv)
{
    CommonOptionsParser op(argc, argv, MyToolCategory);
    ClangTool Tool(op.getCompilations(), op.getSourcePathList());
    return Tool.run(newFrontendActionFactory<ExampleFrontendAction>().get());
}
```
####3.1.1.ソースの説明　－　定番の処理
　AST解析を行う場合に「お約束」的な記述になるようです。
　目的によっては、それぞれの部分をそれなりに修正したり、間に処理を追加したりするケースもあると思いますが、大きな流れは変わらないのではないかと思います。

・main()関数　実質３行です。
　CommonOptionsParserクラスで、コマンドラインからソース・ファイルのリストとオプション・リストを取り出します。
　それらを与えて、ClangToolクラスのオブシェクトを生成します。
　そのオブジェクトのrun()を実行します。この時、FrontendActionを継承した自分のオブジェクトを与えることで、AST解析結果を受け取ります。

・ExampleFrontendActionクラス　中身は2行です。
　これが自分のFrontendActionクラスです。
　と言っても、ASTConsumerを継承した自分用オブジェクトの生成関数をオーバーライドするだけです。

・ExampleASTConsumerクラス
　これは自分用ASTConsumerクラスです。役割は2つあります。
　①コンストラクタで、PPCallbacksを継承した自分用オブジェクトを登録しています。
　②HandleTranslationUnit()をオーバーライドしています。
　　これは全てのAST解析が終了してから呼ばれます。
　　この中でASTをウォークスルーします。

[参考ページ](https://kevinaboos.wordpress.com/2013/07/23/clang-tutorial-part-ii-libtooling-example/ "CLANG TUTORIAL PART II: LIBTOOLING EXAMPLE")との相違について①

``` text:相違点１
参考ページでは最初にHandleTopLevelDecl()を紹介し、次により良い実装としてHandleTranslationUnit()を紹介しています。このHandleTopLevelDecl()ですが、AST解析中にトップレベル要素の解析が１つ終わる度に呼ばれます。namespaceがあるとそれがトップレベル要素になるため、namespaceが閉じるまで呼ばれませんからHandleTopLevelDecl()はイマイチ使いドコロが難しそうです。
```

####3.1.2.ソースの説明　－　プリプロセス追跡

・PPCallbacksTrackerクラス（これ1つです）
　ExampleASTConsumerのコンストラクタで登録する、自分用にカスタマイズしたPPCallbacksクラスです。
　今回はInclusionDirective()メンバー関数だけをオーバーライドしています。
　これは、プリプロセス中(同時にAST解析も進んでいます)に#includeに出会う度にコールバックされ、#include情報を教えてくれます。今回は#includeしたファイルのフル・パスをダンプしています。
　コールバック関数は非常に数多く用意されているようです。詳細は[公式ドキュメント](http://clang.llvm.org/doxygen/classclang_1_1PPCallbacks.html)やpp-traceを見るのが良いと思います。

####3.1.3.ソースの説明　－　ASTウォークスルー　【ここが今回の本題です】

・ExampleVisitorクラス(これ1つです)
　DeclVisitorクラスを継承してExampleVisitorを定義しています。

　ここで、ウォークスルーしたい要素に対応するVisit???Decl()関数をオーバーライドします。
　これは、ASTの中に???Declが現れる度によばれます。
　???Declは言語の様々な要素を示します。今回作ったASTダンプ・ツールでは下記を使っています。

|???Decl|C++要素|
|:--|:--|
|CXXRecordDecl|class, struct, union|
|FieldDecl|メンバー変数|
|NamespaceDecl|namespace定義|
|LinkageSpecDecl|extern "C", extern "C++"|

　???Declは本当に多数あり、調べただけでも下記のようなものもありました。

|???Decl|C++要素|
|:--|:--|
|CXXMethodDecl|メンバー関数|
|ClassTemplateDecl|クラス・テンプレート定義|
|ClassTemplateSpecializationDecl|クラス・テンプレートの特殊化定義|
|ClassTemplatePartialSpecializationDecl|クラス・テンプレートの部分特殊化定義|
|FunctionTemplateDecl|関数テンプレート|
|TypedefDecl|typedef|
|UsingDirectiveDecl|using|
|　　：　　|　　：　　|

``` text:Note
　???Declの一覧があると良いのですが、見つけることができませんでした。
　これらはExampleVisitor::EnumerateDecl()が呼び出しているVisit()関数の中でディスパッチされています。
　このVisit()関数は、clangソースのllvm\tools\clang\include\clang\AST\DeclVisitor.hの38行目で定義されています。これは幾つかのマクロを定義して、clangをビルドしたフォルダの\build-llvm-release\tools\clang\include\clang\AST\DeclNodes.incをインクルードして、case文を生成しています。
　ということは、一覧がDeclNodes.incにあることになるのですが、このファイル自体がclangをビルドする時に生成されているようなのです。その生成元までは追求しませんでした。
　今回のASTダンプ・ツールでは、検出された全てのDecl名を表示するようにしていますので、追跡したい言語要素が分かっていれば、それを含むソースをAST簡易ダンプすることでそのDecl名を調べることができると思います。
```

[参考ページ](https://kevinaboos.wordpress.com/2013/07/23/clang-tutorial-part-ii-libtooling-example/ "CLANG TUTORIAL PART II: LIBTOOLING EXAMPLE")との相違について②

``` text:相違点２
　参考ページでは、RecursiveASTVisitorクラスを派生してExampleVisitorを作り、HandleTopLevelDecl()からvisitor->TraverseDecl(D);を呼び出してウォクスルーしています。
　しかし、私はDeclVisitorクラスから派生し、自作のEnumerateDecl()を呼び出すように変更しました。
　私は、名前無しstructで定義された変数(struct {...} foo;のような定義)についても、変数名と結びつけて名前無しstructの内容を追跡したかったので、その変数用のVisitFieldDeclが呼ばれた時に名前無しstructの内容も追跡するようにしました。その場合にRecursiveASTVisitorを使うと、まず名前無しstructでVisitCXXRecordDecl()が呼ばれ、次にそれを使って定義した変数で呼ばれるため、2度同じ名前無しstructを追跡することになります。
　これを避けたかったので、1レベルだけ枚挙する再帰呼出可能なEnumerateDecl()関数を作って対応しています。そのため、一部自力で追跡処理する必要が出てきました。今回の場合はnamespaceとextern "C"/"C++"です。
```

###3.2.QtCreatorでのビルド方法
　まず、QtCreatorで新しいプロジェクトで「非Qtプロジェクト」の「C++プロジェクト」を作ります。
　exampleと言う名前でプロジェクトを作りました。

![新しいプロジェクト.png](https://qiita-image-store.s3.amazonaws.com/0/59362/b2be85fb-98c0-5838-138f-ad17ea9b4d6d.png)

　次に、このソースをビルドする際、当たり前ですがlibToolingのインクルードパスとライブラリを指定する必要があります。
　インクルードパスとライブラリパスは、clangをインストールしたフォルダの下のincludeとlibです。
　そして、ライブラリですが、[参考ページ](https://kevinaboos.wordpress.com/2013/07/23/clang-tutorial-part-ii-libtooling-example/ "CLANG TUTORIAL PART II: LIBTOOLING EXAMPLE")の[ソースが公開](https://github.com/kevinaboos/LibToolingExample "LibToolingExample")されているので、そのMakefileを参考に抽出しました。
　ちょっと苦労したのがLINK_COMPONENTSでの指定です。[ここ](http://llvm.org/docs/Projects.html#variables-for-building-programs)によるとllvm-config --libsと言うコマンドでライブラリがリストできるということでした。

　このままビルドすると「[C++11規格](http://ja.wikipedia.org/wiki/C%2B%2B11 "C++11")でコンパイルするように」等のエラーやその他の警告がでますので、エラーや警告が出ないようにするために幾つかのビルド・オプション(-std=c++11 -Wno-unused-parameter -fno-strict-aliasing)も与えました。
　更に、gccのライブラリをスタティック・リンクするオプションを与えました。（でないとgccのライブラリdllをコピーしないと単独で走らないから面倒なのです。）

　以上より、私のところではプロジェクト・ファイルであるexample.proを下記のように設定しました。（add for libTooling以下を追加してます。）
　なお、clangをビルドする際にインストール先としてN:\FOSS\LLVM-clang\install\releaseとN:\FOSS\LLVM-clang\install\debugを指定しています。

```mf:example.pro
TEMPLATE = app
CONFIG += console
CONFIG -= app_bundle
CONFIG -= qt

SOURCES += main.cpp

include(deployment.pri)
qtcAddDeployment()

# add for libTooling
QMAKE_CXXFLAGS += -std=c++11 -Wno-unused-parameter -fno-strict-aliasing
LIBS += -static -static-libgcc -static-libstdc++

win32:CONFIG(release, debug|release){
    INCLUDEPATH = N:\FOSS\LLVM-clang\install\release\include
    LIBS += -LN:\FOSS\LLVM-clang\install\release\lib
}
else:win32:CONFIG(debug, debug|release){
    INCLUDEPATH = N:\FOSS\LLVM-clang\install\debug\include
    LIBS += -LN:\FOSS\LLVM-clang\install\debug\lib
}

LIBS += -lclangFrontend -lclangSerialization -lclangDriver
LIBS += -lclangTooling -lclangParse -lclangSema
LIBS += -lclangAnalysis -lclangRewriteFrontend -lclangRewrite
LIBS += -lclangEdit -lclangAST -lclangLex -lclangBasic
LIBS += $(shell N:\FOSS\LLVM-clang\install\release\bin\llvm-config --libs mcparser bitreader support mc option)
# for MinGW
LIBS += -limagehlp
```

　最後に、デバッグ・ビルドとリリース・ビルドは下図の左下のボタンを押して切り替えることができます。最初はリリース・ビルドすると良いです。（デバッグ・ビルドは時間がかかります。）

![デバッグとリリース切替.png](https://qiita-image-store.s3.amazonaws.com/0/59362/2c2398fb-9ac3-c267-0962-e5c41e588ce8.png)

　以上の設定ができたら、QtCreatorのビルド・ボタン（左下にあるトンカチ・ボタンです）を押してビルドします。
　エラーがでなければ成功です。おめでとう！！

##4.AST簡易ダンプ・ツールの実行
　さて、いよいよ実行です。ちゃんとやるにはもう少し設定が必要なのですが、まずは設定がほぼ不要なダミー・ソースのASTをダンプしてみます。

###4.1.テスト用のダミー・ソースで通常実行
　プロジェクトを新しく作った時に「パス」を指定した筈ですので、その「パス」のフォルダに下記の２つのソースをおいて下さい。（main.cppやexample.proのあるフォルダの１つ上になります。）

```cpp:test.h
struct StructFoo {
    int m_Int;
};
```
```cpp:test.cpp
#include "test.h"

int main(void) {
  StructFoo foo;
  foo.m_Int=0;
  return foo.m_Int;
}
```

　QtCreatorで実行する時のカレント・フォルダのデフォルトは、上記test.cppを置いたフォルダの１つ下で、ビルドしたexeのあるフォルダの１つ上になります。
　これを踏まえてQtCreatorを設定します。

![実行①.png](https://qiita-image-store.s3.amazonaws.com/0/59362/a9ebf3ec-102e-169f-b4d8-9ce096214a97.png)

①「プロジェクト」をクリック。
②「実行」をクリック。(これはこっそりラジオ・ボタンです)
③ここにtest.cppを解析するようAST簡易ダンプ・ツールへのパラメータを設定します。

```text:パラメータ
..\test.cpp --
```

　これで設定終了です。
④の緑▲ボタンを押すと実行されます！！
　黒いウィンドウが表示されて、下記のような解析結果が表示されたら成功です。

```text:Result
InclusionDirective : "C:\example\build-example-Desktop_Qt_5_4_0_MinGW_32bit-Release\../test.h"


HandleTranslationUnit()
TopLevel : Typedef __builtin_va_list (<invalid loc>)
TopLevel : CXXRecord StructFoo (C:\example\build-example-Desktop_Qt_5_4_0_MinGW_32bit-Release\../test.h:1:11)
<<<====================================
struct StructFoo {
    int m_Int;
}
--------------------
CXXRecordDecl : StructFoo {
  FieldDecl : int m_Int
}
====================================>>>
TopLevel : Function main (C:\example\build-example-Desktop_Qt_5_4_0_MinGW_32bit-Release\..\test.cpp:3:5)
```

###4.2.テスト用のダミー・ソースでデバッグ実行
　デバッグ実行すれば、ブレークを張って中断・再開やステップ実行ができるので便利です。

　緑▲ボタンの上のボタンを押して「デバッグ」へ切り替え、「トンカチ」ボタンを押してビルドします。
　ブレークの張り方は多くのIDEと同じで、ソースを表示してブレークを張りたい行の頭付近をクリックです。
　そして、④の緑▲ボタンの下にあるルーペ付き緑▲ボタンを押すとデバッグ実行できます。

　・・・

　の筈だったのですが、Qt5.4.0のQtCreatorには[バグ](https://bugreports.qt.io/browse/QTCREATORBUG-13679 "Qt Creator does not recognize MinGW debugger")があり、ひっかかりました。
　しかし、[上記のリンクしているページ](https://bugreports.qt.io/browse/QTCREATORBUG-13679 "Qt Creator does not recognize MinGW debugger")に既に対策が載っていました。
　Qtを標準のC:\Qtへインストールした場合、
　　C:\Qt\Tools\QtCreator\share\qtcreator\QtProject\qtcreator\debuggers.xml
を下記のように修正して、QtCreatorを再起動すれば良いです。

```text
　　変更前>  <value type="uint" key="EngineType">0</value>
　　変更後>  <value type="uint" key="EngineType">1</value>
```

###4.3.AST簡易ダンプ・ツールのソースをAST簡易ダンプする
　上記のダミー・ソースは本当に単純で、インクルードパスの指定さえ不要でした。
　でも、一般には全てのヘッダがカレントにある筈もなく、インクルードパスの指定は必須です。
　また、libToolingは[C++11規格](http://ja.wikipedia.org/wiki/C%2B%2B11 "C++11")に対応する必要があります。（gccと同様libToolingでもC++を使えってエラーが出ます。）
　そこで、一般的なソースとしてmain.cppを簡易ダンプしてみます。

　そのためはもう少し設定が必要です。

####4.3.1.MinGWのインクルードパスについて
　今回、私はAST簡易ダンプ・ツールをMinGWでビルドしました。
　MinGWはコンパイルする際に[インクルードパスを自動生成](http://takuya-1st.hatenablog.jp/entry/20120920/1348511712 "gccのインクルードパスについて調べたこと")します。つまり、指定していないパスからもインクルードしちゃうのです。IDEにインクルードパスを設定しなくて良いので便利なのですが、今回のようなケースではハマります。

　libToolingも似た動作をするようですが、MinGWが自動生成するインクルードパスとは異なるのです。
　従って、「MinGWでビルドできるソース」を「libToolingで解析する」場合には、「MinGWが自動生成するインクルードパス」を「libToolingへ明示的に与える」必要があります。（ああ、ややこしい。）

``` text:私の環境のMinGWインクルードパス
#include "..." search starts here:
#include <...> search starts here:
 N:/Qt/Tools/mingw491_32/bin/../lib/gcc/i686-w64-mingw32/4.9.1/include
 N:/Qt/Tools/mingw491_32/bin/../lib/gcc/i686-w64-mingw32/4.9.1/include-fixed
 N:/Qt/Tools/mingw491_32/bin/../lib/gcc/i686-w64-mingw32/4.9.1/../../../../i686-w64-mingw32/include
 N:/Qt/Tools/mingw491_32/lib/gcc/../../i686-w64-mingw32/include/c++
 N:/Qt/Tools/mingw491_32/lib/gcc/../../i686-w64-mingw32/include/c++/i686-w64-mingw32
 N:/Qt/Tools/mingw491_32/lib/gcc/../../i686-w64-mingw32/include/c++/backward
End of search list.
```

　私の環境では、"g++ -v test.cpp"で表示して抜き出したところ、上記のようにインクルードパスが表示されました。また、clangのライブラリをインクルードするソースを解析する時はclangヘッダのインクルードパスも与える必要があります。
　従って、AST簡易ダンプ・ツールへ与えるインクルードパスのオプションは下記のようになります。

```text:インクルードパス・オプション
INC=-IN:/Qt/Tools/mingw491_32/lib/gcc/i686-w64-mingw32/4.9.1/include -IN:/Qt/Tools/mingw491_32/lib/gcc/i686-w64-mingw32/4.9.1/include-fixed -IN:/Qt/Tools/mingw491_32/i686-w64-mingw32/include -IN:/Qt/Tools/mingw491_32/i686-w64-mingw32/include/c++ -IN:/Qt/Tools/mingw491_32/i686-w64-mingw32/include/c++/i686-w64-mingw32 -IN:/Qt/Tools/mingw491_32/i686-w64-mingw32/include/c++/backward -IN:\FOSS\LLVM-clang\install\release\include
```
　あまりに長いので一旦環境変数へ記録することにしました。なので、環境変数INCへ設定する形式で書いています。

```text:Note
少しなりと短くしたかったので???/../を削除してますが、この削除は不要です。
寧ろ削除作業のミスがすっごく痛いので削除しない方が良いかも。私はこれでハマりました。orz
```

####4.3.2.AST簡易ダンプ・ツールへ与えるオプションの設定と実行
　main.cppがインクルードしているヘッダは本当に多くのヘッダをインクルードするので、結果は凄まじい行数になります。
　私のところでは1,000回以上インクルードし、10万行以上の結果が出力されました。
　そこで、出力をファイルへリダイレクトします。

　さて、main()関数の最初のCommonOptionsParserでコマンドライン・オプションを解析しています。これは、解析したいソース・ファイルのリストを"--"の前へ置き、"--"の後へlibToolingへ与えるオプションを置けば良いようです。そして、libToolingのオプションはgccとコンパチのようです。（CAUTION : この辺についてはあまり確認していません。なので間違っている可能性が高いです。ごめん。）

　以上を踏まえてQtCreatorを設定します。

![実行②.png](https://qiita-image-store.s3.amazonaws.com/0/59362/bea29ecf-3cbc-d791-0d17-380ea5098deb.png)


①ここにオプションを設定します。
②「詳細」をクリックすると⑤が表示されます。
③「一括編集」を押すと「環境変数の編集」ウィンドウが開きます。
　そこへ各自の環境に合わせた「インクルードパス・オプション」をコピペして、OKを押して下さい。

```text:オプション
..\example\main.cpp -- -std=c++11 %INC% >..\main.log 2>&1
```

④の緑▲ボタンを押すと実行されます！！
　数秒かけてAST簡易ダンプが、main.logに出力されます。

```text:Note
　なお、上記のように標準出力と標準エラー出力をリダイレクトしていると、デバッグ実行できません。デバッグ実行したい時は、">..\main.log 2>&1"を付けないようにして下さい。
```

　結果を見ると__builtin_???の未定義エラーが多量にでてます。
　clangはgccと基本的に互換性があるようですが、[一部非互換](http://clang.llvm.org/compatibility.html "Language Compatibility")です。
　特にSIMD命令の実装方法の違いが大きく、main.cppのAST解析でbuiltin関数に関連するエラーが多数（-ferror-limit=1000を与えると700回以上）出てしまうのです。

　たぶん、これらのbuiltin関数を宣言した独自ヘッダを内部的にインクルードする等で対策できるだろうと思いますか、なかなかたいへんそうです。
　builtin関数に関連したエラーしかでてないし、AST解析はできるので対策してません。

##5.あとがき
　QtCreatorは32bit版でも64bits版アプリをビルド・デバッグできることが分かっていたし、Qt本体は使わないので、Qtの64bits版はなくてもAST簡易ダンプ・ツールを64bitsビルドできると思い、64bitsビルドでこの投稿を作り始めました。が、間違いでした。（あうちっ）

　QtCreatorは、ビルドするための環境をkitとして管理しています。ここにコンパイラやデバッガを登録して使います。コンパイラとデバッガはMinGWに含まれていますが、もう一つqmakeも必要なことを忘れていました。

　qmakeはQtをビルドすればできますが、MinGWの64bits用のqmakeはQt公式からは配布されていません。つまり、上記のAST簡易ダンプ・ツールをMinGWで64bitsビルドする際にIDEとしてQtCreatorを使う場合に限り、QtをMinGWの64bitsビルドしておく必要があります。
　qmakeのためだけにQt一式をビルド（かなり時間がかかります）するのはあまりに勿体無いので、ターゲットを32bitsへ急遽変更しました。なので、なにかミスっているかも。もし、ミスを見つけたら教えて下さい。m(__)m

おしまい。