blob: 3f07b880f795e274d9343738ba66c9b76d1a823b [file] [log] [blame]
Argyrios Kyrtzidis4b562cf2009-06-20 08:27:14 +00001//===--- 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
Argyrios Kyrtzidis0853a022009-06-20 08:08:23 +000014#include "clang/Frontend/ASTUnit.h"
15#include "clang/Frontend/PCHReader.h"
Argyrios Kyrtzidis0853a022009-06-20 08:08:23 +000016#include "clang/AST/ASTContext.h"
Daniel Dunbar521bf9c2009-12-01 09:51:01 +000017#include "clang/AST/ASTConsumer.h"
Argyrios Kyrtzidis0853a022009-06-20 08:08:23 +000018#include "clang/AST/DeclVisitor.h"
19#include "clang/AST/StmtVisitor.h"
Daniel Dunbar521bf9c2009-12-01 09:51:01 +000020#include "clang/Frontend/CompilerInstance.h"
21#include "clang/Frontend/FrontendActions.h"
22#include "clang/Frontend/FrontendOptions.h"
Argyrios Kyrtzidis0853a022009-06-20 08:08:23 +000023#include "clang/Lex/HeaderSearch.h"
24#include "clang/Lex/Preprocessor.h"
Daniel Dunbard58c03f2009-11-15 06:48:46 +000025#include "clang/Basic/TargetOptions.h"
Argyrios Kyrtzidis0853a022009-06-20 08:08:23 +000026#include "clang/Basic/TargetInfo.h"
27#include "clang/Basic/Diagnostic.h"
Daniel Dunbar521bf9c2009-12-01 09:51:01 +000028#include "llvm/LLVMContext.h"
Benjamin Kramer4a630d32009-10-18 11:34:14 +000029#include "llvm/System/Path.h"
Argyrios Kyrtzidis0853a022009-06-20 08:08:23 +000030using namespace clang;
31
Daniel Dunbar521bf9c2009-12-01 09:51:01 +000032ASTUnit::ASTUnit(DiagnosticClient *diagClient) : tempFile(false) {
Ted Kremenekfc062212009-10-19 21:44:57 +000033 Diags.setClient(diagClient ? diagClient : new TextDiagnosticBuffer());
Steve Naroff36c44642009-10-19 14:34:22 +000034}
Daniel Dunbar521bf9c2009-12-01 09:51:01 +000035ASTUnit::~ASTUnit() {
Steve Naroffe19944c2009-10-15 22:23:48 +000036 if (tempFile)
Benjamin Kramer4a630d32009-10-18 11:34:14 +000037 llvm::sys::Path(getPCHFileName()).eraseFromDisk();
Daniel Dunbar521bf9c2009-12-01 09:51:01 +000038
Ted Kremenekfc062212009-10-19 21:44:57 +000039 // The ASTUnit object owns the DiagnosticClient.
40 delete Diags.getClient();
Steve Naroffe19944c2009-10-15 22:23:48 +000041}
Argyrios Kyrtzidis0853a022009-06-20 08:08:23 +000042
43namespace {
44
45/// \brief Gathers information from PCHReader that will be used to initialize
46/// a Preprocessor.
Benjamin Kramerbd218282009-11-28 10:07:24 +000047class PCHInfoCollector : public PCHReaderListener {
Argyrios Kyrtzidis0853a022009-06-20 08:08:23 +000048 LangOptions &LangOpt;
49 HeaderSearch &HSI;
50 std::string &TargetTriple;
51 std::string &Predefines;
52 unsigned &Counter;
Mike Stump1eb44332009-09-09 15:08:12 +000053
Argyrios Kyrtzidis0853a022009-06-20 08:08:23 +000054 unsigned NumHeaderInfos;
Mike Stump1eb44332009-09-09 15:08:12 +000055
Argyrios Kyrtzidis0853a022009-06-20 08:08:23 +000056public:
57 PCHInfoCollector(LangOptions &LangOpt, HeaderSearch &HSI,
58 std::string &TargetTriple, std::string &Predefines,
59 unsigned &Counter)
60 : LangOpt(LangOpt), HSI(HSI), TargetTriple(TargetTriple),
61 Predefines(Predefines), Counter(Counter), NumHeaderInfos(0) {}
Mike Stump1eb44332009-09-09 15:08:12 +000062
Argyrios Kyrtzidis0853a022009-06-20 08:08:23 +000063 virtual bool ReadLanguageOptions(const LangOptions &LangOpts) {
64 LangOpt = LangOpts;
65 return false;
66 }
Mike Stump1eb44332009-09-09 15:08:12 +000067
Daniel Dunbardc3c0d22009-11-11 00:52:11 +000068 virtual bool ReadTargetTriple(llvm::StringRef Triple) {
Argyrios Kyrtzidis0853a022009-06-20 08:08:23 +000069 TargetTriple = Triple;
70 return false;
71 }
Mike Stump1eb44332009-09-09 15:08:12 +000072
Daniel Dunbardc3c0d22009-11-11 00:52:11 +000073 virtual bool ReadPredefinesBuffer(llvm::StringRef PCHPredef,
Argyrios Kyrtzidis0853a022009-06-20 08:08:23 +000074 FileID PCHBufferID,
Daniel Dunbar7b5a1212009-11-11 05:29:04 +000075 llvm::StringRef OriginalFileName,
Argyrios Kyrtzidis0853a022009-06-20 08:08:23 +000076 std::string &SuggestedPredefines) {
77 Predefines = PCHPredef;
78 return false;
79 }
Mike Stump1eb44332009-09-09 15:08:12 +000080
Argyrios Kyrtzidis0853a022009-06-20 08:08:23 +000081 virtual void ReadHeaderFileInfo(const HeaderFileInfo &HFI) {
82 HSI.setHeaderFileInfoForUID(HFI, NumHeaderInfos++);
83 }
Mike Stump1eb44332009-09-09 15:08:12 +000084
Argyrios Kyrtzidis0853a022009-06-20 08:08:23 +000085 virtual void ReadCounter(unsigned Value) {
86 Counter = Value;
87 }
88};
89
90} // anonymous namespace
91
Steve Naroff77accc12009-09-03 18:19:54 +000092const std::string &ASTUnit::getOriginalSourceFileName() {
93 return dyn_cast<PCHReader>(Ctx->getExternalSource())->getOriginalSourceFile();
94}
Argyrios Kyrtzidis0853a022009-06-20 08:08:23 +000095
Steve Naroffe19944c2009-10-15 22:23:48 +000096const std::string &ASTUnit::getPCHFileName() {
97 return dyn_cast<PCHReader>(Ctx->getExternalSource())->getFileName();
98}
99
Argyrios Kyrtzidis0853a022009-06-20 08:08:23 +0000100ASTUnit *ASTUnit::LoadFromPCHFile(const std::string &Filename,
Douglas Gregor7d1d49d2009-10-16 20:01:17 +0000101 std::string *ErrMsg,
Ted Kremenekfc062212009-10-19 21:44:57 +0000102 DiagnosticClient *diagClient,
Ted Kremenek5cf48762009-10-17 00:34:24 +0000103 bool OnlyLocalDecls,
104 bool UseBumpAllocator) {
Ted Kremenekfc062212009-10-19 21:44:57 +0000105 llvm::OwningPtr<ASTUnit> AST(new ASTUnit(diagClient));
Douglas Gregor7d1d49d2009-10-16 20:01:17 +0000106 AST->OnlyLocalDecls = OnlyLocalDecls;
Steve Naroff36c44642009-10-19 14:34:22 +0000107 AST->HeaderInfo.reset(new HeaderSearch(AST->getFileManager()));
Argyrios Kyrtzidis0853a022009-06-20 08:08:23 +0000108
109 // Gather Info for preprocessor construction later on.
Mike Stump1eb44332009-09-09 15:08:12 +0000110
Argyrios Kyrtzidis0853a022009-06-20 08:08:23 +0000111 LangOptions LangInfo;
112 HeaderSearch &HeaderInfo = *AST->HeaderInfo.get();
113 std::string TargetTriple;
114 std::string Predefines;
115 unsigned Counter;
116
Daniel Dunbarbce6f622009-09-03 05:59:50 +0000117 llvm::OwningPtr<PCHReader> Reader;
Argyrios Kyrtzidis0853a022009-06-20 08:08:23 +0000118 llvm::OwningPtr<ExternalASTSource> Source;
119
Ted Kremenekfc062212009-10-19 21:44:57 +0000120 Reader.reset(new PCHReader(AST->getSourceManager(), AST->getFileManager(),
121 AST->Diags));
Daniel Dunbarcc318932009-09-03 05:59:35 +0000122 Reader->setListener(new PCHInfoCollector(LangInfo, HeaderInfo, TargetTriple,
123 Predefines, Counter));
124
125 switch (Reader->ReadPCH(Filename)) {
Argyrios Kyrtzidis0853a022009-06-20 08:08:23 +0000126 case PCHReader::Success:
127 break;
Mike Stump1eb44332009-09-09 15:08:12 +0000128
Argyrios Kyrtzidis0853a022009-06-20 08:08:23 +0000129 case PCHReader::Failure:
Argyrios Kyrtzidis106c9982009-06-25 18:22:30 +0000130 case PCHReader::IgnorePCH:
Argyrios Kyrtzidis0853a022009-06-20 08:08:23 +0000131 if (ErrMsg)
132 *ErrMsg = "Could not load PCH file";
133 return NULL;
Argyrios Kyrtzidis0853a022009-06-20 08:08:23 +0000134 }
Mike Stump1eb44332009-09-09 15:08:12 +0000135
Argyrios Kyrtzidis0853a022009-06-20 08:08:23 +0000136 // PCH loaded successfully. Now create the preprocessor.
Mike Stump1eb44332009-09-09 15:08:12 +0000137
Argyrios Kyrtzidis0853a022009-06-20 08:08:23 +0000138 // Get information about the target being compiled for.
Daniel Dunbard58c03f2009-11-15 06:48:46 +0000139 //
140 // FIXME: This is broken, we should store the TargetOptions in the PCH.
141 TargetOptions TargetOpts;
142 TargetOpts.ABI = "";
143 TargetOpts.CPU = "";
144 TargetOpts.Features.clear();
145 TargetOpts.Triple = TargetTriple;
146 AST->Target.reset(TargetInfo::CreateTargetInfo(AST->Diags, TargetOpts));
Daniel Dunbar31b87d82009-09-21 03:03:39 +0000147 AST->PP.reset(new Preprocessor(AST->Diags, LangInfo, *AST->Target.get(),
148 AST->getSourceManager(), HeaderInfo));
Argyrios Kyrtzidis0853a022009-06-20 08:08:23 +0000149 Preprocessor &PP = *AST->PP.get();
150
Daniel Dunbard5b61262009-09-21 03:03:47 +0000151 PP.setPredefines(Reader->getSuggestedPredefines());
Argyrios Kyrtzidis0853a022009-06-20 08:08:23 +0000152 PP.setCounterValue(Counter);
Daniel Dunbarcc318932009-09-03 05:59:35 +0000153 Reader->setPreprocessor(PP);
Mike Stump1eb44332009-09-09 15:08:12 +0000154
Argyrios Kyrtzidis0853a022009-06-20 08:08:23 +0000155 // Create and initialize the ASTContext.
156
157 AST->Ctx.reset(new ASTContext(LangInfo,
Daniel Dunbar31b87d82009-09-21 03:03:39 +0000158 AST->getSourceManager(),
Argyrios Kyrtzidis0853a022009-06-20 08:08:23 +0000159 *AST->Target.get(),
160 PP.getIdentifierTable(),
161 PP.getSelectorTable(),
162 PP.getBuiltinInfo(),
Ted Kremenek5cf48762009-10-17 00:34:24 +0000163 /* FreeMemory = */ !UseBumpAllocator,
Argyrios Kyrtzidis0853a022009-06-20 08:08:23 +0000164 /* size_reserve = */0));
165 ASTContext &Context = *AST->Ctx.get();
Mike Stump1eb44332009-09-09 15:08:12 +0000166
Daniel Dunbarcc318932009-09-03 05:59:35 +0000167 Reader->InitializeContext(Context);
Mike Stump1eb44332009-09-09 15:08:12 +0000168
Argyrios Kyrtzidis0853a022009-06-20 08:08:23 +0000169 // Attach the PCH reader to the AST context as an external AST
170 // source, so that declarations will be deserialized from the
171 // PCH file as needed.
Daniel Dunbarcc318932009-09-03 05:59:35 +0000172 Source.reset(Reader.take());
Argyrios Kyrtzidis0853a022009-06-20 08:08:23 +0000173 Context.setExternalSource(Source);
174
Mike Stump1eb44332009-09-09 15:08:12 +0000175 return AST.take();
Argyrios Kyrtzidis0853a022009-06-20 08:08:23 +0000176}
Daniel Dunbar521bf9c2009-12-01 09:51:01 +0000177
178namespace {
179
180class NullAction : public ASTFrontendAction {
181 virtual ASTConsumer *CreateASTConsumer(CompilerInstance &CI,
182 llvm::StringRef InFile) {
183 return new ASTConsumer();
184 }
185
186public:
187 virtual bool hasCodeCompletionSupport() const { return false; }
188};
189
190}
191
192ASTUnit *ASTUnit::LoadFromCompilerInvocation(const CompilerInvocation &CI,
193 Diagnostic &Diags,
194 bool OnlyLocalDecls,
195 bool UseBumpAllocator) {
196 // Create the compiler instance to use for building the AST.
197 CompilerInstance Clang(&llvm::getGlobalContext(), false);
198 llvm::OwningPtr<ASTUnit> AST;
199 NullAction Act;
200
201 Clang.getInvocation() = CI;
202
203 Clang.setDiagnostics(&Diags);
204 Clang.setDiagnosticClient(Diags.getClient());
205
206 // Create the target instance.
207 Clang.setTarget(TargetInfo::CreateTargetInfo(Clang.getDiagnostics(),
208 Clang.getTargetOpts()));
209 if (!Clang.hasTarget())
210 goto error;
211
212 // Inform the target of the language options.
213 //
214 // FIXME: We shouldn't need to do this, the target should be immutable once
215 // created. This complexity should be lifted elsewhere.
216 Clang.getTarget().setForcedLangOptions(Clang.getLangOpts());
217
218 assert(Clang.getFrontendOpts().Inputs.size() == 1 &&
219 "Invocation must have exactly one source file!");
220 assert(Clang.getFrontendOpts().Inputs[0].first != FrontendOptions::IK_AST &&
221 "FIXME: AST inputs not yet supported here!");
222
223 // Create the AST unit.
224 //
225 // FIXME: Use the provided diagnostic client.
226 AST.reset(new ASTUnit());
227
228 // Create a file manager object to provide access to and cache the filesystem.
229 Clang.setFileManager(&AST->getFileManager());
230
231 // Create the source manager.
232 Clang.setSourceManager(&AST->getSourceManager());
233
234 // Create the preprocessor.
235 Clang.createPreprocessor();
236
237 if (!Act.BeginSourceFile(Clang, Clang.getFrontendOpts().Inputs[0].second,
238 /*IsAST=*/false))
239 goto error;
240
241 Act.Execute();
242
Daniel Dunbar64a32ba2009-12-01 21:57:33 +0000243 // Steal the created target, context, and preprocessor, and take back the
244 // source and file managers.
Daniel Dunbar521bf9c2009-12-01 09:51:01 +0000245 AST->Ctx.reset(Clang.takeASTContext());
246 AST->PP.reset(Clang.takePreprocessor());
247 Clang.takeSourceManager();
248 Clang.takeFileManager();
Daniel Dunbar64a32ba2009-12-01 21:57:33 +0000249 AST->Target.reset(Clang.takeTarget());
Daniel Dunbar521bf9c2009-12-01 09:51:01 +0000250
251 Act.EndSourceFile();
252
253 Clang.takeDiagnosticClient();
254 Clang.takeDiagnostics();
255
256 return AST.take();
257
258error:
259 Clang.takeSourceManager();
260 Clang.takeFileManager();
261 Clang.takeDiagnosticClient();
262 Clang.takeDiagnostics();
263 return 0;
264}