リポジトリを覗いたら、LLVM共々3.0 RC1が10/18に出ていた。リリースノートを見ると色々改善されている様子なので、環境を入れ替えてみる。
llvmとclangは普通にビルドが通ったが、自分のサンプルはエラーが多発した。
それぞれの内容と対処は以下の通り。
■dyn_castがビルドエラー
→llvm名前空間に入った。
→llvm::dyn_castに変更。
■clang::LangOptions.Microsoftがない
→おそらくMicrosoftExtとMicrosoftModeの2つに分割されたのだと思われる。
→両方trueに設定。
■clang::Diagnosticのコンストラクタの引数が変わった
→DiagnosticsEngineなるクラスができたようだ。
DiagnosticsEngineのコンストラクタは
・llvm::IntrusiveRefCntPtr
・DiagnosticConsumer
・bool ShouldOwnClient
の3引数を受け取る。第1引数は今までと同じだが、第2引数のDiagnosticConsumerはまた知らないクラスだ。ただしこっちはコンストラクタに引数がない。またDiagnosticsEngineはConsumerを受け取らなくてもいいっぽい。
→DiagnosticsEngineはConsumerなしで生成。
→後述の理由(実行時アサーション)により、やっぱり受け取らないと駄目なようだ。
よくよく確認すると、TextDiagnosticPrinterがDiagnosticConsumerの派生クラスになっている!
これを指定するよう修正。
■clang::TargetInfo::CreateTargetInfo()の引数が変わった。
→第1引数がclang::Diagnosticからclang::DiagnosticsEngineに変更されている。
→上記で作ったEngineをそのまま指定。
■clang::SourceManagerのコンストラクタの引数が変わった。
→上記と同様clang::Diagnosticからclang::DiagnosticsEngineに変更されている。
→上記で作ったEngineをそのまま指定。
■clang::Preprocessorのコンストラクタの引数が変わった。
→上記と同様clang::Diagnosticからclang::DiagnosticsEngineに変更されている。
・・・clang::Diagnosticの一部がDiagnosticsEngineに分割されたのかな?
第3引数のTargetInfoが参照からポインタに。
さらに以下の引数が追加された:
・ModuleLoader
・IdentifierInfoLookup
clang::ModuleLoaderはインターフェースであり、それを実装しているのはclang::ASTUnitとclang::CompilerInstanceである。
→上記で作ったEngineをそのまま指定。
ModuleLoaderにはCompilerInstanceを指定。
IdentifierInfoLookupはオプションっぽいのでnullptr指定。
■clang::Builtin::Contextのコンストラクタの引数が変わった。
→引数なしに。ただしInitializeTarget()なるメンバ関数がある。
→InitializeTarget()をコールするよう変更。
■clang::ASTContextのコンストラクタの引数が変わった。
→第3引数のTargetInfoが参照からポインタに。
▲clang::ASTReader::ReadAST()がリンクエラー。
→clangSerialization.libをリンク。
▲clang::driver::Arg::getAsString()がリンクエラー。
→clangDriver.libをリンク。
●実行時、DiagnosticIDs::ProcessDiag()でアサーション。
→DiagnosticsEngineにDiagnosticConsumerがセットされてないと判定NG。
→TextDiagnosticPrinterをDiagnosticsEngineのコンストラクタでConsumerとして設定。
以上の対応で動作した。今のコードはこんな感じ:
#include <iostream>
#include "llvm/Support/raw_ostream.h"
#include "llvm/Support/Host.h"
#include "clang/Frontend/DiagnosticOptions.h"
#include "clang/Frontend/TextDiagnosticPrinter.h"
#include "clang/Basic/LangOptions.h"
#include "clang/Basic/FileSystemOptions.h"
#include "clang/Basic/SourceManager.h"
#include "clang/Lex/HeaderSearch.h"
#include "clang/Basic/FileManager.h"
#include "clang/Frontend/HeaderSearchOptions.h"
#include "clang/Frontend/Utils.h"
#include "clang/Basic/TargetOptions.h"
#include "clang/Basic/TargetInfo.h"
#include "clang/Lex/Preprocessor.h"
#include "clang/Frontend/PreprocessorOptions.h"
#include "clang/Frontend/FrontendOptions.h"
#include "clang/Frontend/CompilerInstance.h"
#include "clang/Basic/IdentifierTable.h"
#include "clang/Basic/Builtins.h"
#include "clang/AST/ASTContext.h"
#include "clang/AST/ASTConsumer.h"
#include "clang/Sema/Sema.h"
#include "clang/AST/DeclBase.h"
#include "clang/AST/Type.h"
#include "clang/AST/Decl.h"
#include "clang/Sema/Lookup.h"
#include "clang/Sema/Ownership.h"
#include "clang/AST/DeclGroup.h"
#include "clang/AST/CXXInheritance.h"
#include "clang/Parse/Parser.h"
#include "clang/Parse/ParseAST.h"
class MyASTConsumer : public clang::ASTConsumer
{
public:
MyASTConsumer() : clang::ASTConsumer() { }
virtual ~MyASTConsumer() { }
virtual void HandleTopLevelDecl( clang::DeclGroupRef d)
{
static int count = 0;
clang::DeclGroupRef::iterator it;
for( it = d.begin(); it != d.end(); it++)
{
count++;
clang::VarDecl *vd = llvm::dyn_cast<clang::VarDecl>(*it);
if(!vd)
{
continue;
}
std::cout << vd << std::endl;
if( vd->isFileVarDecl() && vd->hasExternalStorage() )
{
std::cerr << "Read top-level variable decl: '";
std::cerr << vd->getDeclName().getAsString() ;
std::cerr << std::endl;
}
}
}
};
int main()
{
// 言語オプションをセットアップする。
clang::LangOptions langOpts;
langOpts.BCPLComment = true;
langOpts.Bool = true;
langOpts.MicrosoftExt = true;
langOpts.MicrosoftMode = true;
langOpts.CPlusPlus = true;
langOpts.CPlusPlus0x = true;
langOpts.Exceptions = true;
langOpts.CXXExceptions = true;
langOpts.MSBitfields = true;
langOpts.NeXTRuntime = false;
langOpts.NoBuiltin = true;
langOpts.MSCVersion = _MSC_VER;
// Diagnostic をセットアップする。
clang::DiagnosticOptions diagOpts;
clang::TextDiagnosticPrinter diagPrinter(llvm::outs(), diagOpts);
diagPrinter.BeginSourceFile(langOpts, NULL);
llvm::IntrusiveRefCntPtr<clang::DiagnosticIDs>
diagIds(new clang::DiagnosticIDs());
clang::DiagnosticsEngine diagEngine(diagIds, &diagPrinter, false);
clang::Diagnostic diag(&diagEngine);
// 動作環境オプションをセットアップする。
llvm::Triple triple;
triple.setArch(llvm::Triple::x86);
triple.setVendor(llvm::Triple::PC);
triple.setOS(llvm::Triple::Win32);
clang::TargetOptions targetOpts;
targetOpts.Triple = triple.getTriple();
clang::TargetInfo* targetInfo
= clang::TargetInfo::CreateTargetInfo(diagEngine, targetOpts);
// ソースファイル管理をセットアップする。
clang::FileSystemOptions fileSysOpts;
clang::FileManager fileMgr(fileSysOpts);
clang::SourceManager srcMgr(diagEngine, fileMgr);
// ヘッダ検索をセットアップする。
clang::HeaderSearch headerSearch(fileMgr);
clang::HeaderSearchOptions headerSearchOpts;
headerSearchOpts.AddPath("C:\\Program Files (x86)\\Microsoft Visual Studio 8\\VC\\include",
clang::frontend::Angled, false, false, false);
headerSearchOpts.AddPath("C:\\Program Files (x86)\\Microsoft Visual Studio 8\\VC\\PlatformSDK\\include",
clang::frontend::Angled, false, false, false);
clang::ApplyHeaderSearchOptions(headerSearch, headerSearchOpts, langOpts,
triple);
// プリプロセッサをセットアップする。
clang::CompilerInstance compiler;
clang::Preprocessor pp(diagEngine, langOpts, targetInfo, srcMgr, headerSearch, compiler);
clang::PreprocessorOptions ppOpts;
clang::FrontendOptions frontendOpts;
clang::InitializePreprocessor(pp, ppOpts, headerSearchOpts, frontendOpts);
const clang::FileEntry *pFile = fileMgr.getFile("D:\\develop\\Clang\\temp.cpp");
srcMgr.createMainFileID(pFile);
//pp.EnterMainSourceFile();
clang::IdentifierTable identifierTable(langOpts);
clang::SelectorTable selectorTable;
clang::Builtin::Context builtinContext;
builtinContext.InitializeTarget(*targetInfo);
clang::ASTContext astContext(
langOpts,
srcMgr,
targetInfo,
identifierTable,
selectorTable,
builtinContext,
0 /* size_reserve*/);
// clang::ASTConsumer astConsumer;
MyASTConsumer astConsumer;
clang::Sema sema(
pp,
astContext,
astConsumer);
sema.Initialize();
//MySemanticAnalisys mySema( pp, astContext, astConsumer);
//clang::Parser parser( pp, sema);
//parser.ParseTranslationUnit();
clang::ParseAST(pp, &astConsumer, astContext);
clang::ASTContext::const_type_iterator t = astContext.types_begin();
clang::ASTContext::const_type_iterator eot = astContext.types_end();
for(; t != eot; ++t)
{
clang::CXXRecordDecl* pDecl = (*t)->getAsCXXRecordDecl();
if( (pDecl != nullptr) && pDecl->isClass() )
{
if(pDecl->hasDefinition())
{
clang::CXXRecordDecl::base_class_iterator base = pDecl->bases_begin();
clang::CXXRecordDecl::base_class_iterator eobase = pDecl->bases_end();
for(; base != eobase; ++base)
{
base->getType().dump();
}
}
}
}
getchar();
return 0;
}