blob: 88c55a885a22a0b79db32abe3192be201deb5804 [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"
Douglas Gregor1d715ac2010-08-03 08:14:03 +000015#include "clang/Frontend/PCHWriter.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 Dunbar7b556682009-12-02 03:23:45 +000020#include "clang/Driver/Compilation.h"
21#include "clang/Driver/Driver.h"
22#include "clang/Driver/Job.h"
23#include "clang/Driver/Tool.h"
Daniel Dunbar521bf9c2009-12-01 09:51:01 +000024#include "clang/Frontend/CompilerInstance.h"
25#include "clang/Frontend/FrontendActions.h"
Daniel Dunbar7b556682009-12-02 03:23:45 +000026#include "clang/Frontend/FrontendDiagnostic.h"
Daniel Dunbar521bf9c2009-12-01 09:51:01 +000027#include "clang/Frontend/FrontendOptions.h"
Douglas Gregor1d715ac2010-08-03 08:14:03 +000028#include "clang/Frontend/PCHReader.h"
Argyrios Kyrtzidis0853a022009-06-20 08:08:23 +000029#include "clang/Lex/HeaderSearch.h"
30#include "clang/Lex/Preprocessor.h"
Daniel Dunbard58c03f2009-11-15 06:48:46 +000031#include "clang/Basic/TargetOptions.h"
Argyrios Kyrtzidis0853a022009-06-20 08:08:23 +000032#include "clang/Basic/TargetInfo.h"
33#include "clang/Basic/Diagnostic.h"
Douglas Gregor4db64a42010-01-23 00:14:00 +000034#include "llvm/Support/MemoryBuffer.h"
Daniel Dunbar7b556682009-12-02 03:23:45 +000035#include "llvm/System/Host.h"
Benjamin Kramer4a630d32009-10-18 11:34:14 +000036#include "llvm/System/Path.h"
Douglas Gregor385103b2010-07-30 20:58:08 +000037#include "llvm/Support/Timer.h"
Douglas Gregor44c181a2010-07-23 00:33:23 +000038#include <cstdlib>
Zhongxing Xuad23ebe2010-07-23 02:15:08 +000039#include <cstdio>
Douglas Gregorcc5888d2010-07-31 00:40:00 +000040#include <sys/stat.h>
Argyrios Kyrtzidis0853a022009-06-20 08:08:23 +000041using namespace clang;
42
Douglas Gregoreababfb2010-08-04 05:53:38 +000043/// \brief After failing to build a precompiled preamble (due to
44/// errors in the source that occurs in the preamble), the number of
45/// reparses during which we'll skip even trying to precompile the
46/// preamble.
47const unsigned DefaultPreambleRebuildInterval = 5;
48
Douglas Gregor3687e9d2010-04-05 21:10:19 +000049ASTUnit::ASTUnit(bool _MainFileIsAST)
Douglas Gregorabc563f2010-07-19 21:46:24 +000050 : CaptureDiagnostics(false), MainFileIsAST(_MainFileIsAST),
Douglas Gregoreababfb2010-08-04 05:53:38 +000051 ConcurrencyCheckValue(CheckUnlocked), PreambleRebuildCounter(0),
52 SavedMainFileBuffer(0) {
Douglas Gregor385103b2010-07-30 20:58:08 +000053}
Douglas Gregor3687e9d2010-04-05 21:10:19 +000054
Daniel Dunbar521bf9c2009-12-01 09:51:01 +000055ASTUnit::~ASTUnit() {
Douglas Gregorbdf60622010-03-05 21:16:25 +000056 ConcurrencyCheckValue = CheckLocked;
Douglas Gregorabc563f2010-07-19 21:46:24 +000057 CleanTemporaryFiles();
Douglas Gregor175c4a92010-07-23 23:58:40 +000058 if (!PreambleFile.empty())
Douglas Gregor385103b2010-07-30 20:58:08 +000059 llvm::sys::Path(PreambleFile).eraseFromDisk();
Douglas Gregorf4f6c9d2010-07-26 21:36:20 +000060
61 // Free the buffers associated with remapped files. We are required to
62 // perform this operation here because we explicitly request that the
63 // compiler instance *not* free these buffers for each invocation of the
64 // parser.
65 if (Invocation.get()) {
66 PreprocessorOptions &PPOpts = Invocation->getPreprocessorOpts();
67 for (PreprocessorOptions::remapped_file_buffer_iterator
68 FB = PPOpts.remapped_file_buffer_begin(),
69 FBEnd = PPOpts.remapped_file_buffer_end();
70 FB != FBEnd;
71 ++FB)
72 delete FB->second;
73 }
Douglas Gregor28233422010-07-27 14:52:07 +000074
75 delete SavedMainFileBuffer;
Douglas Gregor385103b2010-07-30 20:58:08 +000076
77 for (unsigned I = 0, N = Timers.size(); I != N; ++I)
78 delete Timers[I];
Douglas Gregorabc563f2010-07-19 21:46:24 +000079}
80
81void ASTUnit::CleanTemporaryFiles() {
Douglas Gregor313e26c2010-02-18 23:35:40 +000082 for (unsigned I = 0, N = TemporaryFiles.size(); I != N; ++I)
83 TemporaryFiles[I].eraseFromDisk();
Douglas Gregorabc563f2010-07-19 21:46:24 +000084 TemporaryFiles.clear();
Steve Naroffe19944c2009-10-15 22:23:48 +000085}
Argyrios Kyrtzidis0853a022009-06-20 08:08:23 +000086
87namespace {
88
89/// \brief Gathers information from PCHReader that will be used to initialize
90/// a Preprocessor.
Benjamin Kramerbd218282009-11-28 10:07:24 +000091class PCHInfoCollector : public PCHReaderListener {
Argyrios Kyrtzidis0853a022009-06-20 08:08:23 +000092 LangOptions &LangOpt;
93 HeaderSearch &HSI;
94 std::string &TargetTriple;
95 std::string &Predefines;
96 unsigned &Counter;
Mike Stump1eb44332009-09-09 15:08:12 +000097
Argyrios Kyrtzidis0853a022009-06-20 08:08:23 +000098 unsigned NumHeaderInfos;
Mike Stump1eb44332009-09-09 15:08:12 +000099
Argyrios Kyrtzidis0853a022009-06-20 08:08:23 +0000100public:
101 PCHInfoCollector(LangOptions &LangOpt, HeaderSearch &HSI,
102 std::string &TargetTriple, std::string &Predefines,
103 unsigned &Counter)
104 : LangOpt(LangOpt), HSI(HSI), TargetTriple(TargetTriple),
105 Predefines(Predefines), Counter(Counter), NumHeaderInfos(0) {}
Mike Stump1eb44332009-09-09 15:08:12 +0000106
Argyrios Kyrtzidis0853a022009-06-20 08:08:23 +0000107 virtual bool ReadLanguageOptions(const LangOptions &LangOpts) {
108 LangOpt = LangOpts;
109 return false;
110 }
Mike Stump1eb44332009-09-09 15:08:12 +0000111
Daniel Dunbardc3c0d22009-11-11 00:52:11 +0000112 virtual bool ReadTargetTriple(llvm::StringRef Triple) {
Argyrios Kyrtzidis0853a022009-06-20 08:08:23 +0000113 TargetTriple = Triple;
114 return false;
115 }
Mike Stump1eb44332009-09-09 15:08:12 +0000116
Sebastian Redlcb481aa2010-07-14 23:29:55 +0000117 virtual bool ReadPredefinesBuffer(const PCHPredefinesBlocks &Buffers,
Daniel Dunbar7b5a1212009-11-11 05:29:04 +0000118 llvm::StringRef OriginalFileName,
Argyrios Kyrtzidis0853a022009-06-20 08:08:23 +0000119 std::string &SuggestedPredefines) {
Sebastian Redlcb481aa2010-07-14 23:29:55 +0000120 Predefines = Buffers[0].Data;
121 for (unsigned I = 1, N = Buffers.size(); I != N; ++I) {
122 Predefines += Buffers[I].Data;
123 }
Argyrios Kyrtzidis0853a022009-06-20 08:08:23 +0000124 return false;
125 }
Mike Stump1eb44332009-09-09 15:08:12 +0000126
Douglas Gregorec1afbf2010-03-16 19:09:18 +0000127 virtual void ReadHeaderFileInfo(const HeaderFileInfo &HFI, unsigned ID) {
Argyrios Kyrtzidis0853a022009-06-20 08:08:23 +0000128 HSI.setHeaderFileInfoForUID(HFI, NumHeaderInfos++);
129 }
Mike Stump1eb44332009-09-09 15:08:12 +0000130
Argyrios Kyrtzidis0853a022009-06-20 08:08:23 +0000131 virtual void ReadCounter(unsigned Value) {
132 Counter = Value;
133 }
134};
135
Douglas Gregora88084b2010-02-18 18:08:43 +0000136class StoredDiagnosticClient : public DiagnosticClient {
137 llvm::SmallVectorImpl<StoredDiagnostic> &StoredDiags;
138
139public:
140 explicit StoredDiagnosticClient(
141 llvm::SmallVectorImpl<StoredDiagnostic> &StoredDiags)
142 : StoredDiags(StoredDiags) { }
143
144 virtual void HandleDiagnostic(Diagnostic::Level Level,
145 const DiagnosticInfo &Info);
146};
147
148/// \brief RAII object that optionally captures diagnostics, if
149/// there is no diagnostic client to capture them already.
150class CaptureDroppedDiagnostics {
151 Diagnostic &Diags;
152 StoredDiagnosticClient Client;
153 DiagnosticClient *PreviousClient;
154
155public:
156 CaptureDroppedDiagnostics(bool RequestCapture, Diagnostic &Diags,
157 llvm::SmallVectorImpl<StoredDiagnostic> &StoredDiags)
158 : Diags(Diags), Client(StoredDiags), PreviousClient(Diags.getClient())
159 {
160 if (RequestCapture || Diags.getClient() == 0)
161 Diags.setClient(&Client);
162 }
163
164 ~CaptureDroppedDiagnostics() {
165 Diags.setClient(PreviousClient);
166 }
167};
168
Argyrios Kyrtzidis0853a022009-06-20 08:08:23 +0000169} // anonymous namespace
170
Douglas Gregora88084b2010-02-18 18:08:43 +0000171void StoredDiagnosticClient::HandleDiagnostic(Diagnostic::Level Level,
172 const DiagnosticInfo &Info) {
173 StoredDiags.push_back(StoredDiagnostic(Level, Info));
174}
175
Steve Naroff77accc12009-09-03 18:19:54 +0000176const std::string &ASTUnit::getOriginalSourceFileName() {
Daniel Dunbar68d40e22009-12-02 08:44:16 +0000177 return OriginalSourceFile;
Steve Naroff77accc12009-09-03 18:19:54 +0000178}
Argyrios Kyrtzidis0853a022009-06-20 08:08:23 +0000179
Steve Naroffe19944c2009-10-15 22:23:48 +0000180const std::string &ASTUnit::getPCHFileName() {
Daniel Dunbarc7822db2009-12-02 21:47:43 +0000181 assert(isMainFileAST() && "Not an ASTUnit from a PCH file!");
Benjamin Kramer7297c182010-01-30 16:23:25 +0000182 return static_cast<PCHReader *>(Ctx->getExternalSource())->getFileName();
Steve Naroffe19944c2009-10-15 22:23:48 +0000183}
184
Argyrios Kyrtzidis0853a022009-06-20 08:08:23 +0000185ASTUnit *ASTUnit::LoadFromPCHFile(const std::string &Filename,
Douglas Gregor28019772010-04-05 23:52:57 +0000186 llvm::IntrusiveRefCntPtr<Diagnostic> Diags,
Ted Kremenek5cf48762009-10-17 00:34:24 +0000187 bool OnlyLocalDecls,
Douglas Gregor4db64a42010-01-23 00:14:00 +0000188 RemappedFile *RemappedFiles,
Douglas Gregora88084b2010-02-18 18:08:43 +0000189 unsigned NumRemappedFiles,
190 bool CaptureDiagnostics) {
Douglas Gregor3687e9d2010-04-05 21:10:19 +0000191 llvm::OwningPtr<ASTUnit> AST(new ASTUnit(true));
192
Douglas Gregor28019772010-04-05 23:52:57 +0000193 if (!Diags.getPtr()) {
Douglas Gregor3687e9d2010-04-05 21:10:19 +0000194 // No diagnostics engine was provided, so create our own diagnostics object
195 // with the default options.
196 DiagnosticOptions DiagOpts;
Douglas Gregor28019772010-04-05 23:52:57 +0000197 Diags = CompilerInstance::createDiagnostics(DiagOpts, 0, 0);
Douglas Gregor3687e9d2010-04-05 21:10:19 +0000198 }
Douglas Gregorabc563f2010-07-19 21:46:24 +0000199
200 AST->CaptureDiagnostics = CaptureDiagnostics;
Douglas Gregor7d1d49d2009-10-16 20:01:17 +0000201 AST->OnlyLocalDecls = OnlyLocalDecls;
Douglas Gregor28019772010-04-05 23:52:57 +0000202 AST->Diagnostics = Diags;
Douglas Gregor3687e9d2010-04-05 21:10:19 +0000203 AST->FileMgr.reset(new FileManager);
204 AST->SourceMgr.reset(new SourceManager(AST->getDiagnostics()));
Steve Naroff36c44642009-10-19 14:34:22 +0000205 AST->HeaderInfo.reset(new HeaderSearch(AST->getFileManager()));
Argyrios Kyrtzidis0853a022009-06-20 08:08:23 +0000206
Douglas Gregora88084b2010-02-18 18:08:43 +0000207 // If requested, capture diagnostics in the ASTUnit.
Douglas Gregor3687e9d2010-04-05 21:10:19 +0000208 CaptureDroppedDiagnostics Capture(CaptureDiagnostics, AST->getDiagnostics(),
Douglas Gregor405634b2010-04-05 18:10:21 +0000209 AST->StoredDiagnostics);
Douglas Gregora88084b2010-02-18 18:08:43 +0000210
Douglas Gregor4db64a42010-01-23 00:14:00 +0000211 for (unsigned I = 0; I != NumRemappedFiles; ++I) {
212 // Create the file entry for the file that we're mapping from.
213 const FileEntry *FromFile
214 = AST->getFileManager().getVirtualFile(RemappedFiles[I].first,
215 RemappedFiles[I].second->getBufferSize(),
216 0);
217 if (!FromFile) {
Douglas Gregor3687e9d2010-04-05 21:10:19 +0000218 AST->getDiagnostics().Report(diag::err_fe_remap_missing_from_file)
Douglas Gregor4db64a42010-01-23 00:14:00 +0000219 << RemappedFiles[I].first;
Douglas Gregorc8dfe5e2010-02-27 01:32:48 +0000220 delete RemappedFiles[I].second;
Douglas Gregor4db64a42010-01-23 00:14:00 +0000221 continue;
222 }
223
224 // Override the contents of the "from" file with the contents of
225 // the "to" file.
226 AST->getSourceManager().overrideFileContents(FromFile,
227 RemappedFiles[I].second);
228 }
229
Argyrios Kyrtzidis0853a022009-06-20 08:08:23 +0000230 // Gather Info for preprocessor construction later on.
Mike Stump1eb44332009-09-09 15:08:12 +0000231
Argyrios Kyrtzidis0853a022009-06-20 08:08:23 +0000232 LangOptions LangInfo;
233 HeaderSearch &HeaderInfo = *AST->HeaderInfo.get();
234 std::string TargetTriple;
235 std::string Predefines;
236 unsigned Counter;
237
Daniel Dunbarbce6f622009-09-03 05:59:50 +0000238 llvm::OwningPtr<PCHReader> Reader;
Argyrios Kyrtzidis0853a022009-06-20 08:08:23 +0000239 llvm::OwningPtr<ExternalASTSource> Source;
240
Ted Kremenekfc062212009-10-19 21:44:57 +0000241 Reader.reset(new PCHReader(AST->getSourceManager(), AST->getFileManager(),
Douglas Gregor3687e9d2010-04-05 21:10:19 +0000242 AST->getDiagnostics()));
Daniel Dunbarcc318932009-09-03 05:59:35 +0000243 Reader->setListener(new PCHInfoCollector(LangInfo, HeaderInfo, TargetTriple,
244 Predefines, Counter));
245
246 switch (Reader->ReadPCH(Filename)) {
Argyrios Kyrtzidis0853a022009-06-20 08:08:23 +0000247 case PCHReader::Success:
248 break;
Mike Stump1eb44332009-09-09 15:08:12 +0000249
Argyrios Kyrtzidis0853a022009-06-20 08:08:23 +0000250 case PCHReader::Failure:
Argyrios Kyrtzidis106c9982009-06-25 18:22:30 +0000251 case PCHReader::IgnorePCH:
Douglas Gregor3687e9d2010-04-05 21:10:19 +0000252 AST->getDiagnostics().Report(diag::err_fe_unable_to_load_pch);
Argyrios Kyrtzidis0853a022009-06-20 08:08:23 +0000253 return NULL;
Argyrios Kyrtzidis0853a022009-06-20 08:08:23 +0000254 }
Mike Stump1eb44332009-09-09 15:08:12 +0000255
Daniel Dunbar68d40e22009-12-02 08:44:16 +0000256 AST->OriginalSourceFile = Reader->getOriginalSourceFile();
257
Argyrios Kyrtzidis0853a022009-06-20 08:08:23 +0000258 // PCH loaded successfully. Now create the preprocessor.
Mike Stump1eb44332009-09-09 15:08:12 +0000259
Argyrios Kyrtzidis0853a022009-06-20 08:08:23 +0000260 // Get information about the target being compiled for.
Daniel Dunbard58c03f2009-11-15 06:48:46 +0000261 //
262 // FIXME: This is broken, we should store the TargetOptions in the PCH.
263 TargetOptions TargetOpts;
264 TargetOpts.ABI = "";
Charles Davis98b7c5c2010-06-11 01:06:47 +0000265 TargetOpts.CXXABI = "itanium";
Daniel Dunbard58c03f2009-11-15 06:48:46 +0000266 TargetOpts.CPU = "";
267 TargetOpts.Features.clear();
268 TargetOpts.Triple = TargetTriple;
Douglas Gregor3687e9d2010-04-05 21:10:19 +0000269 AST->Target.reset(TargetInfo::CreateTargetInfo(AST->getDiagnostics(),
270 TargetOpts));
271 AST->PP.reset(new Preprocessor(AST->getDiagnostics(), LangInfo,
272 *AST->Target.get(),
Daniel Dunbar31b87d82009-09-21 03:03:39 +0000273 AST->getSourceManager(), HeaderInfo));
Argyrios Kyrtzidis0853a022009-06-20 08:08:23 +0000274 Preprocessor &PP = *AST->PP.get();
275
Daniel Dunbard5b61262009-09-21 03:03:47 +0000276 PP.setPredefines(Reader->getSuggestedPredefines());
Argyrios Kyrtzidis0853a022009-06-20 08:08:23 +0000277 PP.setCounterValue(Counter);
Daniel Dunbarcc318932009-09-03 05:59:35 +0000278 Reader->setPreprocessor(PP);
Mike Stump1eb44332009-09-09 15:08:12 +0000279
Argyrios Kyrtzidis0853a022009-06-20 08:08:23 +0000280 // Create and initialize the ASTContext.
281
282 AST->Ctx.reset(new ASTContext(LangInfo,
Daniel Dunbar31b87d82009-09-21 03:03:39 +0000283 AST->getSourceManager(),
Argyrios Kyrtzidis0853a022009-06-20 08:08:23 +0000284 *AST->Target.get(),
285 PP.getIdentifierTable(),
286 PP.getSelectorTable(),
287 PP.getBuiltinInfo(),
Argyrios Kyrtzidis0853a022009-06-20 08:08:23 +0000288 /* size_reserve = */0));
289 ASTContext &Context = *AST->Ctx.get();
Mike Stump1eb44332009-09-09 15:08:12 +0000290
Daniel Dunbarcc318932009-09-03 05:59:35 +0000291 Reader->InitializeContext(Context);
Mike Stump1eb44332009-09-09 15:08:12 +0000292
Argyrios Kyrtzidis0853a022009-06-20 08:08:23 +0000293 // Attach the PCH reader to the AST context as an external AST
294 // source, so that declarations will be deserialized from the
295 // PCH file as needed.
Daniel Dunbarcc318932009-09-03 05:59:35 +0000296 Source.reset(Reader.take());
Argyrios Kyrtzidis0853a022009-06-20 08:08:23 +0000297 Context.setExternalSource(Source);
298
Mike Stump1eb44332009-09-09 15:08:12 +0000299 return AST.take();
Argyrios Kyrtzidis0853a022009-06-20 08:08:23 +0000300}
Daniel Dunbar521bf9c2009-12-01 09:51:01 +0000301
302namespace {
303
Daniel Dunbarf772d1e2009-12-04 08:17:33 +0000304class TopLevelDeclTrackerConsumer : public ASTConsumer {
305 ASTUnit &Unit;
306
307public:
308 TopLevelDeclTrackerConsumer(ASTUnit &_Unit) : Unit(_Unit) {}
309
310 void HandleTopLevelDecl(DeclGroupRef D) {
Ted Kremenekda5a4282010-05-03 20:16:35 +0000311 for (DeclGroupRef::iterator it = D.begin(), ie = D.end(); it != ie; ++it) {
312 Decl *D = *it;
313 // FIXME: Currently ObjC method declarations are incorrectly being
314 // reported as top-level declarations, even though their DeclContext
315 // is the containing ObjC @interface/@implementation. This is a
316 // fundamental problem in the parser right now.
317 if (isa<ObjCMethodDecl>(D))
318 continue;
Douglas Gregoreb8837b2010-08-03 19:06:41 +0000319 Unit.addTopLevelDecl(D);
Ted Kremenekda5a4282010-05-03 20:16:35 +0000320 }
Daniel Dunbarf772d1e2009-12-04 08:17:33 +0000321 }
322};
323
324class TopLevelDeclTrackerAction : public ASTFrontendAction {
325public:
326 ASTUnit &Unit;
327
Daniel Dunbar521bf9c2009-12-01 09:51:01 +0000328 virtual ASTConsumer *CreateASTConsumer(CompilerInstance &CI,
329 llvm::StringRef InFile) {
Daniel Dunbarf772d1e2009-12-04 08:17:33 +0000330 return new TopLevelDeclTrackerConsumer(Unit);
Daniel Dunbar521bf9c2009-12-01 09:51:01 +0000331 }
332
333public:
Daniel Dunbarf772d1e2009-12-04 08:17:33 +0000334 TopLevelDeclTrackerAction(ASTUnit &_Unit) : Unit(_Unit) {}
335
Daniel Dunbar521bf9c2009-12-01 09:51:01 +0000336 virtual bool hasCodeCompletionSupport() const { return false; }
337};
338
Douglas Gregor1d715ac2010-08-03 08:14:03 +0000339class PrecompilePreambleConsumer : public PCHGenerator {
340 ASTUnit &Unit;
Douglas Gregoreb8837b2010-08-03 19:06:41 +0000341 std::vector<Decl *> TopLevelDecls;
Douglas Gregor1d715ac2010-08-03 08:14:03 +0000342
343public:
344 PrecompilePreambleConsumer(ASTUnit &Unit,
345 const Preprocessor &PP, bool Chaining,
346 const char *isysroot, llvm::raw_ostream *Out)
347 : PCHGenerator(PP, Chaining, isysroot, Out), Unit(Unit) { }
348
Douglas Gregoreb8837b2010-08-03 19:06:41 +0000349 virtual void HandleTopLevelDecl(DeclGroupRef D) {
Douglas Gregor1d715ac2010-08-03 08:14:03 +0000350 for (DeclGroupRef::iterator it = D.begin(), ie = D.end(); it != ie; ++it) {
351 Decl *D = *it;
352 // FIXME: Currently ObjC method declarations are incorrectly being
353 // reported as top-level declarations, even though their DeclContext
354 // is the containing ObjC @interface/@implementation. This is a
355 // fundamental problem in the parser right now.
356 if (isa<ObjCMethodDecl>(D))
357 continue;
Douglas Gregoreb8837b2010-08-03 19:06:41 +0000358 TopLevelDecls.push_back(D);
359 }
360 }
361
362 virtual void HandleTranslationUnit(ASTContext &Ctx) {
363 PCHGenerator::HandleTranslationUnit(Ctx);
364 if (!Unit.getDiagnostics().hasErrorOccurred()) {
365 // Translate the top-level declarations we captured during
366 // parsing into declaration IDs in the precompiled
367 // preamble. This will allow us to deserialize those top-level
368 // declarations when requested.
369 for (unsigned I = 0, N = TopLevelDecls.size(); I != N; ++I)
370 Unit.addTopLevelDeclFromPreamble(
371 getWriter().getDeclID(TopLevelDecls[I]));
Douglas Gregor1d715ac2010-08-03 08:14:03 +0000372 }
373 }
374};
375
376class PrecompilePreambleAction : public ASTFrontendAction {
377 ASTUnit &Unit;
378
379public:
380 explicit PrecompilePreambleAction(ASTUnit &Unit) : Unit(Unit) {}
381
382 virtual ASTConsumer *CreateASTConsumer(CompilerInstance &CI,
383 llvm::StringRef InFile) {
384 std::string Sysroot;
385 llvm::raw_ostream *OS = 0;
386 bool Chaining;
387 if (GeneratePCHAction::ComputeASTConsumerArguments(CI, InFile, Sysroot,
388 OS, Chaining))
389 return 0;
390
391 const char *isysroot = CI.getFrontendOpts().RelocatablePCH ?
392 Sysroot.c_str() : 0;
393 return new PrecompilePreambleConsumer(Unit, CI.getPreprocessor(), Chaining,
394 isysroot, OS);
395 }
396
397 virtual bool hasCodeCompletionSupport() const { return false; }
398 virtual bool hasASTFileSupport() const { return false; }
399};
400
Daniel Dunbar521bf9c2009-12-01 09:51:01 +0000401}
402
Douglas Gregorabc563f2010-07-19 21:46:24 +0000403/// Parse the source file into a translation unit using the given compiler
404/// invocation, replacing the current translation unit.
405///
406/// \returns True if a failure occurred that causes the ASTUnit not to
407/// contain any translation-unit information, false otherwise.
Douglas Gregor754f3492010-07-24 00:38:13 +0000408bool ASTUnit::Parse(llvm::MemoryBuffer *OverrideMainBuffer) {
Douglas Gregor28233422010-07-27 14:52:07 +0000409 delete SavedMainFileBuffer;
410 SavedMainFileBuffer = 0;
411
Douglas Gregorabc563f2010-07-19 21:46:24 +0000412 if (!Invocation.get())
413 return true;
414
Daniel Dunbar521bf9c2009-12-01 09:51:01 +0000415 // Create the compiler instance to use for building the AST.
Daniel Dunbarcb6dda12009-12-02 08:43:56 +0000416 CompilerInstance Clang;
Douglas Gregorabc563f2010-07-19 21:46:24 +0000417 Clang.setInvocation(Invocation.take());
418 OriginalSourceFile = Clang.getFrontendOpts().Inputs[0].second;
419
Douglas Gregor1abc6bc2010-08-04 16:47:14 +0000420 // Set up diagnostics, capturing any diagnostics that would
421 // otherwise be dropped.
Douglas Gregorabc563f2010-07-19 21:46:24 +0000422 Clang.setDiagnostics(&getDiagnostics());
Douglas Gregor1abc6bc2010-08-04 16:47:14 +0000423 CaptureDroppedDiagnostics Capture(CaptureDiagnostics,
424 getDiagnostics(),
425 StoredDiagnostics);
Douglas Gregorabc563f2010-07-19 21:46:24 +0000426 Clang.setDiagnosticClient(getDiagnostics().getClient());
Douglas Gregor3687e9d2010-04-05 21:10:19 +0000427
Daniel Dunbar521bf9c2009-12-01 09:51:01 +0000428 // Create the target instance.
429 Clang.setTarget(TargetInfo::CreateTargetInfo(Clang.getDiagnostics(),
430 Clang.getTargetOpts()));
Douglas Gregora88084b2010-02-18 18:08:43 +0000431 if (!Clang.hasTarget()) {
Douglas Gregora88084b2010-02-18 18:08:43 +0000432 Clang.takeDiagnosticClient();
Douglas Gregorabc563f2010-07-19 21:46:24 +0000433 return true;
Douglas Gregora88084b2010-02-18 18:08:43 +0000434 }
Douglas Gregorabc563f2010-07-19 21:46:24 +0000435
Daniel Dunbar521bf9c2009-12-01 09:51:01 +0000436 // Inform the target of the language options.
437 //
438 // FIXME: We shouldn't need to do this, the target should be immutable once
439 // created. This complexity should be lifted elsewhere.
440 Clang.getTarget().setForcedLangOptions(Clang.getLangOpts());
Douglas Gregorabc563f2010-07-19 21:46:24 +0000441
Daniel Dunbar521bf9c2009-12-01 09:51:01 +0000442 assert(Clang.getFrontendOpts().Inputs.size() == 1 &&
443 "Invocation must have exactly one source file!");
Daniel Dunbarc34ce3f2010-06-07 23:22:09 +0000444 assert(Clang.getFrontendOpts().Inputs[0].first != IK_AST &&
Daniel Dunbar521bf9c2009-12-01 09:51:01 +0000445 "FIXME: AST inputs not yet supported here!");
Daniel Dunbarfaddc3e2010-06-07 23:26:47 +0000446 assert(Clang.getFrontendOpts().Inputs[0].first != IK_LLVM_IR &&
447 "IR inputs not support here!");
Daniel Dunbar521bf9c2009-12-01 09:51:01 +0000448
Douglas Gregorabc563f2010-07-19 21:46:24 +0000449 // Configure the various subsystems.
450 // FIXME: Should we retain the previous file manager?
451 FileMgr.reset(new FileManager);
452 SourceMgr.reset(new SourceManager(getDiagnostics()));
453 Ctx.reset();
454 PP.reset();
455
456 // Clear out old caches and data.
457 TopLevelDecls.clear();
Douglas Gregorabc563f2010-07-19 21:46:24 +0000458 CleanTemporaryFiles();
459 PreprocessedEntitiesByFile.clear();
Douglas Gregorc0659ec2010-08-02 20:51:39 +0000460
461 if (!OverrideMainBuffer)
462 StoredDiagnostics.clear();
Douglas Gregor1abc6bc2010-08-04 16:47:14 +0000463
Daniel Dunbar521bf9c2009-12-01 09:51:01 +0000464 // Create a file manager object to provide access to and cache the filesystem.
Douglas Gregorabc563f2010-07-19 21:46:24 +0000465 Clang.setFileManager(&getFileManager());
466
Daniel Dunbar521bf9c2009-12-01 09:51:01 +0000467 // Create the source manager.
Douglas Gregorabc563f2010-07-19 21:46:24 +0000468 Clang.setSourceManager(&getSourceManager());
469
Douglas Gregorf4f6c9d2010-07-26 21:36:20 +0000470 // If the main file has been overridden due to the use of a preamble,
471 // make that override happen and introduce the preamble.
472 PreprocessorOptions &PreprocessorOpts = Clang.getPreprocessorOpts();
Douglas Gregor1abc6bc2010-08-04 16:47:14 +0000473 std::string PriorImplicitPCHInclude;
Douglas Gregorf4f6c9d2010-07-26 21:36:20 +0000474 if (OverrideMainBuffer) {
475 PreprocessorOpts.addRemappedFile(OriginalSourceFile, OverrideMainBuffer);
476 PreprocessorOpts.PrecompiledPreambleBytes.first = Preamble.size();
477 PreprocessorOpts.PrecompiledPreambleBytes.second
478 = PreambleEndsAtStartOfLine;
Douglas Gregor1abc6bc2010-08-04 16:47:14 +0000479 PriorImplicitPCHInclude = PreprocessorOpts.ImplicitPCHInclude;
Douglas Gregor385103b2010-07-30 20:58:08 +0000480 PreprocessorOpts.ImplicitPCHInclude = PreambleFile;
Douglas Gregorfae3b2f2010-07-27 00:27:13 +0000481 PreprocessorOpts.DisablePCHValidation = true;
Douglas Gregor28233422010-07-27 14:52:07 +0000482
483 // Keep track of the override buffer;
484 SavedMainFileBuffer = OverrideMainBuffer;
Douglas Gregorc0659ec2010-08-02 20:51:39 +0000485
486 // The stored diagnostic has the old source manager in it; update
487 // the locations to refer into the new source manager. Since we've
488 // been careful to make sure that the source manager's state
489 // before and after are identical, so that we can reuse the source
490 // location itself.
491 for (unsigned I = 0, N = StoredDiagnostics.size(); I != N; ++I) {
492 FullSourceLoc Loc(StoredDiagnostics[I].getLocation(),
493 getSourceManager());
494 StoredDiagnostics[I].setLocation(Loc);
495 }
Douglas Gregorf4f6c9d2010-07-26 21:36:20 +0000496 }
497
Douglas Gregorabc563f2010-07-19 21:46:24 +0000498 llvm::OwningPtr<TopLevelDeclTrackerAction> Act;
499 Act.reset(new TopLevelDeclTrackerAction(*this));
Daniel Dunbarf772d1e2009-12-04 08:17:33 +0000500 if (!Act->BeginSourceFile(Clang, Clang.getFrontendOpts().Inputs[0].second,
Daniel Dunbard3598a62010-06-07 23:23:06 +0000501 Clang.getFrontendOpts().Inputs[0].first))
Daniel Dunbar521bf9c2009-12-01 09:51:01 +0000502 goto error;
Douglas Gregorabc563f2010-07-19 21:46:24 +0000503
Daniel Dunbarf772d1e2009-12-04 08:17:33 +0000504 Act->Execute();
Douglas Gregorabc563f2010-07-19 21:46:24 +0000505
Daniel Dunbar64a32ba2009-12-01 21:57:33 +0000506 // Steal the created target, context, and preprocessor, and take back the
507 // source and file managers.
Douglas Gregorabc563f2010-07-19 21:46:24 +0000508 Ctx.reset(Clang.takeASTContext());
509 PP.reset(Clang.takePreprocessor());
Daniel Dunbar521bf9c2009-12-01 09:51:01 +0000510 Clang.takeSourceManager();
511 Clang.takeFileManager();
Douglas Gregorabc563f2010-07-19 21:46:24 +0000512 Target.reset(Clang.takeTarget());
513
Daniel Dunbarf772d1e2009-12-04 08:17:33 +0000514 Act->EndSourceFile();
Douglas Gregorf4f6c9d2010-07-26 21:36:20 +0000515
516 // Remove the overridden buffer we used for the preamble.
Douglas Gregor1abc6bc2010-08-04 16:47:14 +0000517 if (OverrideMainBuffer) {
Douglas Gregorf4f6c9d2010-07-26 21:36:20 +0000518 PreprocessorOpts.eraseRemappedFile(
519 PreprocessorOpts.remapped_file_buffer_end() - 1);
Douglas Gregor1abc6bc2010-08-04 16:47:14 +0000520 PreprocessorOpts.ImplicitPCHInclude = PriorImplicitPCHInclude;
521 }
522
Daniel Dunbar521bf9c2009-12-01 09:51:01 +0000523 Clang.takeDiagnosticClient();
Douglas Gregorabc563f2010-07-19 21:46:24 +0000524
525 Invocation.reset(Clang.takeInvocation());
526 return false;
527
Daniel Dunbar521bf9c2009-12-01 09:51:01 +0000528error:
Douglas Gregorf4f6c9d2010-07-26 21:36:20 +0000529 // Remove the overridden buffer we used for the preamble.
Douglas Gregorfae3b2f2010-07-27 00:27:13 +0000530 if (OverrideMainBuffer) {
Douglas Gregorf4f6c9d2010-07-26 21:36:20 +0000531 PreprocessorOpts.eraseRemappedFile(
532 PreprocessorOpts.remapped_file_buffer_end() - 1);
Douglas Gregorfae3b2f2010-07-27 00:27:13 +0000533 PreprocessorOpts.DisablePCHValidation = true;
Douglas Gregor1abc6bc2010-08-04 16:47:14 +0000534 PreprocessorOpts.ImplicitPCHInclude = PriorImplicitPCHInclude;
Douglas Gregorfae3b2f2010-07-27 00:27:13 +0000535 }
Douglas Gregorf4f6c9d2010-07-26 21:36:20 +0000536
Daniel Dunbar521bf9c2009-12-01 09:51:01 +0000537 Clang.takeSourceManager();
538 Clang.takeFileManager();
539 Clang.takeDiagnosticClient();
Douglas Gregorabc563f2010-07-19 21:46:24 +0000540 Invocation.reset(Clang.takeInvocation());
541 return true;
542}
543
Douglas Gregor44c181a2010-07-23 00:33:23 +0000544/// \brief Simple function to retrieve a path for a preamble precompiled header.
545static std::string GetPreamblePCHPath() {
546 // FIXME: This is lame; sys::Path should provide this function (in particular,
547 // it should know how to find the temporary files dir).
548 // FIXME: This is really lame. I copied this code from the Driver!
549 std::string Error;
550 const char *TmpDir = ::getenv("TMPDIR");
551 if (!TmpDir)
552 TmpDir = ::getenv("TEMP");
553 if (!TmpDir)
554 TmpDir = ::getenv("TMP");
555 if (!TmpDir)
556 TmpDir = "/tmp";
557 llvm::sys::Path P(TmpDir);
558 P.appendComponent("preamble");
559 if (P.createTemporaryFileOnDisk())
560 return std::string();
561
562 P.appendSuffix("pch");
563 return P.str();
564}
565
Douglas Gregorf4f6c9d2010-07-26 21:36:20 +0000566/// \brief Compute the preamble for the main file, providing the source buffer
567/// that corresponds to the main file along with a pair (bytes, start-of-line)
568/// that describes the preamble.
569std::pair<llvm::MemoryBuffer *, std::pair<unsigned, bool> >
Douglas Gregor175c4a92010-07-23 23:58:40 +0000570ASTUnit::ComputePreamble(CompilerInvocation &Invocation, bool &CreatedBuffer) {
571 FrontendOptions &FrontendOpts = Invocation.getFrontendOpts();
Douglas Gregor44c181a2010-07-23 00:33:23 +0000572 PreprocessorOptions &PreprocessorOpts
Douglas Gregor175c4a92010-07-23 23:58:40 +0000573 = Invocation.getPreprocessorOpts();
574 CreatedBuffer = false;
575
Douglas Gregor44c181a2010-07-23 00:33:23 +0000576 // Try to determine if the main file has been remapped, either from the
577 // command line (to another file) or directly through the compiler invocation
578 // (to a memory buffer).
Douglas Gregor175c4a92010-07-23 23:58:40 +0000579 llvm::MemoryBuffer *Buffer = 0;
Douglas Gregor44c181a2010-07-23 00:33:23 +0000580 llvm::sys::PathWithStatus MainFilePath(FrontendOpts.Inputs[0].second);
581 if (const llvm::sys::FileStatus *MainFileStatus = MainFilePath.getFileStatus()) {
582 // Check whether there is a file-file remapping of the main file
583 for (PreprocessorOptions::remapped_file_iterator
Douglas Gregor175c4a92010-07-23 23:58:40 +0000584 M = PreprocessorOpts.remapped_file_begin(),
585 E = PreprocessorOpts.remapped_file_end();
Douglas Gregor44c181a2010-07-23 00:33:23 +0000586 M != E;
587 ++M) {
588 llvm::sys::PathWithStatus MPath(M->first);
589 if (const llvm::sys::FileStatus *MStatus = MPath.getFileStatus()) {
590 if (MainFileStatus->uniqueID == MStatus->uniqueID) {
591 // We found a remapping. Try to load the resulting, remapped source.
Douglas Gregor175c4a92010-07-23 23:58:40 +0000592 if (CreatedBuffer) {
Douglas Gregor44c181a2010-07-23 00:33:23 +0000593 delete Buffer;
Douglas Gregor175c4a92010-07-23 23:58:40 +0000594 CreatedBuffer = false;
595 }
596
Douglas Gregor44c181a2010-07-23 00:33:23 +0000597 Buffer = llvm::MemoryBuffer::getFile(M->second);
598 if (!Buffer)
Douglas Gregorf4f6c9d2010-07-26 21:36:20 +0000599 return std::make_pair((llvm::MemoryBuffer*)0,
600 std::make_pair(0, true));
Douglas Gregor175c4a92010-07-23 23:58:40 +0000601 CreatedBuffer = true;
Douglas Gregor44c181a2010-07-23 00:33:23 +0000602
Douglas Gregor175c4a92010-07-23 23:58:40 +0000603 // Remove this remapping. We've captured the buffer already.
Douglas Gregor44c181a2010-07-23 00:33:23 +0000604 M = PreprocessorOpts.eraseRemappedFile(M);
605 E = PreprocessorOpts.remapped_file_end();
606 }
607 }
608 }
609
610 // Check whether there is a file-buffer remapping. It supercedes the
611 // file-file remapping.
612 for (PreprocessorOptions::remapped_file_buffer_iterator
613 M = PreprocessorOpts.remapped_file_buffer_begin(),
614 E = PreprocessorOpts.remapped_file_buffer_end();
615 M != E;
616 ++M) {
617 llvm::sys::PathWithStatus MPath(M->first);
618 if (const llvm::sys::FileStatus *MStatus = MPath.getFileStatus()) {
619 if (MainFileStatus->uniqueID == MStatus->uniqueID) {
620 // We found a remapping.
Douglas Gregor175c4a92010-07-23 23:58:40 +0000621 if (CreatedBuffer) {
Douglas Gregor44c181a2010-07-23 00:33:23 +0000622 delete Buffer;
Douglas Gregor175c4a92010-07-23 23:58:40 +0000623 CreatedBuffer = false;
624 }
Douglas Gregor44c181a2010-07-23 00:33:23 +0000625
Douglas Gregor175c4a92010-07-23 23:58:40 +0000626 Buffer = const_cast<llvm::MemoryBuffer *>(M->second);
627
628 // Remove this remapping. We've captured the buffer already.
Douglas Gregor44c181a2010-07-23 00:33:23 +0000629 M = PreprocessorOpts.eraseRemappedFile(M);
630 E = PreprocessorOpts.remapped_file_buffer_end();
631 }
632 }
Douglas Gregor175c4a92010-07-23 23:58:40 +0000633 }
Douglas Gregor44c181a2010-07-23 00:33:23 +0000634 }
635
636 // If the main source file was not remapped, load it now.
637 if (!Buffer) {
638 Buffer = llvm::MemoryBuffer::getFile(FrontendOpts.Inputs[0].second);
639 if (!Buffer)
Douglas Gregorf4f6c9d2010-07-26 21:36:20 +0000640 return std::make_pair((llvm::MemoryBuffer*)0, std::make_pair(0, true));
Douglas Gregor175c4a92010-07-23 23:58:40 +0000641
642 CreatedBuffer = true;
Douglas Gregor44c181a2010-07-23 00:33:23 +0000643 }
644
Douglas Gregor175c4a92010-07-23 23:58:40 +0000645 return std::make_pair(Buffer, Lexer::ComputePreamble(Buffer));
646}
647
Douglas Gregor754f3492010-07-24 00:38:13 +0000648static llvm::MemoryBuffer *CreatePaddedMainFileBuffer(llvm::MemoryBuffer *Old,
649 bool DeleteOld,
650 unsigned NewSize,
651 llvm::StringRef NewName) {
652 llvm::MemoryBuffer *Result
653 = llvm::MemoryBuffer::getNewUninitMemBuffer(NewSize, NewName);
654 memcpy(const_cast<char*>(Result->getBufferStart()),
655 Old->getBufferStart(), Old->getBufferSize());
656 memset(const_cast<char*>(Result->getBufferStart()) + Old->getBufferSize(),
Douglas Gregorf4f6c9d2010-07-26 21:36:20 +0000657 ' ', NewSize - Old->getBufferSize() - 1);
658 const_cast<char*>(Result->getBufferEnd())[-1] = '\n';
Douglas Gregor754f3492010-07-24 00:38:13 +0000659
660 if (DeleteOld)
661 delete Old;
662
663 return Result;
664}
665
Douglas Gregor175c4a92010-07-23 23:58:40 +0000666/// \brief Attempt to build or re-use a precompiled preamble when (re-)parsing
667/// the source file.
668///
669/// This routine will compute the preamble of the main source file. If a
670/// non-trivial preamble is found, it will precompile that preamble into a
671/// precompiled header so that the precompiled preamble can be used to reduce
672/// reparsing time. If a precompiled preamble has already been constructed,
673/// this routine will determine if it is still valid and, if so, avoid
674/// rebuilding the precompiled preamble.
675///
Douglas Gregor754f3492010-07-24 00:38:13 +0000676/// \returns If the precompiled preamble can be used, returns a newly-allocated
677/// buffer that should be used in place of the main file when doing so.
678/// Otherwise, returns a NULL pointer.
679llvm::MemoryBuffer *ASTUnit::BuildPrecompiledPreamble() {
Douglas Gregor175c4a92010-07-23 23:58:40 +0000680 CompilerInvocation PreambleInvocation(*Invocation);
681 FrontendOptions &FrontendOpts = PreambleInvocation.getFrontendOpts();
682 PreprocessorOptions &PreprocessorOpts
683 = PreambleInvocation.getPreprocessorOpts();
684
685 bool CreatedPreambleBuffer = false;
Douglas Gregorf4f6c9d2010-07-26 21:36:20 +0000686 std::pair<llvm::MemoryBuffer *, std::pair<unsigned, bool> > NewPreamble
Douglas Gregor175c4a92010-07-23 23:58:40 +0000687 = ComputePreamble(PreambleInvocation, CreatedPreambleBuffer);
688
Douglas Gregorf4f6c9d2010-07-26 21:36:20 +0000689 if (!NewPreamble.second.first) {
Douglas Gregor175c4a92010-07-23 23:58:40 +0000690 // We couldn't find a preamble in the main source. Clear out the current
691 // preamble, if we have one. It's obviously no good any more.
692 Preamble.clear();
693 if (!PreambleFile.empty()) {
Douglas Gregor385103b2010-07-30 20:58:08 +0000694 llvm::sys::Path(PreambleFile).eraseFromDisk();
Douglas Gregor175c4a92010-07-23 23:58:40 +0000695 PreambleFile.clear();
696 }
697 if (CreatedPreambleBuffer)
698 delete NewPreamble.first;
Douglas Gregoreababfb2010-08-04 05:53:38 +0000699
700 // The next time we actually see a preamble, precompile it.
701 PreambleRebuildCounter = 1;
Douglas Gregor754f3492010-07-24 00:38:13 +0000702 return 0;
Douglas Gregor175c4a92010-07-23 23:58:40 +0000703 }
704
705 if (!Preamble.empty()) {
706 // We've previously computed a preamble. Check whether we have the same
707 // preamble now that we did before, and that there's enough space in
708 // the main-file buffer within the precompiled preamble to fit the
709 // new main file.
Douglas Gregorf4f6c9d2010-07-26 21:36:20 +0000710 if (Preamble.size() == NewPreamble.second.first &&
711 PreambleEndsAtStartOfLine == NewPreamble.second.second &&
Douglas Gregor592508e2010-07-24 00:42:07 +0000712 NewPreamble.first->getBufferSize() < PreambleReservedSize-2 &&
Douglas Gregor175c4a92010-07-23 23:58:40 +0000713 memcmp(&Preamble[0], NewPreamble.first->getBufferStart(),
Douglas Gregorf4f6c9d2010-07-26 21:36:20 +0000714 NewPreamble.second.first) == 0) {
Douglas Gregor175c4a92010-07-23 23:58:40 +0000715 // The preamble has not changed. We may be able to re-use the precompiled
716 // preamble.
Douglas Gregorc0659ec2010-08-02 20:51:39 +0000717
Douglas Gregorcc5888d2010-07-31 00:40:00 +0000718 // Check that none of the files used by the preamble have changed.
719 bool AnyFileChanged = false;
720
721 // First, make a record of those files that have been overridden via
722 // remapping or unsaved_files.
723 llvm::StringMap<std::pair<off_t, time_t> > OverriddenFiles;
724 for (PreprocessorOptions::remapped_file_iterator
725 R = PreprocessorOpts.remapped_file_begin(),
726 REnd = PreprocessorOpts.remapped_file_end();
727 !AnyFileChanged && R != REnd;
728 ++R) {
729 struct stat StatBuf;
730 if (stat(R->second.c_str(), &StatBuf)) {
731 // If we can't stat the file we're remapping to, assume that something
732 // horrible happened.
733 AnyFileChanged = true;
734 break;
735 }
Douglas Gregor754f3492010-07-24 00:38:13 +0000736
Douglas Gregorcc5888d2010-07-31 00:40:00 +0000737 OverriddenFiles[R->first] = std::make_pair(StatBuf.st_size,
738 StatBuf.st_mtime);
739 }
740 for (PreprocessorOptions::remapped_file_buffer_iterator
741 R = PreprocessorOpts.remapped_file_buffer_begin(),
742 REnd = PreprocessorOpts.remapped_file_buffer_end();
743 !AnyFileChanged && R != REnd;
744 ++R) {
745 // FIXME: Should we actually compare the contents of file->buffer
746 // remappings?
747 OverriddenFiles[R->first] = std::make_pair(R->second->getBufferSize(),
748 0);
749 }
750
751 // Check whether anything has changed.
752 for (llvm::StringMap<std::pair<off_t, time_t> >::iterator
753 F = FilesInPreamble.begin(), FEnd = FilesInPreamble.end();
754 !AnyFileChanged && F != FEnd;
755 ++F) {
756 llvm::StringMap<std::pair<off_t, time_t> >::iterator Overridden
757 = OverriddenFiles.find(F->first());
758 if (Overridden != OverriddenFiles.end()) {
759 // This file was remapped; check whether the newly-mapped file
760 // matches up with the previous mapping.
761 if (Overridden->second != F->second)
762 AnyFileChanged = true;
763 continue;
764 }
765
766 // The file was not remapped; check whether it has changed on disk.
767 struct stat StatBuf;
768 if (stat(F->first(), &StatBuf)) {
769 // If we can't stat the file, assume that something horrible happened.
770 AnyFileChanged = true;
771 } else if (StatBuf.st_size != F->second.first ||
772 StatBuf.st_mtime != F->second.second)
773 AnyFileChanged = true;
774 }
775
776 if (!AnyFileChanged) {
Douglas Gregorc0659ec2010-08-02 20:51:39 +0000777 // Okay! We can re-use the precompiled preamble.
778
779 // Set the state of the diagnostic object to mimic its state
780 // after parsing the preamble.
781 getDiagnostics().Reset();
782 getDiagnostics().setNumWarnings(NumWarningsInPreamble);
783 if (StoredDiagnostics.size() > NumStoredDiagnosticsInPreamble)
784 StoredDiagnostics.erase(
785 StoredDiagnostics.begin() + NumStoredDiagnosticsInPreamble,
786 StoredDiagnostics.end());
787
788 // Create a version of the main file buffer that is padded to
789 // buffer size we reserved when creating the preamble.
Douglas Gregorcc5888d2010-07-31 00:40:00 +0000790 return CreatePaddedMainFileBuffer(NewPreamble.first,
791 CreatedPreambleBuffer,
792 PreambleReservedSize,
793 FrontendOpts.Inputs[0].second);
794 }
Douglas Gregor175c4a92010-07-23 23:58:40 +0000795 }
796
797 // We can't reuse the previously-computed preamble. Build a new one.
798 Preamble.clear();
Douglas Gregor385103b2010-07-30 20:58:08 +0000799 llvm::sys::Path(PreambleFile).eraseFromDisk();
Douglas Gregoreababfb2010-08-04 05:53:38 +0000800 PreambleRebuildCounter = 1;
Douglas Gregor175c4a92010-07-23 23:58:40 +0000801 }
Douglas Gregoreababfb2010-08-04 05:53:38 +0000802
803 // If the preamble rebuild counter > 1, it's because we previously
804 // failed to build a preamble and we're not yet ready to try
805 // again. Decrement the counter and return a failure.
806 if (PreambleRebuildCounter > 1) {
807 --PreambleRebuildCounter;
808 return 0;
809 }
810
Douglas Gregor175c4a92010-07-23 23:58:40 +0000811 // We did not previously compute a preamble, or it can't be reused anyway.
Douglas Gregor385103b2010-07-30 20:58:08 +0000812 llvm::Timer *PreambleTimer = 0;
813 if (TimerGroup.get()) {
814 PreambleTimer = new llvm::Timer("Precompiling preamble", *TimerGroup);
815 PreambleTimer->startTimer();
816 Timers.push_back(PreambleTimer);
817 }
Douglas Gregor44c181a2010-07-23 00:33:23 +0000818
819 // Create a new buffer that stores the preamble. The buffer also contains
820 // extra space for the original contents of the file (which will be present
821 // when we actually parse the file) along with more room in case the file
Douglas Gregor175c4a92010-07-23 23:58:40 +0000822 // grows.
823 PreambleReservedSize = NewPreamble.first->getBufferSize();
824 if (PreambleReservedSize < 4096)
Douglas Gregorf4f6c9d2010-07-26 21:36:20 +0000825 PreambleReservedSize = 8191;
Douglas Gregor44c181a2010-07-23 00:33:23 +0000826 else
Douglas Gregor175c4a92010-07-23 23:58:40 +0000827 PreambleReservedSize *= 2;
828
Douglas Gregorc0659ec2010-08-02 20:51:39 +0000829 // Save the preamble text for later; we'll need to compare against it for
830 // subsequent reparses.
831 Preamble.assign(NewPreamble.first->getBufferStart(),
832 NewPreamble.first->getBufferStart()
833 + NewPreamble.second.first);
834 PreambleEndsAtStartOfLine = NewPreamble.second.second;
835
Douglas Gregor44c181a2010-07-23 00:33:23 +0000836 llvm::MemoryBuffer *PreambleBuffer
Douglas Gregor175c4a92010-07-23 23:58:40 +0000837 = llvm::MemoryBuffer::getNewUninitMemBuffer(PreambleReservedSize,
Douglas Gregor44c181a2010-07-23 00:33:23 +0000838 FrontendOpts.Inputs[0].second);
839 memcpy(const_cast<char*>(PreambleBuffer->getBufferStart()),
Douglas Gregor175c4a92010-07-23 23:58:40 +0000840 NewPreamble.first->getBufferStart(), Preamble.size());
841 memset(const_cast<char*>(PreambleBuffer->getBufferStart()) + Preamble.size(),
Douglas Gregorf4f6c9d2010-07-26 21:36:20 +0000842 ' ', PreambleReservedSize - Preamble.size() - 1);
843 const_cast<char*>(PreambleBuffer->getBufferEnd())[-1] = '\n';
Douglas Gregor44c181a2010-07-23 00:33:23 +0000844
845 // Remap the main source file to the preamble buffer.
Douglas Gregor175c4a92010-07-23 23:58:40 +0000846 llvm::sys::PathWithStatus MainFilePath(FrontendOpts.Inputs[0].second);
Douglas Gregor44c181a2010-07-23 00:33:23 +0000847 PreprocessorOpts.addRemappedFile(MainFilePath.str(), PreambleBuffer);
848
849 // Tell the compiler invocation to generate a temporary precompiled header.
850 FrontendOpts.ProgramAction = frontend::GeneratePCH;
Sebastian Redlf65339e2010-08-06 00:35:11 +0000851 // FIXME: Set ChainedPCH unconditionally, once it is ready.
852 if (::getenv("LIBCLANG_CHAINING"))
853 FrontendOpts.ChainedPCH = true;
Douglas Gregor44c181a2010-07-23 00:33:23 +0000854 // FIXME: Generate the precompiled header into memory?
Douglas Gregor385103b2010-07-30 20:58:08 +0000855 FrontendOpts.OutputFile = GetPreamblePCHPath();
Douglas Gregor44c181a2010-07-23 00:33:23 +0000856
857 // Create the compiler instance to use for building the precompiled preamble.
858 CompilerInstance Clang;
859 Clang.setInvocation(&PreambleInvocation);
860 OriginalSourceFile = Clang.getFrontendOpts().Inputs[0].second;
861
Douglas Gregor1abc6bc2010-08-04 16:47:14 +0000862 // Set up diagnostics, capturing all of the diagnostics produced.
Douglas Gregor44c181a2010-07-23 00:33:23 +0000863 Clang.setDiagnostics(&getDiagnostics());
Douglas Gregor1abc6bc2010-08-04 16:47:14 +0000864 CaptureDroppedDiagnostics Capture(CaptureDiagnostics,
865 getDiagnostics(),
866 StoredDiagnostics);
Douglas Gregor44c181a2010-07-23 00:33:23 +0000867 Clang.setDiagnosticClient(getDiagnostics().getClient());
868
869 // Create the target instance.
870 Clang.setTarget(TargetInfo::CreateTargetInfo(Clang.getDiagnostics(),
871 Clang.getTargetOpts()));
872 if (!Clang.hasTarget()) {
873 Clang.takeDiagnosticClient();
Douglas Gregor175c4a92010-07-23 23:58:40 +0000874 llvm::sys::Path(FrontendOpts.OutputFile).eraseFromDisk();
875 Preamble.clear();
876 if (CreatedPreambleBuffer)
877 delete NewPreamble.first;
Douglas Gregor385103b2010-07-30 20:58:08 +0000878 if (PreambleTimer)
879 PreambleTimer->stopTimer();
Douglas Gregoreababfb2010-08-04 05:53:38 +0000880 PreambleRebuildCounter = DefaultPreambleRebuildInterval;
Douglas Gregor754f3492010-07-24 00:38:13 +0000881 return 0;
Douglas Gregor44c181a2010-07-23 00:33:23 +0000882 }
883
884 // Inform the target of the language options.
885 //
886 // FIXME: We shouldn't need to do this, the target should be immutable once
887 // created. This complexity should be lifted elsewhere.
888 Clang.getTarget().setForcedLangOptions(Clang.getLangOpts());
889
890 assert(Clang.getFrontendOpts().Inputs.size() == 1 &&
891 "Invocation must have exactly one source file!");
892 assert(Clang.getFrontendOpts().Inputs[0].first != IK_AST &&
893 "FIXME: AST inputs not yet supported here!");
894 assert(Clang.getFrontendOpts().Inputs[0].first != IK_LLVM_IR &&
895 "IR inputs not support here!");
896
897 // Clear out old caches and data.
898 StoredDiagnostics.clear();
Douglas Gregoreb8837b2010-08-03 19:06:41 +0000899 TopLevelDecls.clear();
900 TopLevelDeclsInPreamble.clear();
Douglas Gregor44c181a2010-07-23 00:33:23 +0000901
902 // Create a file manager object to provide access to and cache the filesystem.
903 Clang.setFileManager(new FileManager);
904
905 // Create the source manager.
906 Clang.setSourceManager(new SourceManager(getDiagnostics()));
907
Douglas Gregor1d715ac2010-08-03 08:14:03 +0000908 llvm::OwningPtr<PrecompilePreambleAction> Act;
909 Act.reset(new PrecompilePreambleAction(*this));
Douglas Gregor44c181a2010-07-23 00:33:23 +0000910 if (!Act->BeginSourceFile(Clang, Clang.getFrontendOpts().Inputs[0].second,
911 Clang.getFrontendOpts().Inputs[0].first)) {
912 Clang.takeDiagnosticClient();
913 Clang.takeInvocation();
Douglas Gregor175c4a92010-07-23 23:58:40 +0000914 llvm::sys::Path(FrontendOpts.OutputFile).eraseFromDisk();
915 Preamble.clear();
916 if (CreatedPreambleBuffer)
917 delete NewPreamble.first;
Douglas Gregor385103b2010-07-30 20:58:08 +0000918 if (PreambleTimer)
919 PreambleTimer->stopTimer();
Douglas Gregoreababfb2010-08-04 05:53:38 +0000920 PreambleRebuildCounter = DefaultPreambleRebuildInterval;
Douglas Gregor385103b2010-07-30 20:58:08 +0000921
Douglas Gregor754f3492010-07-24 00:38:13 +0000922 return 0;
Douglas Gregor44c181a2010-07-23 00:33:23 +0000923 }
924
925 Act->Execute();
926 Act->EndSourceFile();
927 Clang.takeDiagnosticClient();
928 Clang.takeInvocation();
929
Douglas Gregoreb8837b2010-08-03 19:06:41 +0000930 if (Diagnostics->hasErrorOccurred()) {
Douglas Gregor175c4a92010-07-23 23:58:40 +0000931 // There were errors parsing the preamble, so no precompiled header was
932 // generated. Forget that we even tried.
933 // FIXME: Should we leave a note for ourselves to try again?
934 llvm::sys::Path(FrontendOpts.OutputFile).eraseFromDisk();
935 Preamble.clear();
936 if (CreatedPreambleBuffer)
937 delete NewPreamble.first;
Douglas Gregor385103b2010-07-30 20:58:08 +0000938 if (PreambleTimer)
939 PreambleTimer->stopTimer();
Douglas Gregoreb8837b2010-08-03 19:06:41 +0000940 TopLevelDeclsInPreamble.clear();
Douglas Gregoreababfb2010-08-04 05:53:38 +0000941 PreambleRebuildCounter = DefaultPreambleRebuildInterval;
Douglas Gregor754f3492010-07-24 00:38:13 +0000942 return 0;
Douglas Gregor175c4a92010-07-23 23:58:40 +0000943 }
944
945 // Keep track of the preamble we precompiled.
946 PreambleFile = FrontendOpts.OutputFile;
Douglas Gregorc0659ec2010-08-02 20:51:39 +0000947 NumStoredDiagnosticsInPreamble = StoredDiagnostics.size();
948 NumWarningsInPreamble = getDiagnostics().getNumWarnings();
Douglas Gregorcc5888d2010-07-31 00:40:00 +0000949
950 // Keep track of all of the files that the source manager knows about,
951 // so we can verify whether they have changed or not.
952 FilesInPreamble.clear();
953 SourceManager &SourceMgr = Clang.getSourceManager();
954 const llvm::MemoryBuffer *MainFileBuffer
955 = SourceMgr.getBuffer(SourceMgr.getMainFileID());
956 for (SourceManager::fileinfo_iterator F = SourceMgr.fileinfo_begin(),
957 FEnd = SourceMgr.fileinfo_end();
958 F != FEnd;
959 ++F) {
960 const FileEntry *File = F->second->Entry;
961 if (!File || F->second->getRawBuffer() == MainFileBuffer)
962 continue;
963
964 FilesInPreamble[File->getName()]
965 = std::make_pair(F->second->getSize(), File->getModificationTime());
966 }
967
Douglas Gregor385103b2010-07-30 20:58:08 +0000968 if (PreambleTimer)
969 PreambleTimer->stopTimer();
970
Douglas Gregoreababfb2010-08-04 05:53:38 +0000971 PreambleRebuildCounter = 1;
Douglas Gregor754f3492010-07-24 00:38:13 +0000972 return CreatePaddedMainFileBuffer(NewPreamble.first,
973 CreatedPreambleBuffer,
974 PreambleReservedSize,
975 FrontendOpts.Inputs[0].second);
Douglas Gregor44c181a2010-07-23 00:33:23 +0000976}
Douglas Gregorabc563f2010-07-19 21:46:24 +0000977
Douglas Gregoreb8837b2010-08-03 19:06:41 +0000978void ASTUnit::RealizeTopLevelDeclsFromPreamble() {
979 std::vector<Decl *> Resolved;
980 Resolved.reserve(TopLevelDeclsInPreamble.size());
981 ExternalASTSource &Source = *getASTContext().getExternalSource();
982 for (unsigned I = 0, N = TopLevelDeclsInPreamble.size(); I != N; ++I) {
983 // Resolve the declaration ID to an actual declaration, possibly
984 // deserializing the declaration in the process.
985 Decl *D = Source.GetExternalDecl(TopLevelDeclsInPreamble[I]);
986 if (D)
987 Resolved.push_back(D);
988 }
989 TopLevelDeclsInPreamble.clear();
990 TopLevelDecls.insert(TopLevelDecls.begin(), Resolved.begin(), Resolved.end());
991}
992
993unsigned ASTUnit::getMaxPCHLevel() const {
994 if (!getOnlyLocalDecls())
995 return Decl::MaxPCHLevel;
996
997 unsigned Result = 0;
998 if (isMainFileAST() || SavedMainFileBuffer)
999 ++Result;
1000 return Result;
1001}
1002
Douglas Gregorabc563f2010-07-19 21:46:24 +00001003ASTUnit *ASTUnit::LoadFromCompilerInvocation(CompilerInvocation *CI,
1004 llvm::IntrusiveRefCntPtr<Diagnostic> Diags,
1005 bool OnlyLocalDecls,
Douglas Gregor44c181a2010-07-23 00:33:23 +00001006 bool CaptureDiagnostics,
1007 bool PrecompilePreamble) {
Douglas Gregorabc563f2010-07-19 21:46:24 +00001008 if (!Diags.getPtr()) {
1009 // No diagnostics engine was provided, so create our own diagnostics object
1010 // with the default options.
1011 DiagnosticOptions DiagOpts;
1012 Diags = CompilerInstance::createDiagnostics(DiagOpts, 0, 0);
1013 }
1014
1015 // Create the AST unit.
1016 llvm::OwningPtr<ASTUnit> AST;
1017 AST.reset(new ASTUnit(false));
1018 AST->Diagnostics = Diags;
1019 AST->CaptureDiagnostics = CaptureDiagnostics;
1020 AST->OnlyLocalDecls = OnlyLocalDecls;
1021 AST->Invocation.reset(CI);
Douglas Gregorf4f6c9d2010-07-26 21:36:20 +00001022 CI->getPreprocessorOpts().RetainRemappedFileBuffers = true;
Douglas Gregorabc563f2010-07-19 21:46:24 +00001023
Douglas Gregor385103b2010-07-30 20:58:08 +00001024 if (getenv("LIBCLANG_TIMING"))
1025 AST->TimerGroup.reset(
1026 new llvm::TimerGroup(CI->getFrontendOpts().Inputs[0].second));
1027
1028
Douglas Gregor754f3492010-07-24 00:38:13 +00001029 llvm::MemoryBuffer *OverrideMainBuffer = 0;
Douglas Gregorfd0b8702010-07-28 22:12:37 +00001030 // FIXME: When C++ PCH is ready, allow use of it for a precompiled preamble.
Douglas Gregoreababfb2010-08-04 05:53:38 +00001031 if (PrecompilePreamble && !CI->getLangOpts().CPlusPlus) {
1032 AST->PreambleRebuildCounter = 1;
Douglas Gregor754f3492010-07-24 00:38:13 +00001033 OverrideMainBuffer = AST->BuildPrecompiledPreamble();
Douglas Gregoreababfb2010-08-04 05:53:38 +00001034 }
Douglas Gregor44c181a2010-07-23 00:33:23 +00001035
Douglas Gregor385103b2010-07-30 20:58:08 +00001036 llvm::Timer *ParsingTimer = 0;
1037 if (AST->TimerGroup.get()) {
1038 ParsingTimer = new llvm::Timer("Initial parse", *AST->TimerGroup);
1039 ParsingTimer->startTimer();
1040 AST->Timers.push_back(ParsingTimer);
1041 }
Douglas Gregorabc563f2010-07-19 21:46:24 +00001042
Douglas Gregor385103b2010-07-30 20:58:08 +00001043 bool Failed = AST->Parse(OverrideMainBuffer);
1044 if (ParsingTimer)
1045 ParsingTimer->stopTimer();
1046
1047 return Failed? 0 : AST.take();
Daniel Dunbar521bf9c2009-12-01 09:51:01 +00001048}
Daniel Dunbar7b556682009-12-02 03:23:45 +00001049
1050ASTUnit *ASTUnit::LoadFromCommandLine(const char **ArgBegin,
1051 const char **ArgEnd,
Douglas Gregor28019772010-04-05 23:52:57 +00001052 llvm::IntrusiveRefCntPtr<Diagnostic> Diags,
Daniel Dunbar869824e2009-12-13 03:46:13 +00001053 llvm::StringRef ResourceFilesPath,
Daniel Dunbar7b556682009-12-02 03:23:45 +00001054 bool OnlyLocalDecls,
Douglas Gregor4db64a42010-01-23 00:14:00 +00001055 RemappedFile *RemappedFiles,
Douglas Gregora88084b2010-02-18 18:08:43 +00001056 unsigned NumRemappedFiles,
Douglas Gregor44c181a2010-07-23 00:33:23 +00001057 bool CaptureDiagnostics,
1058 bool PrecompilePreamble) {
Douglas Gregor28019772010-04-05 23:52:57 +00001059 if (!Diags.getPtr()) {
Douglas Gregor3687e9d2010-04-05 21:10:19 +00001060 // No diagnostics engine was provided, so create our own diagnostics object
1061 // with the default options.
1062 DiagnosticOptions DiagOpts;
Douglas Gregor28019772010-04-05 23:52:57 +00001063 Diags = CompilerInstance::createDiagnostics(DiagOpts, 0, 0);
Douglas Gregor3687e9d2010-04-05 21:10:19 +00001064 }
1065
Daniel Dunbar7b556682009-12-02 03:23:45 +00001066 llvm::SmallVector<const char *, 16> Args;
1067 Args.push_back("<clang>"); // FIXME: Remove dummy argument.
1068 Args.insert(Args.end(), ArgBegin, ArgEnd);
1069
1070 // FIXME: Find a cleaner way to force the driver into restricted modes. We
1071 // also want to force it to use clang.
1072 Args.push_back("-fsyntax-only");
1073
Daniel Dunbar869824e2009-12-13 03:46:13 +00001074 // FIXME: We shouldn't have to pass in the path info.
Daniel Dunbar0bbad512010-07-19 00:44:04 +00001075 driver::Driver TheDriver("clang", llvm::sys::getHostTriple(),
Douglas Gregor3687e9d2010-04-05 21:10:19 +00001076 "a.out", false, false, *Diags);
Daniel Dunbar3bd54cc2010-01-25 00:44:02 +00001077
1078 // Don't check that inputs exist, they have been remapped.
1079 TheDriver.setCheckInputsExist(false);
1080
Daniel Dunbar7b556682009-12-02 03:23:45 +00001081 llvm::OwningPtr<driver::Compilation> C(
1082 TheDriver.BuildCompilation(Args.size(), Args.data()));
1083
1084 // We expect to get back exactly one command job, if we didn't something
1085 // failed.
1086 const driver::JobList &Jobs = C->getJobs();
1087 if (Jobs.size() != 1 || !isa<driver::Command>(Jobs.begin())) {
1088 llvm::SmallString<256> Msg;
1089 llvm::raw_svector_ostream OS(Msg);
1090 C->PrintJob(OS, C->getJobs(), "; ", true);
Douglas Gregor3687e9d2010-04-05 21:10:19 +00001091 Diags->Report(diag::err_fe_expected_compiler_job) << OS.str();
Daniel Dunbar7b556682009-12-02 03:23:45 +00001092 return 0;
1093 }
1094
1095 const driver::Command *Cmd = cast<driver::Command>(*Jobs.begin());
1096 if (llvm::StringRef(Cmd->getCreator().getName()) != "clang") {
Douglas Gregor3687e9d2010-04-05 21:10:19 +00001097 Diags->Report(diag::err_fe_expected_clang_command);
Daniel Dunbar7b556682009-12-02 03:23:45 +00001098 return 0;
1099 }
1100
1101 const driver::ArgStringList &CCArgs = Cmd->getArguments();
Daniel Dunbar807b0612010-01-30 21:47:16 +00001102 llvm::OwningPtr<CompilerInvocation> CI(new CompilerInvocation);
Dan Gohmancb421fa2010-04-19 16:39:44 +00001103 CompilerInvocation::CreateFromArgs(*CI,
1104 const_cast<const char **>(CCArgs.data()),
1105 const_cast<const char **>(CCArgs.data()) +
Douglas Gregor44c181a2010-07-23 00:33:23 +00001106 CCArgs.size(),
Douglas Gregor3687e9d2010-04-05 21:10:19 +00001107 *Diags);
Daniel Dunbar1e69fe32009-12-13 03:45:58 +00001108
Douglas Gregor4db64a42010-01-23 00:14:00 +00001109 // Override any files that need remapping
1110 for (unsigned I = 0; I != NumRemappedFiles; ++I)
Daniel Dunbar807b0612010-01-30 21:47:16 +00001111 CI->getPreprocessorOpts().addRemappedFile(RemappedFiles[I].first,
Daniel Dunbarb26d4832010-02-16 01:55:04 +00001112 RemappedFiles[I].second);
Douglas Gregor4db64a42010-01-23 00:14:00 +00001113
Daniel Dunbar8b9adfe2009-12-15 00:06:45 +00001114 // Override the resources path.
Daniel Dunbar807b0612010-01-30 21:47:16 +00001115 CI->getHeaderSearchOpts().ResourceDir = ResourceFilesPath;
Daniel Dunbar7b556682009-12-02 03:23:45 +00001116
Daniel Dunbarb26d4832010-02-16 01:55:04 +00001117 CI->getFrontendOpts().DisableFree = true;
Douglas Gregora88084b2010-02-18 18:08:43 +00001118 return LoadFromCompilerInvocation(CI.take(), Diags, OnlyLocalDecls,
Douglas Gregor44c181a2010-07-23 00:33:23 +00001119 CaptureDiagnostics, PrecompilePreamble);
Daniel Dunbar7b556682009-12-02 03:23:45 +00001120}
Douglas Gregorabc563f2010-07-19 21:46:24 +00001121
1122bool ASTUnit::Reparse(RemappedFile *RemappedFiles, unsigned NumRemappedFiles) {
1123 if (!Invocation.get())
1124 return true;
1125
Douglas Gregor385103b2010-07-30 20:58:08 +00001126 llvm::Timer *ReparsingTimer = 0;
1127 if (TimerGroup.get()) {
1128 ReparsingTimer = new llvm::Timer("Reparse", *TimerGroup);
1129 ReparsingTimer->startTimer();
1130 Timers.push_back(ReparsingTimer);
1131 }
1132
Douglas Gregorcc5888d2010-07-31 00:40:00 +00001133 // Remap files.
Douglas Gregorcc5888d2010-07-31 00:40:00 +00001134 Invocation->getPreprocessorOpts().clearRemappedFiles();
1135 for (unsigned I = 0; I != NumRemappedFiles; ++I)
1136 Invocation->getPreprocessorOpts().addRemappedFile(RemappedFiles[I].first,
1137 RemappedFiles[I].second);
1138
Douglas Gregoreababfb2010-08-04 05:53:38 +00001139 // If we have a preamble file lying around, or if we might try to
1140 // build a precompiled preamble, do so now.
Douglas Gregor754f3492010-07-24 00:38:13 +00001141 llvm::MemoryBuffer *OverrideMainBuffer = 0;
Douglas Gregoreababfb2010-08-04 05:53:38 +00001142 if (!PreambleFile.empty() || PreambleRebuildCounter > 0)
Douglas Gregor754f3492010-07-24 00:38:13 +00001143 OverrideMainBuffer = BuildPrecompiledPreamble();
Douglas Gregor175c4a92010-07-23 23:58:40 +00001144
Douglas Gregorabc563f2010-07-19 21:46:24 +00001145 // Clear out the diagnostics state.
Douglas Gregorc0659ec2010-08-02 20:51:39 +00001146 if (!OverrideMainBuffer)
1147 getDiagnostics().Reset();
Douglas Gregorabc563f2010-07-19 21:46:24 +00001148
Douglas Gregor175c4a92010-07-23 23:58:40 +00001149 // Parse the sources
Douglas Gregor754f3492010-07-24 00:38:13 +00001150 bool Result = Parse(OverrideMainBuffer);
Douglas Gregor385103b2010-07-30 20:58:08 +00001151 if (ReparsingTimer)
1152 ReparsingTimer->stopTimer();
Douglas Gregor175c4a92010-07-23 23:58:40 +00001153 return Result;
Douglas Gregorabc563f2010-07-19 21:46:24 +00001154}
Douglas Gregor1abc6bc2010-08-04 16:47:14 +00001155
1156void ASTUnit::CodeComplete(llvm::StringRef File, unsigned Line, unsigned Column,
1157 RemappedFile *RemappedFiles,
1158 unsigned NumRemappedFiles,
Douglas Gregorcee235c2010-08-05 09:09:23 +00001159 bool IncludeMacros,
1160 bool IncludeCodePatterns,
Douglas Gregor1abc6bc2010-08-04 16:47:14 +00001161 CodeCompleteConsumer &Consumer,
1162 Diagnostic &Diag, LangOptions &LangOpts,
1163 SourceManager &SourceMgr, FileManager &FileMgr,
1164 llvm::SmallVectorImpl<StoredDiagnostic> &StoredDiagnostics) {
1165 if (!Invocation.get())
1166 return;
1167
1168 CompilerInvocation CCInvocation(*Invocation);
1169 FrontendOptions &FrontendOpts = CCInvocation.getFrontendOpts();
1170 PreprocessorOptions &PreprocessorOpts = CCInvocation.getPreprocessorOpts();
Douglas Gregorcee235c2010-08-05 09:09:23 +00001171
1172 FrontendOpts.ShowMacrosInCodeCompletion = IncludeMacros;
1173 FrontendOpts.ShowCodePatternsInCodeCompletion = IncludeCodePatterns;
Douglas Gregor1abc6bc2010-08-04 16:47:14 +00001174 FrontendOpts.CodeCompletionAt.FileName = File;
1175 FrontendOpts.CodeCompletionAt.Line = Line;
1176 FrontendOpts.CodeCompletionAt.Column = Column;
1177
Douglas Gregorcee235c2010-08-05 09:09:23 +00001178 // Turn on spell-checking when performing code completion. It leads
1179 // to better results.
1180 unsigned SpellChecking = CCInvocation.getLangOpts().SpellChecking;
1181 CCInvocation.getLangOpts().SpellChecking = 1;
1182
Douglas Gregor1abc6bc2010-08-04 16:47:14 +00001183 // Set the language options appropriately.
1184 LangOpts = CCInvocation.getLangOpts();
1185
1186 CompilerInstance Clang;
1187 Clang.setInvocation(&CCInvocation);
1188 OriginalSourceFile = Clang.getFrontendOpts().Inputs[0].second;
1189
1190 // Set up diagnostics, capturing any diagnostics produced.
1191 Clang.setDiagnostics(&Diag);
1192 CaptureDroppedDiagnostics Capture(true,
1193 Clang.getDiagnostics(),
1194 StoredDiagnostics);
1195 Clang.setDiagnosticClient(Diag.getClient());
1196
1197 // Create the target instance.
1198 Clang.setTarget(TargetInfo::CreateTargetInfo(Clang.getDiagnostics(),
1199 Clang.getTargetOpts()));
1200 if (!Clang.hasTarget()) {
1201 Clang.takeDiagnosticClient();
1202 Clang.takeInvocation();
1203 }
1204
1205 // Inform the target of the language options.
1206 //
1207 // FIXME: We shouldn't need to do this, the target should be immutable once
1208 // created. This complexity should be lifted elsewhere.
1209 Clang.getTarget().setForcedLangOptions(Clang.getLangOpts());
1210
1211 assert(Clang.getFrontendOpts().Inputs.size() == 1 &&
1212 "Invocation must have exactly one source file!");
1213 assert(Clang.getFrontendOpts().Inputs[0].first != IK_AST &&
1214 "FIXME: AST inputs not yet supported here!");
1215 assert(Clang.getFrontendOpts().Inputs[0].first != IK_LLVM_IR &&
1216 "IR inputs not support here!");
1217
1218
1219 // Use the source and file managers that we were given.
1220 Clang.setFileManager(&FileMgr);
1221 Clang.setSourceManager(&SourceMgr);
1222
1223 // Remap files.
1224 PreprocessorOpts.clearRemappedFiles();
Douglas Gregorb75d3df2010-08-04 17:07:00 +00001225 PreprocessorOpts.RetainRemappedFileBuffers = true;
Douglas Gregor1abc6bc2010-08-04 16:47:14 +00001226 for (unsigned I = 0; I != NumRemappedFiles; ++I)
1227 PreprocessorOpts.addRemappedFile(RemappedFiles[I].first,
1228 RemappedFiles[I].second);
1229
1230 // Use the code completion consumer we were given.
1231 Clang.setCodeCompletionConsumer(&Consumer);
1232
1233 llvm::OwningPtr<SyntaxOnlyAction> Act;
1234 Act.reset(new SyntaxOnlyAction);
1235 if (Act->BeginSourceFile(Clang, Clang.getFrontendOpts().Inputs[0].second,
1236 Clang.getFrontendOpts().Inputs[0].first)) {
1237 Act->Execute();
1238 Act->EndSourceFile();
1239 }
1240
1241 // Steal back our resources.
1242 Clang.takeFileManager();
1243 Clang.takeSourceManager();
1244 Clang.takeInvocation();
1245 Clang.takeDiagnosticClient();
1246 Clang.takeCodeCompletionConsumer();
Douglas Gregorcee235c2010-08-05 09:09:23 +00001247 CCInvocation.getLangOpts().SpellChecking = SpellChecking;
Douglas Gregor1abc6bc2010-08-04 16:47:14 +00001248}