blob: 2d1708ccc6e783bd06c47cc7a0ce318654247145 [file] [log] [blame]
Argyrios Kyrtzidis3a08ec12009-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 Kyrtzidisce379752009-06-20 08:08:23 +000014#include "clang/Frontend/ASTUnit.h"
Douglas Gregor48c8cd32010-08-03 08:14:03 +000015#include "clang/Frontend/PCHWriter.h"
Argyrios Kyrtzidisce379752009-06-20 08:08:23 +000016#include "clang/AST/ASTContext.h"
Daniel Dunbar764c0822009-12-01 09:51:01 +000017#include "clang/AST/ASTConsumer.h"
Argyrios Kyrtzidisce379752009-06-20 08:08:23 +000018#include "clang/AST/DeclVisitor.h"
19#include "clang/AST/StmtVisitor.h"
Daniel Dunbar55a17b62009-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 Dunbar764c0822009-12-01 09:51:01 +000024#include "clang/Frontend/CompilerInstance.h"
25#include "clang/Frontend/FrontendActions.h"
Daniel Dunbar55a17b62009-12-02 03:23:45 +000026#include "clang/Frontend/FrontendDiagnostic.h"
Daniel Dunbar764c0822009-12-01 09:51:01 +000027#include "clang/Frontend/FrontendOptions.h"
Douglas Gregor48c8cd32010-08-03 08:14:03 +000028#include "clang/Frontend/PCHReader.h"
Argyrios Kyrtzidisce379752009-06-20 08:08:23 +000029#include "clang/Lex/HeaderSearch.h"
30#include "clang/Lex/Preprocessor.h"
Daniel Dunbarb9bbd542009-11-15 06:48:46 +000031#include "clang/Basic/TargetOptions.h"
Argyrios Kyrtzidisce379752009-06-20 08:08:23 +000032#include "clang/Basic/TargetInfo.h"
33#include "clang/Basic/Diagnostic.h"
Douglas Gregoraa98ed92010-01-23 00:14:00 +000034#include "llvm/Support/MemoryBuffer.h"
Daniel Dunbar55a17b62009-12-02 03:23:45 +000035#include "llvm/System/Host.h"
Benjamin Kramer6c839f82009-10-18 11:34:14 +000036#include "llvm/System/Path.h"
Douglas Gregor15ba0b32010-07-30 20:58:08 +000037#include "llvm/Support/Timer.h"
Douglas Gregorbe2d8c62010-07-23 00:33:23 +000038#include <cstdlib>
Zhongxing Xu318e4032010-07-23 02:15:08 +000039#include <cstdio>
Douglas Gregor0e119552010-07-31 00:40:00 +000040#include <sys/stat.h>
Argyrios Kyrtzidisce379752009-06-20 08:08:23 +000041using namespace clang;
42
Douglas Gregorbb420ab2010-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 Gregord03e8232010-04-05 21:10:19 +000049ASTUnit::ASTUnit(bool _MainFileIsAST)
Douglas Gregoraa21cc42010-07-19 21:46:24 +000050 : CaptureDiagnostics(false), MainFileIsAST(_MainFileIsAST),
Douglas Gregorbb420ab2010-08-04 05:53:38 +000051 ConcurrencyCheckValue(CheckUnlocked), PreambleRebuildCounter(0),
52 SavedMainFileBuffer(0) {
Douglas Gregor15ba0b32010-07-30 20:58:08 +000053}
Douglas Gregord03e8232010-04-05 21:10:19 +000054
Daniel Dunbar764c0822009-12-01 09:51:01 +000055ASTUnit::~ASTUnit() {
Douglas Gregor0c7c2f82010-03-05 21:16:25 +000056 ConcurrencyCheckValue = CheckLocked;
Douglas Gregoraa21cc42010-07-19 21:46:24 +000057 CleanTemporaryFiles();
Douglas Gregor4dde7492010-07-23 23:58:40 +000058 if (!PreambleFile.empty())
Douglas Gregor15ba0b32010-07-30 20:58:08 +000059 llvm::sys::Path(PreambleFile).eraseFromDisk();
Douglas Gregor3f4bea02010-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 Gregor96c04262010-07-27 14:52:07 +000074
75 delete SavedMainFileBuffer;
Douglas Gregor15ba0b32010-07-30 20:58:08 +000076
77 for (unsigned I = 0, N = Timers.size(); I != N; ++I)
78 delete Timers[I];
Douglas Gregoraa21cc42010-07-19 21:46:24 +000079}
80
81void ASTUnit::CleanTemporaryFiles() {
Douglas Gregor6cb5ba42010-02-18 23:35:40 +000082 for (unsigned I = 0, N = TemporaryFiles.size(); I != N; ++I)
83 TemporaryFiles[I].eraseFromDisk();
Douglas Gregoraa21cc42010-07-19 21:46:24 +000084 TemporaryFiles.clear();
Steve Naroff44cd60e2009-10-15 22:23:48 +000085}
Argyrios Kyrtzidisce379752009-06-20 08:08:23 +000086
87namespace {
88
89/// \brief Gathers information from PCHReader that will be used to initialize
90/// a Preprocessor.
Benjamin Kramer16634c22009-11-28 10:07:24 +000091class PCHInfoCollector : public PCHReaderListener {
Argyrios Kyrtzidisce379752009-06-20 08:08:23 +000092 LangOptions &LangOpt;
93 HeaderSearch &HSI;
94 std::string &TargetTriple;
95 std::string &Predefines;
96 unsigned &Counter;
Mike Stump11289f42009-09-09 15:08:12 +000097
Argyrios Kyrtzidisce379752009-06-20 08:08:23 +000098 unsigned NumHeaderInfos;
Mike Stump11289f42009-09-09 15:08:12 +000099
Argyrios Kyrtzidisce379752009-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 Stump11289f42009-09-09 15:08:12 +0000106
Argyrios Kyrtzidisce379752009-06-20 08:08:23 +0000107 virtual bool ReadLanguageOptions(const LangOptions &LangOpts) {
108 LangOpt = LangOpts;
109 return false;
110 }
Mike Stump11289f42009-09-09 15:08:12 +0000111
Daniel Dunbar20a682d2009-11-11 00:52:11 +0000112 virtual bool ReadTargetTriple(llvm::StringRef Triple) {
Argyrios Kyrtzidisce379752009-06-20 08:08:23 +0000113 TargetTriple = Triple;
114 return false;
115 }
Mike Stump11289f42009-09-09 15:08:12 +0000116
Sebastian Redl8b41f302010-07-14 23:29:55 +0000117 virtual bool ReadPredefinesBuffer(const PCHPredefinesBlocks &Buffers,
Daniel Dunbar000c4ff2009-11-11 05:29:04 +0000118 llvm::StringRef OriginalFileName,
Argyrios Kyrtzidisce379752009-06-20 08:08:23 +0000119 std::string &SuggestedPredefines) {
Sebastian Redl8b41f302010-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 Kyrtzidisce379752009-06-20 08:08:23 +0000124 return false;
125 }
Mike Stump11289f42009-09-09 15:08:12 +0000126
Douglas Gregora2f49452010-03-16 19:09:18 +0000127 virtual void ReadHeaderFileInfo(const HeaderFileInfo &HFI, unsigned ID) {
Argyrios Kyrtzidisce379752009-06-20 08:08:23 +0000128 HSI.setHeaderFileInfoForUID(HFI, NumHeaderInfos++);
129 }
Mike Stump11289f42009-09-09 15:08:12 +0000130
Argyrios Kyrtzidisce379752009-06-20 08:08:23 +0000131 virtual void ReadCounter(unsigned Value) {
132 Counter = Value;
133 }
134};
135
Douglas Gregor33cdd812010-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 Kyrtzidisce379752009-06-20 08:08:23 +0000169} // anonymous namespace
170
Douglas Gregor33cdd812010-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 Naroffc0683b92009-09-03 18:19:54 +0000176const std::string &ASTUnit::getOriginalSourceFileName() {
Daniel Dunbara8a50932009-12-02 08:44:16 +0000177 return OriginalSourceFile;
Steve Naroffc0683b92009-09-03 18:19:54 +0000178}
Argyrios Kyrtzidisce379752009-06-20 08:08:23 +0000179
Steve Naroff44cd60e2009-10-15 22:23:48 +0000180const std::string &ASTUnit::getPCHFileName() {
Daniel Dunbara18f9582009-12-02 21:47:43 +0000181 assert(isMainFileAST() && "Not an ASTUnit from a PCH file!");
Benjamin Kramer2ecf8eb2010-01-30 16:23:25 +0000182 return static_cast<PCHReader *>(Ctx->getExternalSource())->getFileName();
Steve Naroff44cd60e2009-10-15 22:23:48 +0000183}
184
Argyrios Kyrtzidisce379752009-06-20 08:08:23 +0000185ASTUnit *ASTUnit::LoadFromPCHFile(const std::string &Filename,
Douglas Gregor7f95d262010-04-05 23:52:57 +0000186 llvm::IntrusiveRefCntPtr<Diagnostic> Diags,
Ted Kremenek8bcb1c62009-10-17 00:34:24 +0000187 bool OnlyLocalDecls,
Douglas Gregoraa98ed92010-01-23 00:14:00 +0000188 RemappedFile *RemappedFiles,
Douglas Gregor33cdd812010-02-18 18:08:43 +0000189 unsigned NumRemappedFiles,
190 bool CaptureDiagnostics) {
Douglas Gregord03e8232010-04-05 21:10:19 +0000191 llvm::OwningPtr<ASTUnit> AST(new ASTUnit(true));
192
Douglas Gregor7f95d262010-04-05 23:52:57 +0000193 if (!Diags.getPtr()) {
Douglas Gregord03e8232010-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 Gregor7f95d262010-04-05 23:52:57 +0000197 Diags = CompilerInstance::createDiagnostics(DiagOpts, 0, 0);
Douglas Gregord03e8232010-04-05 21:10:19 +0000198 }
Douglas Gregoraa21cc42010-07-19 21:46:24 +0000199
200 AST->CaptureDiagnostics = CaptureDiagnostics;
Douglas Gregor16bef852009-10-16 20:01:17 +0000201 AST->OnlyLocalDecls = OnlyLocalDecls;
Douglas Gregor7f95d262010-04-05 23:52:57 +0000202 AST->Diagnostics = Diags;
Douglas Gregord03e8232010-04-05 21:10:19 +0000203 AST->FileMgr.reset(new FileManager);
204 AST->SourceMgr.reset(new SourceManager(AST->getDiagnostics()));
Steve Naroff505fb842009-10-19 14:34:22 +0000205 AST->HeaderInfo.reset(new HeaderSearch(AST->getFileManager()));
Argyrios Kyrtzidisce379752009-06-20 08:08:23 +0000206
Douglas Gregor33cdd812010-02-18 18:08:43 +0000207 // If requested, capture diagnostics in the ASTUnit.
Douglas Gregord03e8232010-04-05 21:10:19 +0000208 CaptureDroppedDiagnostics Capture(CaptureDiagnostics, AST->getDiagnostics(),
Douglas Gregora2433152010-04-05 18:10:21 +0000209 AST->StoredDiagnostics);
Douglas Gregor33cdd812010-02-18 18:08:43 +0000210
Douglas Gregoraa98ed92010-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 Gregord03e8232010-04-05 21:10:19 +0000218 AST->getDiagnostics().Report(diag::err_fe_remap_missing_from_file)
Douglas Gregoraa98ed92010-01-23 00:14:00 +0000219 << RemappedFiles[I].first;
Douglas Gregor89a56c52010-02-27 01:32:48 +0000220 delete RemappedFiles[I].second;
Douglas Gregoraa98ed92010-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 Kyrtzidisce379752009-06-20 08:08:23 +0000230 // Gather Info for preprocessor construction later on.
Mike Stump11289f42009-09-09 15:08:12 +0000231
Argyrios Kyrtzidisce379752009-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 Dunbar3a0637b2009-09-03 05:59:50 +0000238 llvm::OwningPtr<PCHReader> Reader;
Argyrios Kyrtzidisce379752009-06-20 08:08:23 +0000239 llvm::OwningPtr<ExternalASTSource> Source;
240
Ted Kremenek428c6372009-10-19 21:44:57 +0000241 Reader.reset(new PCHReader(AST->getSourceManager(), AST->getFileManager(),
Douglas Gregord03e8232010-04-05 21:10:19 +0000242 AST->getDiagnostics()));
Daniel Dunbar2d9c7402009-09-03 05:59:35 +0000243 Reader->setListener(new PCHInfoCollector(LangInfo, HeaderInfo, TargetTriple,
244 Predefines, Counter));
245
246 switch (Reader->ReadPCH(Filename)) {
Argyrios Kyrtzidisce379752009-06-20 08:08:23 +0000247 case PCHReader::Success:
248 break;
Mike Stump11289f42009-09-09 15:08:12 +0000249
Argyrios Kyrtzidisce379752009-06-20 08:08:23 +0000250 case PCHReader::Failure:
Argyrios Kyrtzidis55c34112009-06-25 18:22:30 +0000251 case PCHReader::IgnorePCH:
Douglas Gregord03e8232010-04-05 21:10:19 +0000252 AST->getDiagnostics().Report(diag::err_fe_unable_to_load_pch);
Argyrios Kyrtzidisce379752009-06-20 08:08:23 +0000253 return NULL;
Argyrios Kyrtzidisce379752009-06-20 08:08:23 +0000254 }
Mike Stump11289f42009-09-09 15:08:12 +0000255
Daniel Dunbara8a50932009-12-02 08:44:16 +0000256 AST->OriginalSourceFile = Reader->getOriginalSourceFile();
257
Argyrios Kyrtzidisce379752009-06-20 08:08:23 +0000258 // PCH loaded successfully. Now create the preprocessor.
Mike Stump11289f42009-09-09 15:08:12 +0000259
Argyrios Kyrtzidisce379752009-06-20 08:08:23 +0000260 // Get information about the target being compiled for.
Daniel Dunbarb9bbd542009-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 Davis95a546e2010-06-11 01:06:47 +0000265 TargetOpts.CXXABI = "itanium";
Daniel Dunbarb9bbd542009-11-15 06:48:46 +0000266 TargetOpts.CPU = "";
267 TargetOpts.Features.clear();
268 TargetOpts.Triple = TargetTriple;
Douglas Gregord03e8232010-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 Dunbar7cd285f2009-09-21 03:03:39 +0000273 AST->getSourceManager(), HeaderInfo));
Argyrios Kyrtzidisce379752009-06-20 08:08:23 +0000274 Preprocessor &PP = *AST->PP.get();
275
Daniel Dunbarb7bbfdd2009-09-21 03:03:47 +0000276 PP.setPredefines(Reader->getSuggestedPredefines());
Argyrios Kyrtzidisce379752009-06-20 08:08:23 +0000277 PP.setCounterValue(Counter);
Daniel Dunbar2d9c7402009-09-03 05:59:35 +0000278 Reader->setPreprocessor(PP);
Mike Stump11289f42009-09-09 15:08:12 +0000279
Argyrios Kyrtzidisce379752009-06-20 08:08:23 +0000280 // Create and initialize the ASTContext.
281
282 AST->Ctx.reset(new ASTContext(LangInfo,
Daniel Dunbar7cd285f2009-09-21 03:03:39 +0000283 AST->getSourceManager(),
Argyrios Kyrtzidisce379752009-06-20 08:08:23 +0000284 *AST->Target.get(),
285 PP.getIdentifierTable(),
286 PP.getSelectorTable(),
287 PP.getBuiltinInfo(),
Argyrios Kyrtzidisce379752009-06-20 08:08:23 +0000288 /* size_reserve = */0));
289 ASTContext &Context = *AST->Ctx.get();
Mike Stump11289f42009-09-09 15:08:12 +0000290
Daniel Dunbar2d9c7402009-09-03 05:59:35 +0000291 Reader->InitializeContext(Context);
Mike Stump11289f42009-09-09 15:08:12 +0000292
Argyrios Kyrtzidisce379752009-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 Dunbar2d9c7402009-09-03 05:59:35 +0000296 Source.reset(Reader.take());
Argyrios Kyrtzidisce379752009-06-20 08:08:23 +0000297 Context.setExternalSource(Source);
298
Mike Stump11289f42009-09-09 15:08:12 +0000299 return AST.take();
Argyrios Kyrtzidisce379752009-06-20 08:08:23 +0000300}
Daniel Dunbar764c0822009-12-01 09:51:01 +0000301
302namespace {
303
Daniel Dunbar644dca02009-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 Kremenekacc59c32010-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 Gregore9db88f2010-08-03 19:06:41 +0000319 Unit.addTopLevelDecl(D);
Ted Kremenekacc59c32010-05-03 20:16:35 +0000320 }
Daniel Dunbar644dca02009-12-04 08:17:33 +0000321 }
322};
323
324class TopLevelDeclTrackerAction : public ASTFrontendAction {
325public:
326 ASTUnit &Unit;
327
Daniel Dunbar764c0822009-12-01 09:51:01 +0000328 virtual ASTConsumer *CreateASTConsumer(CompilerInstance &CI,
329 llvm::StringRef InFile) {
Daniel Dunbar644dca02009-12-04 08:17:33 +0000330 return new TopLevelDeclTrackerConsumer(Unit);
Daniel Dunbar764c0822009-12-01 09:51:01 +0000331 }
332
333public:
Daniel Dunbar644dca02009-12-04 08:17:33 +0000334 TopLevelDeclTrackerAction(ASTUnit &_Unit) : Unit(_Unit) {}
335
Daniel Dunbar764c0822009-12-01 09:51:01 +0000336 virtual bool hasCodeCompletionSupport() const { return false; }
337};
338
Douglas Gregor48c8cd32010-08-03 08:14:03 +0000339class PrecompilePreambleConsumer : public PCHGenerator {
340 ASTUnit &Unit;
Douglas Gregore9db88f2010-08-03 19:06:41 +0000341 std::vector<Decl *> TopLevelDecls;
Douglas Gregor48c8cd32010-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 Gregore9db88f2010-08-03 19:06:41 +0000349 virtual void HandleTopLevelDecl(DeclGroupRef D) {
Douglas Gregor48c8cd32010-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 Gregore9db88f2010-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 Gregor48c8cd32010-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 Dunbar764c0822009-12-01 09:51:01 +0000401}
402
Douglas Gregoraa21cc42010-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 Gregor6481ef12010-07-24 00:38:13 +0000408bool ASTUnit::Parse(llvm::MemoryBuffer *OverrideMainBuffer) {
Douglas Gregor96c04262010-07-27 14:52:07 +0000409 delete SavedMainFileBuffer;
410 SavedMainFileBuffer = 0;
411
Douglas Gregoraa21cc42010-07-19 21:46:24 +0000412 if (!Invocation.get())
413 return true;
414
Daniel Dunbar764c0822009-12-01 09:51:01 +0000415 // Create the compiler instance to use for building the AST.
Daniel Dunbar7afbb8c2009-12-02 08:43:56 +0000416 CompilerInstance Clang;
Douglas Gregoraa21cc42010-07-19 21:46:24 +0000417 Clang.setInvocation(Invocation.take());
418 OriginalSourceFile = Clang.getFrontendOpts().Inputs[0].second;
419
Douglas Gregor8e984da2010-08-04 16:47:14 +0000420 // Set up diagnostics, capturing any diagnostics that would
421 // otherwise be dropped.
Douglas Gregoraa21cc42010-07-19 21:46:24 +0000422 Clang.setDiagnostics(&getDiagnostics());
Douglas Gregor8e984da2010-08-04 16:47:14 +0000423 CaptureDroppedDiagnostics Capture(CaptureDiagnostics,
424 getDiagnostics(),
425 StoredDiagnostics);
Douglas Gregoraa21cc42010-07-19 21:46:24 +0000426 Clang.setDiagnosticClient(getDiagnostics().getClient());
Douglas Gregord03e8232010-04-05 21:10:19 +0000427
Daniel Dunbar764c0822009-12-01 09:51:01 +0000428 // Create the target instance.
429 Clang.setTarget(TargetInfo::CreateTargetInfo(Clang.getDiagnostics(),
430 Clang.getTargetOpts()));
Douglas Gregor33cdd812010-02-18 18:08:43 +0000431 if (!Clang.hasTarget()) {
Douglas Gregor33cdd812010-02-18 18:08:43 +0000432 Clang.takeDiagnosticClient();
Douglas Gregoraa21cc42010-07-19 21:46:24 +0000433 return true;
Douglas Gregor33cdd812010-02-18 18:08:43 +0000434 }
Douglas Gregoraa21cc42010-07-19 21:46:24 +0000435
Daniel Dunbar764c0822009-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 Gregoraa21cc42010-07-19 21:46:24 +0000441
Daniel Dunbar764c0822009-12-01 09:51:01 +0000442 assert(Clang.getFrontendOpts().Inputs.size() == 1 &&
443 "Invocation must have exactly one source file!");
Daniel Dunbar9b491e72010-06-07 23:22:09 +0000444 assert(Clang.getFrontendOpts().Inputs[0].first != IK_AST &&
Daniel Dunbar764c0822009-12-01 09:51:01 +0000445 "FIXME: AST inputs not yet supported here!");
Daniel Dunbar9507f9c2010-06-07 23:26:47 +0000446 assert(Clang.getFrontendOpts().Inputs[0].first != IK_LLVM_IR &&
447 "IR inputs not support here!");
Daniel Dunbar764c0822009-12-01 09:51:01 +0000448
Douglas Gregoraa21cc42010-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 Gregoraa21cc42010-07-19 21:46:24 +0000458 CleanTemporaryFiles();
459 PreprocessedEntitiesByFile.clear();
Douglas Gregord9a30af2010-08-02 20:51:39 +0000460
461 if (!OverrideMainBuffer)
462 StoredDiagnostics.clear();
Douglas Gregor8e984da2010-08-04 16:47:14 +0000463
Daniel Dunbar764c0822009-12-01 09:51:01 +0000464 // Create a file manager object to provide access to and cache the filesystem.
Douglas Gregoraa21cc42010-07-19 21:46:24 +0000465 Clang.setFileManager(&getFileManager());
466
Daniel Dunbar764c0822009-12-01 09:51:01 +0000467 // Create the source manager.
Douglas Gregoraa21cc42010-07-19 21:46:24 +0000468 Clang.setSourceManager(&getSourceManager());
469
Douglas Gregor3f4bea02010-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 Gregor8e984da2010-08-04 16:47:14 +0000473 std::string PriorImplicitPCHInclude;
Douglas Gregor3f4bea02010-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 Gregor8e984da2010-08-04 16:47:14 +0000479 PriorImplicitPCHInclude = PreprocessorOpts.ImplicitPCHInclude;
Douglas Gregor15ba0b32010-07-30 20:58:08 +0000480 PreprocessorOpts.ImplicitPCHInclude = PreambleFile;
Douglas Gregorce3a8292010-07-27 00:27:13 +0000481 PreprocessorOpts.DisablePCHValidation = true;
Douglas Gregor96c04262010-07-27 14:52:07 +0000482
483 // Keep track of the override buffer;
484 SavedMainFileBuffer = OverrideMainBuffer;
Douglas Gregord9a30af2010-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 Gregor3f4bea02010-07-26 21:36:20 +0000496 }
497
Douglas Gregoraa21cc42010-07-19 21:46:24 +0000498 llvm::OwningPtr<TopLevelDeclTrackerAction> Act;
499 Act.reset(new TopLevelDeclTrackerAction(*this));
Daniel Dunbar644dca02009-12-04 08:17:33 +0000500 if (!Act->BeginSourceFile(Clang, Clang.getFrontendOpts().Inputs[0].second,
Daniel Dunbar86546382010-06-07 23:23:06 +0000501 Clang.getFrontendOpts().Inputs[0].first))
Daniel Dunbar764c0822009-12-01 09:51:01 +0000502 goto error;
Douglas Gregoraa21cc42010-07-19 21:46:24 +0000503
Daniel Dunbar644dca02009-12-04 08:17:33 +0000504 Act->Execute();
Douglas Gregoraa21cc42010-07-19 21:46:24 +0000505
Daniel Dunbard2f8be32009-12-01 21:57:33 +0000506 // Steal the created target, context, and preprocessor, and take back the
507 // source and file managers.
Douglas Gregoraa21cc42010-07-19 21:46:24 +0000508 Ctx.reset(Clang.takeASTContext());
509 PP.reset(Clang.takePreprocessor());
Daniel Dunbar764c0822009-12-01 09:51:01 +0000510 Clang.takeSourceManager();
511 Clang.takeFileManager();
Douglas Gregoraa21cc42010-07-19 21:46:24 +0000512 Target.reset(Clang.takeTarget());
513
Daniel Dunbar644dca02009-12-04 08:17:33 +0000514 Act->EndSourceFile();
Douglas Gregor3f4bea02010-07-26 21:36:20 +0000515
516 // Remove the overridden buffer we used for the preamble.
Douglas Gregor8e984da2010-08-04 16:47:14 +0000517 if (OverrideMainBuffer) {
Douglas Gregor3f4bea02010-07-26 21:36:20 +0000518 PreprocessorOpts.eraseRemappedFile(
519 PreprocessorOpts.remapped_file_buffer_end() - 1);
Douglas Gregor8e984da2010-08-04 16:47:14 +0000520 PreprocessorOpts.ImplicitPCHInclude = PriorImplicitPCHInclude;
521 }
522
Daniel Dunbar764c0822009-12-01 09:51:01 +0000523 Clang.takeDiagnosticClient();
Douglas Gregoraa21cc42010-07-19 21:46:24 +0000524
525 Invocation.reset(Clang.takeInvocation());
526 return false;
527
Daniel Dunbar764c0822009-12-01 09:51:01 +0000528error:
Douglas Gregor3f4bea02010-07-26 21:36:20 +0000529 // Remove the overridden buffer we used for the preamble.
Douglas Gregorce3a8292010-07-27 00:27:13 +0000530 if (OverrideMainBuffer) {
Douglas Gregor3f4bea02010-07-26 21:36:20 +0000531 PreprocessorOpts.eraseRemappedFile(
532 PreprocessorOpts.remapped_file_buffer_end() - 1);
Douglas Gregorce3a8292010-07-27 00:27:13 +0000533 PreprocessorOpts.DisablePCHValidation = true;
Douglas Gregor8e984da2010-08-04 16:47:14 +0000534 PreprocessorOpts.ImplicitPCHInclude = PriorImplicitPCHInclude;
Douglas Gregorce3a8292010-07-27 00:27:13 +0000535 }
Douglas Gregor3f4bea02010-07-26 21:36:20 +0000536
Daniel Dunbar764c0822009-12-01 09:51:01 +0000537 Clang.takeSourceManager();
538 Clang.takeFileManager();
539 Clang.takeDiagnosticClient();
Douglas Gregoraa21cc42010-07-19 21:46:24 +0000540 Invocation.reset(Clang.takeInvocation());
541 return true;
542}
543
Douglas Gregorbe2d8c62010-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 Gregor3f4bea02010-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 Gregor4dde7492010-07-23 23:58:40 +0000570ASTUnit::ComputePreamble(CompilerInvocation &Invocation, bool &CreatedBuffer) {
571 FrontendOptions &FrontendOpts = Invocation.getFrontendOpts();
Douglas Gregorbe2d8c62010-07-23 00:33:23 +0000572 PreprocessorOptions &PreprocessorOpts
Douglas Gregor4dde7492010-07-23 23:58:40 +0000573 = Invocation.getPreprocessorOpts();
574 CreatedBuffer = false;
575
Douglas Gregorbe2d8c62010-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 Gregor4dde7492010-07-23 23:58:40 +0000579 llvm::MemoryBuffer *Buffer = 0;
Douglas Gregorbe2d8c62010-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 Gregor4dde7492010-07-23 23:58:40 +0000584 M = PreprocessorOpts.remapped_file_begin(),
585 E = PreprocessorOpts.remapped_file_end();
Douglas Gregorbe2d8c62010-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 Gregor4dde7492010-07-23 23:58:40 +0000592 if (CreatedBuffer) {
Douglas Gregorbe2d8c62010-07-23 00:33:23 +0000593 delete Buffer;
Douglas Gregor4dde7492010-07-23 23:58:40 +0000594 CreatedBuffer = false;
595 }
596
Douglas Gregorbe2d8c62010-07-23 00:33:23 +0000597 Buffer = llvm::MemoryBuffer::getFile(M->second);
598 if (!Buffer)
Douglas Gregor3f4bea02010-07-26 21:36:20 +0000599 return std::make_pair((llvm::MemoryBuffer*)0,
600 std::make_pair(0, true));
Douglas Gregor4dde7492010-07-23 23:58:40 +0000601 CreatedBuffer = true;
Douglas Gregorbe2d8c62010-07-23 00:33:23 +0000602
Douglas Gregor4dde7492010-07-23 23:58:40 +0000603 // Remove this remapping. We've captured the buffer already.
Douglas Gregorbe2d8c62010-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 Gregor4dde7492010-07-23 23:58:40 +0000621 if (CreatedBuffer) {
Douglas Gregorbe2d8c62010-07-23 00:33:23 +0000622 delete Buffer;
Douglas Gregor4dde7492010-07-23 23:58:40 +0000623 CreatedBuffer = false;
624 }
Douglas Gregorbe2d8c62010-07-23 00:33:23 +0000625
Douglas Gregor4dde7492010-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 Gregorbe2d8c62010-07-23 00:33:23 +0000629 M = PreprocessorOpts.eraseRemappedFile(M);
630 E = PreprocessorOpts.remapped_file_buffer_end();
631 }
632 }
Douglas Gregor4dde7492010-07-23 23:58:40 +0000633 }
Douglas Gregorbe2d8c62010-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 Gregor3f4bea02010-07-26 21:36:20 +0000640 return std::make_pair((llvm::MemoryBuffer*)0, std::make_pair(0, true));
Douglas Gregor4dde7492010-07-23 23:58:40 +0000641
642 CreatedBuffer = true;
Douglas Gregorbe2d8c62010-07-23 00:33:23 +0000643 }
644
Douglas Gregor4dde7492010-07-23 23:58:40 +0000645 return std::make_pair(Buffer, Lexer::ComputePreamble(Buffer));
646}
647
Douglas Gregor6481ef12010-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 Gregor3f4bea02010-07-26 21:36:20 +0000657 ' ', NewSize - Old->getBufferSize() - 1);
658 const_cast<char*>(Result->getBufferEnd())[-1] = '\n';
Douglas Gregor6481ef12010-07-24 00:38:13 +0000659
660 if (DeleteOld)
661 delete Old;
662
663 return Result;
664}
665
Douglas Gregor4dde7492010-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 Gregor6481ef12010-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 Gregor4dde7492010-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 Gregor3f4bea02010-07-26 21:36:20 +0000686 std::pair<llvm::MemoryBuffer *, std::pair<unsigned, bool> > NewPreamble
Douglas Gregor4dde7492010-07-23 23:58:40 +0000687 = ComputePreamble(PreambleInvocation, CreatedPreambleBuffer);
688
Douglas Gregor3f4bea02010-07-26 21:36:20 +0000689 if (!NewPreamble.second.first) {
Douglas Gregor4dde7492010-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 Gregor15ba0b32010-07-30 20:58:08 +0000694 llvm::sys::Path(PreambleFile).eraseFromDisk();
Douglas Gregor4dde7492010-07-23 23:58:40 +0000695 PreambleFile.clear();
696 }
697 if (CreatedPreambleBuffer)
698 delete NewPreamble.first;
Douglas Gregorbb420ab2010-08-04 05:53:38 +0000699
700 // The next time we actually see a preamble, precompile it.
701 PreambleRebuildCounter = 1;
Douglas Gregor6481ef12010-07-24 00:38:13 +0000702 return 0;
Douglas Gregor4dde7492010-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 Gregor3f4bea02010-07-26 21:36:20 +0000710 if (Preamble.size() == NewPreamble.second.first &&
711 PreambleEndsAtStartOfLine == NewPreamble.second.second &&
Douglas Gregorf5275a82010-07-24 00:42:07 +0000712 NewPreamble.first->getBufferSize() < PreambleReservedSize-2 &&
Douglas Gregor4dde7492010-07-23 23:58:40 +0000713 memcmp(&Preamble[0], NewPreamble.first->getBufferStart(),
Douglas Gregor3f4bea02010-07-26 21:36:20 +0000714 NewPreamble.second.first) == 0) {
Douglas Gregor4dde7492010-07-23 23:58:40 +0000715 // The preamble has not changed. We may be able to re-use the precompiled
716 // preamble.
Douglas Gregord9a30af2010-08-02 20:51:39 +0000717
Douglas Gregor0e119552010-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 Gregor6481ef12010-07-24 00:38:13 +0000736
Douglas Gregor0e119552010-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 Gregord9a30af2010-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 Gregor0e119552010-07-31 00:40:00 +0000790 return CreatePaddedMainFileBuffer(NewPreamble.first,
791 CreatedPreambleBuffer,
792 PreambleReservedSize,
793 FrontendOpts.Inputs[0].second);
794 }
Douglas Gregor4dde7492010-07-23 23:58:40 +0000795 }
796
797 // We can't reuse the previously-computed preamble. Build a new one.
798 Preamble.clear();
Douglas Gregor15ba0b32010-07-30 20:58:08 +0000799 llvm::sys::Path(PreambleFile).eraseFromDisk();
Douglas Gregorbb420ab2010-08-04 05:53:38 +0000800 PreambleRebuildCounter = 1;
Douglas Gregor4dde7492010-07-23 23:58:40 +0000801 }
Douglas Gregorbb420ab2010-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 Gregor4dde7492010-07-23 23:58:40 +0000811 // We did not previously compute a preamble, or it can't be reused anyway.
Douglas Gregor15ba0b32010-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 Gregorbe2d8c62010-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 Gregor4dde7492010-07-23 23:58:40 +0000822 // grows.
823 PreambleReservedSize = NewPreamble.first->getBufferSize();
824 if (PreambleReservedSize < 4096)
Douglas Gregor3f4bea02010-07-26 21:36:20 +0000825 PreambleReservedSize = 8191;
Douglas Gregorbe2d8c62010-07-23 00:33:23 +0000826 else
Douglas Gregor4dde7492010-07-23 23:58:40 +0000827 PreambleReservedSize *= 2;
828
Douglas Gregord9a30af2010-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 Gregorbe2d8c62010-07-23 00:33:23 +0000836 llvm::MemoryBuffer *PreambleBuffer
Douglas Gregor4dde7492010-07-23 23:58:40 +0000837 = llvm::MemoryBuffer::getNewUninitMemBuffer(PreambleReservedSize,
Douglas Gregorbe2d8c62010-07-23 00:33:23 +0000838 FrontendOpts.Inputs[0].second);
839 memcpy(const_cast<char*>(PreambleBuffer->getBufferStart()),
Douglas Gregor4dde7492010-07-23 23:58:40 +0000840 NewPreamble.first->getBufferStart(), Preamble.size());
841 memset(const_cast<char*>(PreambleBuffer->getBufferStart()) + Preamble.size(),
Douglas Gregor3f4bea02010-07-26 21:36:20 +0000842 ' ', PreambleReservedSize - Preamble.size() - 1);
843 const_cast<char*>(PreambleBuffer->getBufferEnd())[-1] = '\n';
Douglas Gregorbe2d8c62010-07-23 00:33:23 +0000844
845 // Remap the main source file to the preamble buffer.
Douglas Gregor4dde7492010-07-23 23:58:40 +0000846 llvm::sys::PathWithStatus MainFilePath(FrontendOpts.Inputs[0].second);
Douglas Gregorbe2d8c62010-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;
851 // FIXME: Set ChainedPCH, once it is ready.
852 // FIXME: Generate the precompiled header into memory?
Douglas Gregor15ba0b32010-07-30 20:58:08 +0000853 FrontendOpts.OutputFile = GetPreamblePCHPath();
Douglas Gregorbe2d8c62010-07-23 00:33:23 +0000854
855 // Create the compiler instance to use for building the precompiled preamble.
856 CompilerInstance Clang;
857 Clang.setInvocation(&PreambleInvocation);
858 OriginalSourceFile = Clang.getFrontendOpts().Inputs[0].second;
859
Douglas Gregor8e984da2010-08-04 16:47:14 +0000860 // Set up diagnostics, capturing all of the diagnostics produced.
Douglas Gregorbe2d8c62010-07-23 00:33:23 +0000861 Clang.setDiagnostics(&getDiagnostics());
Douglas Gregor8e984da2010-08-04 16:47:14 +0000862 CaptureDroppedDiagnostics Capture(CaptureDiagnostics,
863 getDiagnostics(),
864 StoredDiagnostics);
Douglas Gregorbe2d8c62010-07-23 00:33:23 +0000865 Clang.setDiagnosticClient(getDiagnostics().getClient());
866
867 // Create the target instance.
868 Clang.setTarget(TargetInfo::CreateTargetInfo(Clang.getDiagnostics(),
869 Clang.getTargetOpts()));
870 if (!Clang.hasTarget()) {
871 Clang.takeDiagnosticClient();
Douglas Gregor4dde7492010-07-23 23:58:40 +0000872 llvm::sys::Path(FrontendOpts.OutputFile).eraseFromDisk();
873 Preamble.clear();
874 if (CreatedPreambleBuffer)
875 delete NewPreamble.first;
Douglas Gregor15ba0b32010-07-30 20:58:08 +0000876 if (PreambleTimer)
877 PreambleTimer->stopTimer();
Douglas Gregorbb420ab2010-08-04 05:53:38 +0000878 PreambleRebuildCounter = DefaultPreambleRebuildInterval;
Douglas Gregor6481ef12010-07-24 00:38:13 +0000879 return 0;
Douglas Gregorbe2d8c62010-07-23 00:33:23 +0000880 }
881
882 // Inform the target of the language options.
883 //
884 // FIXME: We shouldn't need to do this, the target should be immutable once
885 // created. This complexity should be lifted elsewhere.
886 Clang.getTarget().setForcedLangOptions(Clang.getLangOpts());
887
888 assert(Clang.getFrontendOpts().Inputs.size() == 1 &&
889 "Invocation must have exactly one source file!");
890 assert(Clang.getFrontendOpts().Inputs[0].first != IK_AST &&
891 "FIXME: AST inputs not yet supported here!");
892 assert(Clang.getFrontendOpts().Inputs[0].first != IK_LLVM_IR &&
893 "IR inputs not support here!");
894
895 // Clear out old caches and data.
896 StoredDiagnostics.clear();
Douglas Gregore9db88f2010-08-03 19:06:41 +0000897 TopLevelDecls.clear();
898 TopLevelDeclsInPreamble.clear();
Douglas Gregorbe2d8c62010-07-23 00:33:23 +0000899
900 // Create a file manager object to provide access to and cache the filesystem.
901 Clang.setFileManager(new FileManager);
902
903 // Create the source manager.
904 Clang.setSourceManager(new SourceManager(getDiagnostics()));
905
Douglas Gregor48c8cd32010-08-03 08:14:03 +0000906 llvm::OwningPtr<PrecompilePreambleAction> Act;
907 Act.reset(new PrecompilePreambleAction(*this));
Douglas Gregorbe2d8c62010-07-23 00:33:23 +0000908 if (!Act->BeginSourceFile(Clang, Clang.getFrontendOpts().Inputs[0].second,
909 Clang.getFrontendOpts().Inputs[0].first)) {
910 Clang.takeDiagnosticClient();
911 Clang.takeInvocation();
Douglas Gregor4dde7492010-07-23 23:58:40 +0000912 llvm::sys::Path(FrontendOpts.OutputFile).eraseFromDisk();
913 Preamble.clear();
914 if (CreatedPreambleBuffer)
915 delete NewPreamble.first;
Douglas Gregor15ba0b32010-07-30 20:58:08 +0000916 if (PreambleTimer)
917 PreambleTimer->stopTimer();
Douglas Gregorbb420ab2010-08-04 05:53:38 +0000918 PreambleRebuildCounter = DefaultPreambleRebuildInterval;
Douglas Gregor15ba0b32010-07-30 20:58:08 +0000919
Douglas Gregor6481ef12010-07-24 00:38:13 +0000920 return 0;
Douglas Gregorbe2d8c62010-07-23 00:33:23 +0000921 }
922
923 Act->Execute();
924 Act->EndSourceFile();
925 Clang.takeDiagnosticClient();
926 Clang.takeInvocation();
927
Douglas Gregore9db88f2010-08-03 19:06:41 +0000928 if (Diagnostics->hasErrorOccurred()) {
Douglas Gregor4dde7492010-07-23 23:58:40 +0000929 // There were errors parsing the preamble, so no precompiled header was
930 // generated. Forget that we even tried.
931 // FIXME: Should we leave a note for ourselves to try again?
932 llvm::sys::Path(FrontendOpts.OutputFile).eraseFromDisk();
933 Preamble.clear();
934 if (CreatedPreambleBuffer)
935 delete NewPreamble.first;
Douglas Gregor15ba0b32010-07-30 20:58:08 +0000936 if (PreambleTimer)
937 PreambleTimer->stopTimer();
Douglas Gregore9db88f2010-08-03 19:06:41 +0000938 TopLevelDeclsInPreamble.clear();
Douglas Gregorbb420ab2010-08-04 05:53:38 +0000939 PreambleRebuildCounter = DefaultPreambleRebuildInterval;
Douglas Gregor6481ef12010-07-24 00:38:13 +0000940 return 0;
Douglas Gregor4dde7492010-07-23 23:58:40 +0000941 }
942
943 // Keep track of the preamble we precompiled.
944 PreambleFile = FrontendOpts.OutputFile;
Douglas Gregord9a30af2010-08-02 20:51:39 +0000945 NumStoredDiagnosticsInPreamble = StoredDiagnostics.size();
946 NumWarningsInPreamble = getDiagnostics().getNumWarnings();
Douglas Gregor0e119552010-07-31 00:40:00 +0000947
948 // Keep track of all of the files that the source manager knows about,
949 // so we can verify whether they have changed or not.
950 FilesInPreamble.clear();
951 SourceManager &SourceMgr = Clang.getSourceManager();
952 const llvm::MemoryBuffer *MainFileBuffer
953 = SourceMgr.getBuffer(SourceMgr.getMainFileID());
954 for (SourceManager::fileinfo_iterator F = SourceMgr.fileinfo_begin(),
955 FEnd = SourceMgr.fileinfo_end();
956 F != FEnd;
957 ++F) {
958 const FileEntry *File = F->second->Entry;
959 if (!File || F->second->getRawBuffer() == MainFileBuffer)
960 continue;
961
962 FilesInPreamble[File->getName()]
963 = std::make_pair(F->second->getSize(), File->getModificationTime());
964 }
965
Douglas Gregor15ba0b32010-07-30 20:58:08 +0000966 if (PreambleTimer)
967 PreambleTimer->stopTimer();
968
Douglas Gregorbb420ab2010-08-04 05:53:38 +0000969 PreambleRebuildCounter = 1;
Douglas Gregor6481ef12010-07-24 00:38:13 +0000970 return CreatePaddedMainFileBuffer(NewPreamble.first,
971 CreatedPreambleBuffer,
972 PreambleReservedSize,
973 FrontendOpts.Inputs[0].second);
Douglas Gregorbe2d8c62010-07-23 00:33:23 +0000974}
Douglas Gregoraa21cc42010-07-19 21:46:24 +0000975
Douglas Gregore9db88f2010-08-03 19:06:41 +0000976void ASTUnit::RealizeTopLevelDeclsFromPreamble() {
977 std::vector<Decl *> Resolved;
978 Resolved.reserve(TopLevelDeclsInPreamble.size());
979 ExternalASTSource &Source = *getASTContext().getExternalSource();
980 for (unsigned I = 0, N = TopLevelDeclsInPreamble.size(); I != N; ++I) {
981 // Resolve the declaration ID to an actual declaration, possibly
982 // deserializing the declaration in the process.
983 Decl *D = Source.GetExternalDecl(TopLevelDeclsInPreamble[I]);
984 if (D)
985 Resolved.push_back(D);
986 }
987 TopLevelDeclsInPreamble.clear();
988 TopLevelDecls.insert(TopLevelDecls.begin(), Resolved.begin(), Resolved.end());
989}
990
991unsigned ASTUnit::getMaxPCHLevel() const {
992 if (!getOnlyLocalDecls())
993 return Decl::MaxPCHLevel;
994
995 unsigned Result = 0;
996 if (isMainFileAST() || SavedMainFileBuffer)
997 ++Result;
998 return Result;
999}
1000
Douglas Gregoraa21cc42010-07-19 21:46:24 +00001001ASTUnit *ASTUnit::LoadFromCompilerInvocation(CompilerInvocation *CI,
1002 llvm::IntrusiveRefCntPtr<Diagnostic> Diags,
1003 bool OnlyLocalDecls,
Douglas Gregorbe2d8c62010-07-23 00:33:23 +00001004 bool CaptureDiagnostics,
1005 bool PrecompilePreamble) {
Douglas Gregoraa21cc42010-07-19 21:46:24 +00001006 if (!Diags.getPtr()) {
1007 // No diagnostics engine was provided, so create our own diagnostics object
1008 // with the default options.
1009 DiagnosticOptions DiagOpts;
1010 Diags = CompilerInstance::createDiagnostics(DiagOpts, 0, 0);
1011 }
1012
1013 // Create the AST unit.
1014 llvm::OwningPtr<ASTUnit> AST;
1015 AST.reset(new ASTUnit(false));
1016 AST->Diagnostics = Diags;
1017 AST->CaptureDiagnostics = CaptureDiagnostics;
1018 AST->OnlyLocalDecls = OnlyLocalDecls;
1019 AST->Invocation.reset(CI);
Douglas Gregor3f4bea02010-07-26 21:36:20 +00001020 CI->getPreprocessorOpts().RetainRemappedFileBuffers = true;
Douglas Gregoraa21cc42010-07-19 21:46:24 +00001021
Douglas Gregor15ba0b32010-07-30 20:58:08 +00001022 if (getenv("LIBCLANG_TIMING"))
1023 AST->TimerGroup.reset(
1024 new llvm::TimerGroup(CI->getFrontendOpts().Inputs[0].second));
1025
1026
Douglas Gregor6481ef12010-07-24 00:38:13 +00001027 llvm::MemoryBuffer *OverrideMainBuffer = 0;
Douglas Gregora5fd5222010-07-28 22:12:37 +00001028 // FIXME: When C++ PCH is ready, allow use of it for a precompiled preamble.
Douglas Gregorbb420ab2010-08-04 05:53:38 +00001029 if (PrecompilePreamble && !CI->getLangOpts().CPlusPlus) {
1030 AST->PreambleRebuildCounter = 1;
Douglas Gregor6481ef12010-07-24 00:38:13 +00001031 OverrideMainBuffer = AST->BuildPrecompiledPreamble();
Douglas Gregorbb420ab2010-08-04 05:53:38 +00001032 }
Douglas Gregorbe2d8c62010-07-23 00:33:23 +00001033
Douglas Gregor15ba0b32010-07-30 20:58:08 +00001034 llvm::Timer *ParsingTimer = 0;
1035 if (AST->TimerGroup.get()) {
1036 ParsingTimer = new llvm::Timer("Initial parse", *AST->TimerGroup);
1037 ParsingTimer->startTimer();
1038 AST->Timers.push_back(ParsingTimer);
1039 }
Douglas Gregoraa21cc42010-07-19 21:46:24 +00001040
Douglas Gregor15ba0b32010-07-30 20:58:08 +00001041 bool Failed = AST->Parse(OverrideMainBuffer);
1042 if (ParsingTimer)
1043 ParsingTimer->stopTimer();
1044
1045 return Failed? 0 : AST.take();
Daniel Dunbar764c0822009-12-01 09:51:01 +00001046}
Daniel Dunbar55a17b62009-12-02 03:23:45 +00001047
1048ASTUnit *ASTUnit::LoadFromCommandLine(const char **ArgBegin,
1049 const char **ArgEnd,
Douglas Gregor7f95d262010-04-05 23:52:57 +00001050 llvm::IntrusiveRefCntPtr<Diagnostic> Diags,
Daniel Dunbar8d4a2022009-12-13 03:46:13 +00001051 llvm::StringRef ResourceFilesPath,
Daniel Dunbar55a17b62009-12-02 03:23:45 +00001052 bool OnlyLocalDecls,
Douglas Gregoraa98ed92010-01-23 00:14:00 +00001053 RemappedFile *RemappedFiles,
Douglas Gregor33cdd812010-02-18 18:08:43 +00001054 unsigned NumRemappedFiles,
Douglas Gregorbe2d8c62010-07-23 00:33:23 +00001055 bool CaptureDiagnostics,
1056 bool PrecompilePreamble) {
Douglas Gregor7f95d262010-04-05 23:52:57 +00001057 if (!Diags.getPtr()) {
Douglas Gregord03e8232010-04-05 21:10:19 +00001058 // No diagnostics engine was provided, so create our own diagnostics object
1059 // with the default options.
1060 DiagnosticOptions DiagOpts;
Douglas Gregor7f95d262010-04-05 23:52:57 +00001061 Diags = CompilerInstance::createDiagnostics(DiagOpts, 0, 0);
Douglas Gregord03e8232010-04-05 21:10:19 +00001062 }
1063
Daniel Dunbar55a17b62009-12-02 03:23:45 +00001064 llvm::SmallVector<const char *, 16> Args;
1065 Args.push_back("<clang>"); // FIXME: Remove dummy argument.
1066 Args.insert(Args.end(), ArgBegin, ArgEnd);
1067
1068 // FIXME: Find a cleaner way to force the driver into restricted modes. We
1069 // also want to force it to use clang.
1070 Args.push_back("-fsyntax-only");
1071
Daniel Dunbar8d4a2022009-12-13 03:46:13 +00001072 // FIXME: We shouldn't have to pass in the path info.
Daniel Dunbare38764c2010-07-19 00:44:04 +00001073 driver::Driver TheDriver("clang", llvm::sys::getHostTriple(),
Douglas Gregord03e8232010-04-05 21:10:19 +00001074 "a.out", false, false, *Diags);
Daniel Dunbarfcf2d422010-01-25 00:44:02 +00001075
1076 // Don't check that inputs exist, they have been remapped.
1077 TheDriver.setCheckInputsExist(false);
1078
Daniel Dunbar55a17b62009-12-02 03:23:45 +00001079 llvm::OwningPtr<driver::Compilation> C(
1080 TheDriver.BuildCompilation(Args.size(), Args.data()));
1081
1082 // We expect to get back exactly one command job, if we didn't something
1083 // failed.
1084 const driver::JobList &Jobs = C->getJobs();
1085 if (Jobs.size() != 1 || !isa<driver::Command>(Jobs.begin())) {
1086 llvm::SmallString<256> Msg;
1087 llvm::raw_svector_ostream OS(Msg);
1088 C->PrintJob(OS, C->getJobs(), "; ", true);
Douglas Gregord03e8232010-04-05 21:10:19 +00001089 Diags->Report(diag::err_fe_expected_compiler_job) << OS.str();
Daniel Dunbar55a17b62009-12-02 03:23:45 +00001090 return 0;
1091 }
1092
1093 const driver::Command *Cmd = cast<driver::Command>(*Jobs.begin());
1094 if (llvm::StringRef(Cmd->getCreator().getName()) != "clang") {
Douglas Gregord03e8232010-04-05 21:10:19 +00001095 Diags->Report(diag::err_fe_expected_clang_command);
Daniel Dunbar55a17b62009-12-02 03:23:45 +00001096 return 0;
1097 }
1098
1099 const driver::ArgStringList &CCArgs = Cmd->getArguments();
Daniel Dunbar6b03ece2010-01-30 21:47:16 +00001100 llvm::OwningPtr<CompilerInvocation> CI(new CompilerInvocation);
Dan Gohman145f3f12010-04-19 16:39:44 +00001101 CompilerInvocation::CreateFromArgs(*CI,
1102 const_cast<const char **>(CCArgs.data()),
1103 const_cast<const char **>(CCArgs.data()) +
Douglas Gregorbe2d8c62010-07-23 00:33:23 +00001104 CCArgs.size(),
Douglas Gregord03e8232010-04-05 21:10:19 +00001105 *Diags);
Daniel Dunbard6136772009-12-13 03:45:58 +00001106
Douglas Gregoraa98ed92010-01-23 00:14:00 +00001107 // Override any files that need remapping
1108 for (unsigned I = 0; I != NumRemappedFiles; ++I)
Daniel Dunbar6b03ece2010-01-30 21:47:16 +00001109 CI->getPreprocessorOpts().addRemappedFile(RemappedFiles[I].first,
Daniel Dunbar19511922010-02-16 01:55:04 +00001110 RemappedFiles[I].second);
Douglas Gregoraa98ed92010-01-23 00:14:00 +00001111
Daniel Dunbara5a166d2009-12-15 00:06:45 +00001112 // Override the resources path.
Daniel Dunbar6b03ece2010-01-30 21:47:16 +00001113 CI->getHeaderSearchOpts().ResourceDir = ResourceFilesPath;
Daniel Dunbar55a17b62009-12-02 03:23:45 +00001114
Daniel Dunbar19511922010-02-16 01:55:04 +00001115 CI->getFrontendOpts().DisableFree = true;
Douglas Gregor33cdd812010-02-18 18:08:43 +00001116 return LoadFromCompilerInvocation(CI.take(), Diags, OnlyLocalDecls,
Douglas Gregorbe2d8c62010-07-23 00:33:23 +00001117 CaptureDiagnostics, PrecompilePreamble);
Daniel Dunbar55a17b62009-12-02 03:23:45 +00001118}
Douglas Gregoraa21cc42010-07-19 21:46:24 +00001119
1120bool ASTUnit::Reparse(RemappedFile *RemappedFiles, unsigned NumRemappedFiles) {
1121 if (!Invocation.get())
1122 return true;
1123
Douglas Gregor15ba0b32010-07-30 20:58:08 +00001124 llvm::Timer *ReparsingTimer = 0;
1125 if (TimerGroup.get()) {
1126 ReparsingTimer = new llvm::Timer("Reparse", *TimerGroup);
1127 ReparsingTimer->startTimer();
1128 Timers.push_back(ReparsingTimer);
1129 }
1130
Douglas Gregor0e119552010-07-31 00:40:00 +00001131 // Remap files.
Douglas Gregor0e119552010-07-31 00:40:00 +00001132 Invocation->getPreprocessorOpts().clearRemappedFiles();
1133 for (unsigned I = 0; I != NumRemappedFiles; ++I)
1134 Invocation->getPreprocessorOpts().addRemappedFile(RemappedFiles[I].first,
1135 RemappedFiles[I].second);
1136
Douglas Gregorbb420ab2010-08-04 05:53:38 +00001137 // If we have a preamble file lying around, or if we might try to
1138 // build a precompiled preamble, do so now.
Douglas Gregor6481ef12010-07-24 00:38:13 +00001139 llvm::MemoryBuffer *OverrideMainBuffer = 0;
Douglas Gregorbb420ab2010-08-04 05:53:38 +00001140 if (!PreambleFile.empty() || PreambleRebuildCounter > 0)
Douglas Gregor6481ef12010-07-24 00:38:13 +00001141 OverrideMainBuffer = BuildPrecompiledPreamble();
Douglas Gregor4dde7492010-07-23 23:58:40 +00001142
Douglas Gregoraa21cc42010-07-19 21:46:24 +00001143 // Clear out the diagnostics state.
Douglas Gregord9a30af2010-08-02 20:51:39 +00001144 if (!OverrideMainBuffer)
1145 getDiagnostics().Reset();
Douglas Gregoraa21cc42010-07-19 21:46:24 +00001146
Douglas Gregor4dde7492010-07-23 23:58:40 +00001147 // Parse the sources
Douglas Gregor6481ef12010-07-24 00:38:13 +00001148 bool Result = Parse(OverrideMainBuffer);
Douglas Gregor15ba0b32010-07-30 20:58:08 +00001149 if (ReparsingTimer)
1150 ReparsingTimer->stopTimer();
Douglas Gregor4dde7492010-07-23 23:58:40 +00001151 return Result;
Douglas Gregoraa21cc42010-07-19 21:46:24 +00001152}
Douglas Gregor8e984da2010-08-04 16:47:14 +00001153
1154void ASTUnit::CodeComplete(llvm::StringRef File, unsigned Line, unsigned Column,
1155 RemappedFile *RemappedFiles,
1156 unsigned NumRemappedFiles,
1157 CodeCompleteConsumer &Consumer,
1158 Diagnostic &Diag, LangOptions &LangOpts,
1159 SourceManager &SourceMgr, FileManager &FileMgr,
1160 llvm::SmallVectorImpl<StoredDiagnostic> &StoredDiagnostics) {
1161 if (!Invocation.get())
1162 return;
1163
1164 CompilerInvocation CCInvocation(*Invocation);
1165 FrontendOptions &FrontendOpts = CCInvocation.getFrontendOpts();
1166 PreprocessorOptions &PreprocessorOpts = CCInvocation.getPreprocessorOpts();
1167
1168 FrontendOpts.ShowMacrosInCodeCompletion = 1;
1169 FrontendOpts.ShowCodePatternsInCodeCompletion = 1;
1170 FrontendOpts.CodeCompletionAt.FileName = File;
1171 FrontendOpts.CodeCompletionAt.Line = Line;
1172 FrontendOpts.CodeCompletionAt.Column = Column;
1173
1174 // Set the language options appropriately.
1175 LangOpts = CCInvocation.getLangOpts();
1176
1177 CompilerInstance Clang;
1178 Clang.setInvocation(&CCInvocation);
1179 OriginalSourceFile = Clang.getFrontendOpts().Inputs[0].second;
1180
1181 // Set up diagnostics, capturing any diagnostics produced.
1182 Clang.setDiagnostics(&Diag);
1183 CaptureDroppedDiagnostics Capture(true,
1184 Clang.getDiagnostics(),
1185 StoredDiagnostics);
1186 Clang.setDiagnosticClient(Diag.getClient());
1187
1188 // Create the target instance.
1189 Clang.setTarget(TargetInfo::CreateTargetInfo(Clang.getDiagnostics(),
1190 Clang.getTargetOpts()));
1191 if (!Clang.hasTarget()) {
1192 Clang.takeDiagnosticClient();
1193 Clang.takeInvocation();
1194 }
1195
1196 // Inform the target of the language options.
1197 //
1198 // FIXME: We shouldn't need to do this, the target should be immutable once
1199 // created. This complexity should be lifted elsewhere.
1200 Clang.getTarget().setForcedLangOptions(Clang.getLangOpts());
1201
1202 assert(Clang.getFrontendOpts().Inputs.size() == 1 &&
1203 "Invocation must have exactly one source file!");
1204 assert(Clang.getFrontendOpts().Inputs[0].first != IK_AST &&
1205 "FIXME: AST inputs not yet supported here!");
1206 assert(Clang.getFrontendOpts().Inputs[0].first != IK_LLVM_IR &&
1207 "IR inputs not support here!");
1208
1209
1210 // Use the source and file managers that we were given.
1211 Clang.setFileManager(&FileMgr);
1212 Clang.setSourceManager(&SourceMgr);
1213
1214 // Remap files.
1215 PreprocessorOpts.clearRemappedFiles();
Douglas Gregord8a5dba2010-08-04 17:07:00 +00001216 PreprocessorOpts.RetainRemappedFileBuffers = true;
Douglas Gregor8e984da2010-08-04 16:47:14 +00001217 for (unsigned I = 0; I != NumRemappedFiles; ++I)
1218 PreprocessorOpts.addRemappedFile(RemappedFiles[I].first,
1219 RemappedFiles[I].second);
1220
1221 // Use the code completion consumer we were given.
1222 Clang.setCodeCompletionConsumer(&Consumer);
1223
1224 llvm::OwningPtr<SyntaxOnlyAction> Act;
1225 Act.reset(new SyntaxOnlyAction);
1226 if (Act->BeginSourceFile(Clang, Clang.getFrontendOpts().Inputs[0].second,
1227 Clang.getFrontendOpts().Inputs[0].first)) {
1228 Act->Execute();
1229 Act->EndSourceFile();
1230 }
1231
1232 // Steal back our resources.
1233 Clang.takeFileManager();
1234 Clang.takeSourceManager();
1235 Clang.takeInvocation();
1236 Clang.takeDiagnosticClient();
1237 Clang.takeCodeCompletionConsumer();
1238}