From 0853a02c3b04d96a3c432b883e403175c954cd81 Mon Sep 17 00:00:00 2001 From: Argyrios Kyrtzidis Date: Sat, 20 Jun 2009 08:08:23 +0000 Subject: [PATCH] Introduce the ASTUnit class. ASTUnit is a helper class to allow easy loading of an ASTContext from a PCH file. No users for now. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@73819 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/clang/Frontend/ASTUnit.h | 62 +++++++++++++ lib/Frontend/ASTUnit.cpp | 146 +++++++++++++++++++++++++++++++ 2 files changed, 208 insertions(+) create mode 100644 include/clang/Frontend/ASTUnit.h create mode 100644 lib/Frontend/ASTUnit.cpp diff --git a/include/clang/Frontend/ASTUnit.h b/include/clang/Frontend/ASTUnit.h new file mode 100644 index 0000000000..1cbe2e2e27 --- /dev/null +++ b/include/clang/Frontend/ASTUnit.h @@ -0,0 +1,62 @@ +#ifndef LLVM_CLANG_FRONTEND_ASTUNIT_H +#define LLVM_CLANG_FRONTEND_ASTUNIT_H + +#include "llvm/ADT/OwningPtr.h" +#include + +namespace clang { + class FileManager; + class FileEntry; + class SourceManager; + class DiagnosticClient; + class Diagnostic; + class HeaderSearch; + class TargetInfo; + class Preprocessor; + class ASTContext; + class Decl; + +/// \brief Utility class for loading a ASTContext from a PCH file. +/// +class ASTUnit { + llvm::OwningPtr SourceMgr; + llvm::OwningPtr DiagClient; + llvm::OwningPtr Diags; + llvm::OwningPtr HeaderInfo; + llvm::OwningPtr Target; + llvm::OwningPtr PP; + llvm::OwningPtr Ctx; + + ASTUnit(const ASTUnit&); // do not implement + ASTUnit &operator=(const ASTUnit &); // do not implement + ASTUnit(); + +public: + ~ASTUnit(); + + const SourceManager &getSourceManager() const { return *SourceMgr.get(); } + SourceManager &getSourceManager() { return *SourceMgr.get(); } + + const Preprocessor &getPreprocessor() const { return *PP.get(); } + Preprocessor &getPreprocessor() { return *PP.get(); } + + const ASTContext &getASTContext() const { return *Ctx.get(); } + ASTContext &getASTContext() { return *Ctx.get(); } + + /// \brief Create a ASTUnit from a PCH file. + /// + /// \param Filename PCH filename + /// + /// \param FileMgr The FileManager to use + /// + /// \param ErrMsg Error message to report if the PCH file could not be loaded + /// + /// \returns the initialized ASTUnit or NULL if the PCH failed to load + static ASTUnit *LoadFromPCHFile(const std::string &Filename, + FileManager &FileMgr, + std::string *ErrMsg = 0); +}; + +} // namespace clang + +#endif diff --git a/lib/Frontend/ASTUnit.cpp b/lib/Frontend/ASTUnit.cpp new file mode 100644 index 0000000000..6ed8fbd5d8 --- /dev/null +++ b/lib/Frontend/ASTUnit.cpp @@ -0,0 +1,146 @@ +#include "clang/Frontend/ASTUnit.h" +#include "clang/Frontend/PCHReader.h" +#include "clang/Frontend/TextDiagnosticBuffer.h" +#include "clang/AST/ASTContext.h" +#include "clang/AST/DeclVisitor.h" +#include "clang/AST/StmtVisitor.h" +#include "clang/Lex/HeaderSearch.h" +#include "clang/Lex/Preprocessor.h" +#include "clang/Basic/TargetInfo.h" +#include "clang/Basic/Diagnostic.h" +#include "llvm/Support/Compiler.h" + +using namespace clang; + +ASTUnit::ASTUnit() { } +ASTUnit::~ASTUnit() { } + +namespace { + +/// \brief Gathers information from PCHReader that will be used to initialize +/// a Preprocessor. +class VISIBILITY_HIDDEN PCHInfoCollector : public PCHReaderListener { + LangOptions &LangOpt; + HeaderSearch &HSI; + std::string &TargetTriple; + std::string &Predefines; + unsigned &Counter; + + unsigned NumHeaderInfos; + +public: + PCHInfoCollector(LangOptions &LangOpt, HeaderSearch &HSI, + std::string &TargetTriple, std::string &Predefines, + unsigned &Counter) + : LangOpt(LangOpt), HSI(HSI), TargetTriple(TargetTriple), + Predefines(Predefines), Counter(Counter), NumHeaderInfos(0) {} + + virtual bool ReadLanguageOptions(const LangOptions &LangOpts) { + LangOpt = LangOpts; + return false; + } + + virtual bool ReadTargetTriple(const std::string &Triple) { + TargetTriple = Triple; + return false; + } + + virtual bool ReadPredefinesBuffer(const char *PCHPredef, + unsigned PCHPredefLen, + FileID PCHBufferID, + std::string &SuggestedPredefines) { + Predefines = PCHPredef; + return false; + } + + virtual void ReadHeaderFileInfo(const HeaderFileInfo &HFI) { + HSI.setHeaderFileInfoForUID(HFI, NumHeaderInfos++); + } + + virtual void ReadCounter(unsigned Value) { + Counter = Value; + } +}; + +} // anonymous namespace + + +ASTUnit *ASTUnit::LoadFromPCHFile(const std::string &Filename, + FileManager &FileMgr, + std::string *ErrMsg) { + + llvm::OwningPtr AST(new ASTUnit()); + + AST->DiagClient.reset(new TextDiagnosticBuffer()); + AST->Diags.reset(new Diagnostic(AST->DiagClient.get())); + + AST->HeaderInfo.reset(new HeaderSearch(FileMgr)); + AST->SourceMgr.reset(new SourceManager()); + + Diagnostic &Diags = *AST->Diags.get(); + SourceManager &SourceMgr = *AST->SourceMgr.get(); + + // Gather Info for preprocessor construction later on. + + LangOptions LangInfo; + HeaderSearch &HeaderInfo = *AST->HeaderInfo.get(); + std::string TargetTriple; + std::string Predefines; + unsigned Counter; + + llvm::OwningPtr Reader; + llvm::OwningPtr Source; + + Reader.reset(new PCHReader(SourceMgr, FileMgr, Diags)); + Reader->setListener(new PCHInfoCollector(LangInfo, HeaderInfo, TargetTriple, + Predefines, Counter)); + + switch (Reader->ReadPCH(Filename)) { + case PCHReader::Success: + break; + + case PCHReader::Failure: + // Unrecoverable failure: don't even try to process the input + // file. + if (ErrMsg) + *ErrMsg = "Could not load PCH file"; + return NULL; + + case PCHReader::IgnorePCH: + assert(0 && "Is there a validation that should not have happened ?"); + } + + // PCH loaded successfully. Now create the preprocessor. + + // Get information about the target being compiled for. + AST->Target.reset(TargetInfo::CreateTargetInfo(TargetTriple)); + AST->PP.reset(new Preprocessor(Diags, LangInfo, *AST->Target.get(), + SourceMgr, HeaderInfo)); + Preprocessor &PP = *AST->PP.get(); + + PP.setPredefines(Predefines); + PP.setCounterValue(Counter); + Reader->setPreprocessor(PP); + + // Create and initialize the ASTContext. + + AST->Ctx.reset(new ASTContext(LangInfo, + SourceMgr, + *AST->Target.get(), + PP.getIdentifierTable(), + PP.getSelectorTable(), + PP.getBuiltinInfo(), + /* FreeMemory = */ true, + /* size_reserve = */0)); + ASTContext &Context = *AST->Ctx.get(); + + Reader->InitializeContext(Context); + + // Attach the PCH reader to the AST context as an external AST + // source, so that declarations will be deserialized from the + // PCH file as needed. + Source.reset(Reader.take()); + Context.setExternalSource(Source); + + return AST.take(); +}