ASTUnit.cpp revision 36c4464ba6cfc2a63dc67c493ef2f5ab2aea09cc
1//===--- ASTUnit.cpp - ASTUnit utility ------------------------------------===//
2//
3//                     The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9//
10// ASTUnit Implementation.
11//
12//===----------------------------------------------------------------------===//
13
14#include "clang/Frontend/ASTUnit.h"
15#include "clang/Frontend/PCHReader.h"
16#include "clang/AST/ASTContext.h"
17#include "clang/AST/DeclVisitor.h"
18#include "clang/AST/StmtVisitor.h"
19#include "clang/Lex/HeaderSearch.h"
20#include "clang/Lex/Preprocessor.h"
21#include "clang/Basic/TargetInfo.h"
22#include "clang/Basic/Diagnostic.h"
23#include "llvm/Support/Compiler.h"
24#include "llvm/System/Path.h"
25
26using namespace clang;
27
28ASTUnit::ASTUnit() : tempFile(false) {
29  Diags.setClient(&DiagClient);
30}
31ASTUnit::~ASTUnit() {
32  if (tempFile)
33    llvm::sys::Path(getPCHFileName()).eraseFromDisk();
34}
35
36namespace {
37
38/// \brief Gathers information from PCHReader that will be used to initialize
39/// a Preprocessor.
40class VISIBILITY_HIDDEN PCHInfoCollector : public PCHReaderListener {
41  LangOptions &LangOpt;
42  HeaderSearch &HSI;
43  std::string &TargetTriple;
44  std::string &Predefines;
45  unsigned &Counter;
46
47  unsigned NumHeaderInfos;
48
49public:
50  PCHInfoCollector(LangOptions &LangOpt, HeaderSearch &HSI,
51                   std::string &TargetTriple, std::string &Predefines,
52                   unsigned &Counter)
53    : LangOpt(LangOpt), HSI(HSI), TargetTriple(TargetTriple),
54      Predefines(Predefines), Counter(Counter), NumHeaderInfos(0) {}
55
56  virtual bool ReadLanguageOptions(const LangOptions &LangOpts) {
57    LangOpt = LangOpts;
58    return false;
59  }
60
61  virtual bool ReadTargetTriple(const std::string &Triple) {
62    TargetTriple = Triple;
63    return false;
64  }
65
66  virtual bool ReadPredefinesBuffer(const char *PCHPredef,
67                                    unsigned PCHPredefLen,
68                                    FileID PCHBufferID,
69                                    std::string &SuggestedPredefines) {
70    Predefines = PCHPredef;
71    return false;
72  }
73
74  virtual void ReadHeaderFileInfo(const HeaderFileInfo &HFI) {
75    HSI.setHeaderFileInfoForUID(HFI, NumHeaderInfos++);
76  }
77
78  virtual void ReadCounter(unsigned Value) {
79    Counter = Value;
80  }
81};
82
83} // anonymous namespace
84
85const std::string &ASTUnit::getOriginalSourceFileName() {
86  return dyn_cast<PCHReader>(Ctx->getExternalSource())->getOriginalSourceFile();
87}
88
89const std::string &ASTUnit::getPCHFileName() {
90  return dyn_cast<PCHReader>(Ctx->getExternalSource())->getFileName();
91}
92
93ASTUnit *ASTUnit::LoadFromPCHFile(const std::string &Filename,
94                                  std::string *ErrMsg,
95                                  bool OnlyLocalDecls,
96                                  bool UseBumpAllocator) {
97  llvm::OwningPtr<ASTUnit> AST(new ASTUnit());
98  AST->OnlyLocalDecls = OnlyLocalDecls;
99  AST->HeaderInfo.reset(new HeaderSearch(AST->getFileManager()));
100
101  // Gather Info for preprocessor construction later on.
102
103  LangOptions LangInfo;
104  HeaderSearch &HeaderInfo = *AST->HeaderInfo.get();
105  std::string TargetTriple;
106  std::string Predefines;
107  unsigned Counter;
108
109  llvm::OwningPtr<PCHReader> Reader;
110  llvm::OwningPtr<ExternalASTSource> Source;
111
112  Reader.reset(new PCHReader(AST->getSourceManager(), AST->getFileManager(), AST->Diags));
113  Reader->setListener(new PCHInfoCollector(LangInfo, HeaderInfo, TargetTriple,
114                                           Predefines, Counter));
115
116  switch (Reader->ReadPCH(Filename)) {
117  case PCHReader::Success:
118    break;
119
120  case PCHReader::Failure:
121  case PCHReader::IgnorePCH:
122    if (ErrMsg)
123      *ErrMsg = "Could not load PCH file";
124    return NULL;
125  }
126
127  // PCH loaded successfully. Now create the preprocessor.
128
129  // Get information about the target being compiled for.
130  AST->Target.reset(TargetInfo::CreateTargetInfo(TargetTriple));
131  AST->PP.reset(new Preprocessor(AST->Diags, LangInfo, *AST->Target.get(),
132                                 AST->getSourceManager(), HeaderInfo));
133  Preprocessor &PP = *AST->PP.get();
134
135  PP.setPredefines(Reader->getSuggestedPredefines());
136  PP.setCounterValue(Counter);
137  Reader->setPreprocessor(PP);
138
139  // Create and initialize the ASTContext.
140
141  AST->Ctx.reset(new ASTContext(LangInfo,
142                                AST->getSourceManager(),
143                                *AST->Target.get(),
144                                PP.getIdentifierTable(),
145                                PP.getSelectorTable(),
146                                PP.getBuiltinInfo(),
147                                /* FreeMemory = */ !UseBumpAllocator,
148                                /* size_reserve = */0));
149  ASTContext &Context = *AST->Ctx.get();
150
151  Reader->InitializeContext(Context);
152
153  // Attach the PCH reader to the AST context as an external AST
154  // source, so that declarations will be deserialized from the
155  // PCH file as needed.
156  Source.reset(Reader.take());
157  Context.setExternalSource(Source);
158
159  return AST.take();
160}
161