2011年10月26日水曜日

CLangをビルド(Release3.0 RC1)


リポジトリを覗いたら、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;
}

0 件のコメント:

コメントを投稿