blob: b36a338c196da7342bcd844cd6fa93d3426dcf1e [file] [log] [blame]
Argyrios Kyrtzidis4b562cf2009-06-20 08:27:14 +00001//===--- ASTUnit.cpp - ASTUnit utility ------------------------------------===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9//
10// ASTUnit Implementation.
11//
12//===----------------------------------------------------------------------===//
13
Argyrios Kyrtzidis0853a022009-06-20 08:08:23 +000014#include "clang/Frontend/ASTUnit.h"
15#include "clang/Frontend/PCHReader.h"
Argyrios Kyrtzidis0853a022009-06-20 08:08:23 +000016#include "clang/AST/ASTContext.h"
Daniel Dunbar521bf9c2009-12-01 09:51:01 +000017#include "clang/AST/ASTConsumer.h"
Argyrios Kyrtzidis0853a022009-06-20 08:08:23 +000018#include "clang/AST/DeclVisitor.h"
19#include "clang/AST/StmtVisitor.h"
Daniel 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"
Argyrios Kyrtzidis0853a022009-06-20 08:08:23 +000028#include "clang/Lex/HeaderSearch.h"
29#include "clang/Lex/Preprocessor.h"
Daniel Dunbard58c03f2009-11-15 06:48:46 +000030#include "clang/Basic/TargetOptions.h"
Argyrios Kyrtzidis0853a022009-06-20 08:08:23 +000031#include "clang/Basic/TargetInfo.h"
32#include "clang/Basic/Diagnostic.h"
Douglas Gregor4db64a42010-01-23 00:14:00 +000033#include "llvm/Support/MemoryBuffer.h"
Daniel Dunbar7b556682009-12-02 03:23:45 +000034#include "llvm/System/Host.h"
Benjamin Kramer4a630d32009-10-18 11:34:14 +000035#include "llvm/System/Path.h"
Douglas Gregor385103b2010-07-30 20:58:08 +000036#include "llvm/Support/Timer.h"
Douglas Gregor44c181a2010-07-23 00:33:23 +000037#include <cstdlib>
Zhongxing Xuad23ebe2010-07-23 02:15:08 +000038#include <cstdio>
Douglas Gregorcc5888d2010-07-31 00:40:00 +000039#include <sys/stat.h>
Argyrios Kyrtzidis0853a022009-06-20 08:08:23 +000040using namespace clang;
41
Douglas Gregor3687e9d2010-04-05 21:10:19 +000042ASTUnit::ASTUnit(bool _MainFileIsAST)
Douglas Gregorabc563f2010-07-19 21:46:24 +000043 : CaptureDiagnostics(false), MainFileIsAST(_MainFileIsAST),
Douglas Gregor385103b2010-07-30 20:58:08 +000044 ConcurrencyCheckValue(CheckUnlocked), SavedMainFileBuffer(0) {
45}
Douglas Gregor3687e9d2010-04-05 21:10:19 +000046
Daniel Dunbar521bf9c2009-12-01 09:51:01 +000047ASTUnit::~ASTUnit() {
Douglas Gregorbdf60622010-03-05 21:16:25 +000048 ConcurrencyCheckValue = CheckLocked;
Douglas Gregorabc563f2010-07-19 21:46:24 +000049 CleanTemporaryFiles();
Douglas Gregor175c4a92010-07-23 23:58:40 +000050 if (!PreambleFile.empty())
Douglas Gregor385103b2010-07-30 20:58:08 +000051 llvm::sys::Path(PreambleFile).eraseFromDisk();
Douglas Gregorf4f6c9d2010-07-26 21:36:20 +000052
53 // Free the buffers associated with remapped files. We are required to
54 // perform this operation here because we explicitly request that the
55 // compiler instance *not* free these buffers for each invocation of the
56 // parser.
57 if (Invocation.get()) {
58 PreprocessorOptions &PPOpts = Invocation->getPreprocessorOpts();
59 for (PreprocessorOptions::remapped_file_buffer_iterator
60 FB = PPOpts.remapped_file_buffer_begin(),
61 FBEnd = PPOpts.remapped_file_buffer_end();
62 FB != FBEnd;
63 ++FB)
64 delete FB->second;
65 }
Douglas Gregor28233422010-07-27 14:52:07 +000066
67 delete SavedMainFileBuffer;
Douglas Gregor385103b2010-07-30 20:58:08 +000068
69 for (unsigned I = 0, N = Timers.size(); I != N; ++I)
70 delete Timers[I];
Douglas Gregorabc563f2010-07-19 21:46:24 +000071}
72
73void ASTUnit::CleanTemporaryFiles() {
Douglas Gregor313e26c2010-02-18 23:35:40 +000074 for (unsigned I = 0, N = TemporaryFiles.size(); I != N; ++I)
75 TemporaryFiles[I].eraseFromDisk();
Douglas Gregorabc563f2010-07-19 21:46:24 +000076 TemporaryFiles.clear();
Steve Naroffe19944c2009-10-15 22:23:48 +000077}
Argyrios Kyrtzidis0853a022009-06-20 08:08:23 +000078
79namespace {
80
81/// \brief Gathers information from PCHReader that will be used to initialize
82/// a Preprocessor.
Benjamin Kramerbd218282009-11-28 10:07:24 +000083class PCHInfoCollector : public PCHReaderListener {
Argyrios Kyrtzidis0853a022009-06-20 08:08:23 +000084 LangOptions &LangOpt;
85 HeaderSearch &HSI;
86 std::string &TargetTriple;
87 std::string &Predefines;
88 unsigned &Counter;
Mike Stump1eb44332009-09-09 15:08:12 +000089
Argyrios Kyrtzidis0853a022009-06-20 08:08:23 +000090 unsigned NumHeaderInfos;
Mike Stump1eb44332009-09-09 15:08:12 +000091
Argyrios Kyrtzidis0853a022009-06-20 08:08:23 +000092public:
93 PCHInfoCollector(LangOptions &LangOpt, HeaderSearch &HSI,
94 std::string &TargetTriple, std::string &Predefines,
95 unsigned &Counter)
96 : LangOpt(LangOpt), HSI(HSI), TargetTriple(TargetTriple),
97 Predefines(Predefines), Counter(Counter), NumHeaderInfos(0) {}
Mike Stump1eb44332009-09-09 15:08:12 +000098
Argyrios Kyrtzidis0853a022009-06-20 08:08:23 +000099 virtual bool ReadLanguageOptions(const LangOptions &LangOpts) {
100 LangOpt = LangOpts;
101 return false;
102 }
Mike Stump1eb44332009-09-09 15:08:12 +0000103
Daniel Dunbardc3c0d22009-11-11 00:52:11 +0000104 virtual bool ReadTargetTriple(llvm::StringRef Triple) {
Argyrios Kyrtzidis0853a022009-06-20 08:08:23 +0000105 TargetTriple = Triple;
106 return false;
107 }
Mike Stump1eb44332009-09-09 15:08:12 +0000108
Sebastian Redlcb481aa2010-07-14 23:29:55 +0000109 virtual bool ReadPredefinesBuffer(const PCHPredefinesBlocks &Buffers,
Daniel Dunbar7b5a1212009-11-11 05:29:04 +0000110 llvm::StringRef OriginalFileName,
Argyrios Kyrtzidis0853a022009-06-20 08:08:23 +0000111 std::string &SuggestedPredefines) {
Sebastian Redlcb481aa2010-07-14 23:29:55 +0000112 Predefines = Buffers[0].Data;
113 for (unsigned I = 1, N = Buffers.size(); I != N; ++I) {
114 Predefines += Buffers[I].Data;
115 }
Argyrios Kyrtzidis0853a022009-06-20 08:08:23 +0000116 return false;
117 }
Mike Stump1eb44332009-09-09 15:08:12 +0000118
Douglas Gregorec1afbf2010-03-16 19:09:18 +0000119 virtual void ReadHeaderFileInfo(const HeaderFileInfo &HFI, unsigned ID) {
Argyrios Kyrtzidis0853a022009-06-20 08:08:23 +0000120 HSI.setHeaderFileInfoForUID(HFI, NumHeaderInfos++);
121 }
Mike Stump1eb44332009-09-09 15:08:12 +0000122
Argyrios Kyrtzidis0853a022009-06-20 08:08:23 +0000123 virtual void ReadCounter(unsigned Value) {
124 Counter = Value;
125 }
126};
127
Douglas Gregora88084b2010-02-18 18:08:43 +0000128class StoredDiagnosticClient : public DiagnosticClient {
129 llvm::SmallVectorImpl<StoredDiagnostic> &StoredDiags;
130
131public:
132 explicit StoredDiagnosticClient(
133 llvm::SmallVectorImpl<StoredDiagnostic> &StoredDiags)
134 : StoredDiags(StoredDiags) { }
135
136 virtual void HandleDiagnostic(Diagnostic::Level Level,
137 const DiagnosticInfo &Info);
138};
139
140/// \brief RAII object that optionally captures diagnostics, if
141/// there is no diagnostic client to capture them already.
142class CaptureDroppedDiagnostics {
143 Diagnostic &Diags;
144 StoredDiagnosticClient Client;
145 DiagnosticClient *PreviousClient;
146
147public:
148 CaptureDroppedDiagnostics(bool RequestCapture, Diagnostic &Diags,
149 llvm::SmallVectorImpl<StoredDiagnostic> &StoredDiags)
150 : Diags(Diags), Client(StoredDiags), PreviousClient(Diags.getClient())
151 {
152 if (RequestCapture || Diags.getClient() == 0)
153 Diags.setClient(&Client);
154 }
155
156 ~CaptureDroppedDiagnostics() {
157 Diags.setClient(PreviousClient);
158 }
159};
160
Argyrios Kyrtzidis0853a022009-06-20 08:08:23 +0000161} // anonymous namespace
162
Douglas Gregora88084b2010-02-18 18:08:43 +0000163void StoredDiagnosticClient::HandleDiagnostic(Diagnostic::Level Level,
164 const DiagnosticInfo &Info) {
165 StoredDiags.push_back(StoredDiagnostic(Level, Info));
166}
167
Steve Naroff77accc12009-09-03 18:19:54 +0000168const std::string &ASTUnit::getOriginalSourceFileName() {
Daniel Dunbar68d40e22009-12-02 08:44:16 +0000169 return OriginalSourceFile;
Steve Naroff77accc12009-09-03 18:19:54 +0000170}
Argyrios Kyrtzidis0853a022009-06-20 08:08:23 +0000171
Steve Naroffe19944c2009-10-15 22:23:48 +0000172const std::string &ASTUnit::getPCHFileName() {
Daniel Dunbarc7822db2009-12-02 21:47:43 +0000173 assert(isMainFileAST() && "Not an ASTUnit from a PCH file!");
Benjamin Kramer7297c182010-01-30 16:23:25 +0000174 return static_cast<PCHReader *>(Ctx->getExternalSource())->getFileName();
Steve Naroffe19944c2009-10-15 22:23:48 +0000175}
176
Argyrios Kyrtzidis0853a022009-06-20 08:08:23 +0000177ASTUnit *ASTUnit::LoadFromPCHFile(const std::string &Filename,
Douglas Gregor28019772010-04-05 23:52:57 +0000178 llvm::IntrusiveRefCntPtr<Diagnostic> Diags,
Ted Kremenek5cf48762009-10-17 00:34:24 +0000179 bool OnlyLocalDecls,
Douglas Gregor4db64a42010-01-23 00:14:00 +0000180 RemappedFile *RemappedFiles,
Douglas Gregora88084b2010-02-18 18:08:43 +0000181 unsigned NumRemappedFiles,
182 bool CaptureDiagnostics) {
Douglas Gregor3687e9d2010-04-05 21:10:19 +0000183 llvm::OwningPtr<ASTUnit> AST(new ASTUnit(true));
184
Douglas Gregor28019772010-04-05 23:52:57 +0000185 if (!Diags.getPtr()) {
Douglas Gregor3687e9d2010-04-05 21:10:19 +0000186 // No diagnostics engine was provided, so create our own diagnostics object
187 // with the default options.
188 DiagnosticOptions DiagOpts;
Douglas Gregor28019772010-04-05 23:52:57 +0000189 Diags = CompilerInstance::createDiagnostics(DiagOpts, 0, 0);
Douglas Gregor3687e9d2010-04-05 21:10:19 +0000190 }
Douglas Gregorabc563f2010-07-19 21:46:24 +0000191
192 AST->CaptureDiagnostics = CaptureDiagnostics;
Douglas Gregor7d1d49d2009-10-16 20:01:17 +0000193 AST->OnlyLocalDecls = OnlyLocalDecls;
Douglas Gregor28019772010-04-05 23:52:57 +0000194 AST->Diagnostics = Diags;
Douglas Gregor3687e9d2010-04-05 21:10:19 +0000195 AST->FileMgr.reset(new FileManager);
196 AST->SourceMgr.reset(new SourceManager(AST->getDiagnostics()));
Steve Naroff36c44642009-10-19 14:34:22 +0000197 AST->HeaderInfo.reset(new HeaderSearch(AST->getFileManager()));
Argyrios Kyrtzidis0853a022009-06-20 08:08:23 +0000198
Douglas Gregora88084b2010-02-18 18:08:43 +0000199 // If requested, capture diagnostics in the ASTUnit.
Douglas Gregor3687e9d2010-04-05 21:10:19 +0000200 CaptureDroppedDiagnostics Capture(CaptureDiagnostics, AST->getDiagnostics(),
Douglas Gregor405634b2010-04-05 18:10:21 +0000201 AST->StoredDiagnostics);
Douglas Gregora88084b2010-02-18 18:08:43 +0000202
Douglas Gregor4db64a42010-01-23 00:14:00 +0000203 for (unsigned I = 0; I != NumRemappedFiles; ++I) {
204 // Create the file entry for the file that we're mapping from.
205 const FileEntry *FromFile
206 = AST->getFileManager().getVirtualFile(RemappedFiles[I].first,
207 RemappedFiles[I].second->getBufferSize(),
208 0);
209 if (!FromFile) {
Douglas Gregor3687e9d2010-04-05 21:10:19 +0000210 AST->getDiagnostics().Report(diag::err_fe_remap_missing_from_file)
Douglas Gregor4db64a42010-01-23 00:14:00 +0000211 << RemappedFiles[I].first;
Douglas Gregorc8dfe5e2010-02-27 01:32:48 +0000212 delete RemappedFiles[I].second;
Douglas Gregor4db64a42010-01-23 00:14:00 +0000213 continue;
214 }
215
216 // Override the contents of the "from" file with the contents of
217 // the "to" file.
218 AST->getSourceManager().overrideFileContents(FromFile,
219 RemappedFiles[I].second);
220 }
221
Argyrios Kyrtzidis0853a022009-06-20 08:08:23 +0000222 // Gather Info for preprocessor construction later on.
Mike Stump1eb44332009-09-09 15:08:12 +0000223
Argyrios Kyrtzidis0853a022009-06-20 08:08:23 +0000224 LangOptions LangInfo;
225 HeaderSearch &HeaderInfo = *AST->HeaderInfo.get();
226 std::string TargetTriple;
227 std::string Predefines;
228 unsigned Counter;
229
Daniel Dunbarbce6f622009-09-03 05:59:50 +0000230 llvm::OwningPtr<PCHReader> Reader;
Argyrios Kyrtzidis0853a022009-06-20 08:08:23 +0000231 llvm::OwningPtr<ExternalASTSource> Source;
232
Ted Kremenekfc062212009-10-19 21:44:57 +0000233 Reader.reset(new PCHReader(AST->getSourceManager(), AST->getFileManager(),
Douglas Gregor3687e9d2010-04-05 21:10:19 +0000234 AST->getDiagnostics()));
Daniel Dunbarcc318932009-09-03 05:59:35 +0000235 Reader->setListener(new PCHInfoCollector(LangInfo, HeaderInfo, TargetTriple,
236 Predefines, Counter));
237
238 switch (Reader->ReadPCH(Filename)) {
Argyrios Kyrtzidis0853a022009-06-20 08:08:23 +0000239 case PCHReader::Success:
240 break;
Mike Stump1eb44332009-09-09 15:08:12 +0000241
Argyrios Kyrtzidis0853a022009-06-20 08:08:23 +0000242 case PCHReader::Failure:
Argyrios Kyrtzidis106c9982009-06-25 18:22:30 +0000243 case PCHReader::IgnorePCH:
Douglas Gregor3687e9d2010-04-05 21:10:19 +0000244 AST->getDiagnostics().Report(diag::err_fe_unable_to_load_pch);
Argyrios Kyrtzidis0853a022009-06-20 08:08:23 +0000245 return NULL;
Argyrios Kyrtzidis0853a022009-06-20 08:08:23 +0000246 }
Mike Stump1eb44332009-09-09 15:08:12 +0000247
Daniel Dunbar68d40e22009-12-02 08:44:16 +0000248 AST->OriginalSourceFile = Reader->getOriginalSourceFile();
249
Argyrios Kyrtzidis0853a022009-06-20 08:08:23 +0000250 // PCH loaded successfully. Now create the preprocessor.
Mike Stump1eb44332009-09-09 15:08:12 +0000251
Argyrios Kyrtzidis0853a022009-06-20 08:08:23 +0000252 // Get information about the target being compiled for.
Daniel Dunbard58c03f2009-11-15 06:48:46 +0000253 //
254 // FIXME: This is broken, we should store the TargetOptions in the PCH.
255 TargetOptions TargetOpts;
256 TargetOpts.ABI = "";
Charles Davis98b7c5c2010-06-11 01:06:47 +0000257 TargetOpts.CXXABI = "itanium";
Daniel Dunbard58c03f2009-11-15 06:48:46 +0000258 TargetOpts.CPU = "";
259 TargetOpts.Features.clear();
260 TargetOpts.Triple = TargetTriple;
Douglas Gregor3687e9d2010-04-05 21:10:19 +0000261 AST->Target.reset(TargetInfo::CreateTargetInfo(AST->getDiagnostics(),
262 TargetOpts));
263 AST->PP.reset(new Preprocessor(AST->getDiagnostics(), LangInfo,
264 *AST->Target.get(),
Daniel Dunbar31b87d82009-09-21 03:03:39 +0000265 AST->getSourceManager(), HeaderInfo));
Argyrios Kyrtzidis0853a022009-06-20 08:08:23 +0000266 Preprocessor &PP = *AST->PP.get();
267
Daniel Dunbard5b61262009-09-21 03:03:47 +0000268 PP.setPredefines(Reader->getSuggestedPredefines());
Argyrios Kyrtzidis0853a022009-06-20 08:08:23 +0000269 PP.setCounterValue(Counter);
Daniel Dunbarcc318932009-09-03 05:59:35 +0000270 Reader->setPreprocessor(PP);
Mike Stump1eb44332009-09-09 15:08:12 +0000271
Argyrios Kyrtzidis0853a022009-06-20 08:08:23 +0000272 // Create and initialize the ASTContext.
273
274 AST->Ctx.reset(new ASTContext(LangInfo,
Daniel Dunbar31b87d82009-09-21 03:03:39 +0000275 AST->getSourceManager(),
Argyrios Kyrtzidis0853a022009-06-20 08:08:23 +0000276 *AST->Target.get(),
277 PP.getIdentifierTable(),
278 PP.getSelectorTable(),
279 PP.getBuiltinInfo(),
Argyrios Kyrtzidis0853a022009-06-20 08:08:23 +0000280 /* size_reserve = */0));
281 ASTContext &Context = *AST->Ctx.get();
Mike Stump1eb44332009-09-09 15:08:12 +0000282
Daniel Dunbarcc318932009-09-03 05:59:35 +0000283 Reader->InitializeContext(Context);
Mike Stump1eb44332009-09-09 15:08:12 +0000284
Argyrios Kyrtzidis0853a022009-06-20 08:08:23 +0000285 // Attach the PCH reader to the AST context as an external AST
286 // source, so that declarations will be deserialized from the
287 // PCH file as needed.
Daniel Dunbarcc318932009-09-03 05:59:35 +0000288 Source.reset(Reader.take());
Argyrios Kyrtzidis0853a022009-06-20 08:08:23 +0000289 Context.setExternalSource(Source);
290
Mike Stump1eb44332009-09-09 15:08:12 +0000291 return AST.take();
Argyrios Kyrtzidis0853a022009-06-20 08:08:23 +0000292}
Daniel Dunbar521bf9c2009-12-01 09:51:01 +0000293
294namespace {
295
Daniel Dunbarf772d1e2009-12-04 08:17:33 +0000296class TopLevelDeclTrackerConsumer : public ASTConsumer {
297 ASTUnit &Unit;
298
299public:
300 TopLevelDeclTrackerConsumer(ASTUnit &_Unit) : Unit(_Unit) {}
301
302 void HandleTopLevelDecl(DeclGroupRef D) {
Ted Kremenekda5a4282010-05-03 20:16:35 +0000303 for (DeclGroupRef::iterator it = D.begin(), ie = D.end(); it != ie; ++it) {
304 Decl *D = *it;
305 // FIXME: Currently ObjC method declarations are incorrectly being
306 // reported as top-level declarations, even though their DeclContext
307 // is the containing ObjC @interface/@implementation. This is a
308 // fundamental problem in the parser right now.
309 if (isa<ObjCMethodDecl>(D))
310 continue;
311 Unit.getTopLevelDecls().push_back(D);
312 }
Daniel Dunbarf772d1e2009-12-04 08:17:33 +0000313 }
314};
315
316class TopLevelDeclTrackerAction : public ASTFrontendAction {
317public:
318 ASTUnit &Unit;
319
Daniel Dunbar521bf9c2009-12-01 09:51:01 +0000320 virtual ASTConsumer *CreateASTConsumer(CompilerInstance &CI,
321 llvm::StringRef InFile) {
Daniel Dunbarf772d1e2009-12-04 08:17:33 +0000322 return new TopLevelDeclTrackerConsumer(Unit);
Daniel Dunbar521bf9c2009-12-01 09:51:01 +0000323 }
324
325public:
Daniel Dunbarf772d1e2009-12-04 08:17:33 +0000326 TopLevelDeclTrackerAction(ASTUnit &_Unit) : Unit(_Unit) {}
327
Daniel Dunbar521bf9c2009-12-01 09:51:01 +0000328 virtual bool hasCodeCompletionSupport() const { return false; }
329};
330
331}
332
Douglas Gregorabc563f2010-07-19 21:46:24 +0000333/// Parse the source file into a translation unit using the given compiler
334/// invocation, replacing the current translation unit.
335///
336/// \returns True if a failure occurred that causes the ASTUnit not to
337/// contain any translation-unit information, false otherwise.
Douglas Gregor754f3492010-07-24 00:38:13 +0000338bool ASTUnit::Parse(llvm::MemoryBuffer *OverrideMainBuffer) {
Douglas Gregor28233422010-07-27 14:52:07 +0000339 delete SavedMainFileBuffer;
340 SavedMainFileBuffer = 0;
341
Douglas Gregorabc563f2010-07-19 21:46:24 +0000342 if (!Invocation.get())
343 return true;
344
Daniel Dunbar521bf9c2009-12-01 09:51:01 +0000345 // Create the compiler instance to use for building the AST.
Daniel Dunbarcb6dda12009-12-02 08:43:56 +0000346 CompilerInstance Clang;
Douglas Gregorabc563f2010-07-19 21:46:24 +0000347 Clang.setInvocation(Invocation.take());
348 OriginalSourceFile = Clang.getFrontendOpts().Inputs[0].second;
349
350 // Set up diagnostics.
351 Clang.setDiagnostics(&getDiagnostics());
352 Clang.setDiagnosticClient(getDiagnostics().getClient());
Douglas Gregor3687e9d2010-04-05 21:10:19 +0000353
Daniel Dunbar521bf9c2009-12-01 09:51:01 +0000354 // Create the target instance.
355 Clang.setTarget(TargetInfo::CreateTargetInfo(Clang.getDiagnostics(),
356 Clang.getTargetOpts()));
Douglas Gregora88084b2010-02-18 18:08:43 +0000357 if (!Clang.hasTarget()) {
Douglas Gregora88084b2010-02-18 18:08:43 +0000358 Clang.takeDiagnosticClient();
Douglas Gregorabc563f2010-07-19 21:46:24 +0000359 return true;
Douglas Gregora88084b2010-02-18 18:08:43 +0000360 }
Douglas Gregorabc563f2010-07-19 21:46:24 +0000361
Daniel Dunbar521bf9c2009-12-01 09:51:01 +0000362 // Inform the target of the language options.
363 //
364 // FIXME: We shouldn't need to do this, the target should be immutable once
365 // created. This complexity should be lifted elsewhere.
366 Clang.getTarget().setForcedLangOptions(Clang.getLangOpts());
Douglas Gregorabc563f2010-07-19 21:46:24 +0000367
Daniel Dunbar521bf9c2009-12-01 09:51:01 +0000368 assert(Clang.getFrontendOpts().Inputs.size() == 1 &&
369 "Invocation must have exactly one source file!");
Daniel Dunbarc34ce3f2010-06-07 23:22:09 +0000370 assert(Clang.getFrontendOpts().Inputs[0].first != IK_AST &&
Daniel Dunbar521bf9c2009-12-01 09:51:01 +0000371 "FIXME: AST inputs not yet supported here!");
Daniel Dunbarfaddc3e2010-06-07 23:26:47 +0000372 assert(Clang.getFrontendOpts().Inputs[0].first != IK_LLVM_IR &&
373 "IR inputs not support here!");
Daniel Dunbar521bf9c2009-12-01 09:51:01 +0000374
Douglas Gregorabc563f2010-07-19 21:46:24 +0000375 // Configure the various subsystems.
376 // FIXME: Should we retain the previous file manager?
377 FileMgr.reset(new FileManager);
378 SourceMgr.reset(new SourceManager(getDiagnostics()));
379 Ctx.reset();
380 PP.reset();
381
382 // Clear out old caches and data.
383 TopLevelDecls.clear();
Douglas Gregorabc563f2010-07-19 21:46:24 +0000384 CleanTemporaryFiles();
385 PreprocessedEntitiesByFile.clear();
Douglas Gregorc0659ec2010-08-02 20:51:39 +0000386
387 if (!OverrideMainBuffer)
388 StoredDiagnostics.clear();
Douglas Gregorabc563f2010-07-19 21:46:24 +0000389
Douglas Gregora88084b2010-02-18 18:08:43 +0000390 // Capture any diagnostics that would otherwise be dropped.
391 CaptureDroppedDiagnostics Capture(CaptureDiagnostics,
392 Clang.getDiagnostics(),
Douglas Gregorabc563f2010-07-19 21:46:24 +0000393 StoredDiagnostics);
394
Daniel Dunbar521bf9c2009-12-01 09:51:01 +0000395 // Create a file manager object to provide access to and cache the filesystem.
Douglas Gregorabc563f2010-07-19 21:46:24 +0000396 Clang.setFileManager(&getFileManager());
397
Daniel Dunbar521bf9c2009-12-01 09:51:01 +0000398 // Create the source manager.
Douglas Gregorabc563f2010-07-19 21:46:24 +0000399 Clang.setSourceManager(&getSourceManager());
400
Douglas Gregorf4f6c9d2010-07-26 21:36:20 +0000401 // If the main file has been overridden due to the use of a preamble,
402 // make that override happen and introduce the preamble.
403 PreprocessorOptions &PreprocessorOpts = Clang.getPreprocessorOpts();
404 if (OverrideMainBuffer) {
405 PreprocessorOpts.addRemappedFile(OriginalSourceFile, OverrideMainBuffer);
406 PreprocessorOpts.PrecompiledPreambleBytes.first = Preamble.size();
407 PreprocessorOpts.PrecompiledPreambleBytes.second
408 = PreambleEndsAtStartOfLine;
Douglas Gregor385103b2010-07-30 20:58:08 +0000409 PreprocessorOpts.ImplicitPCHInclude = PreambleFile;
Douglas Gregorfae3b2f2010-07-27 00:27:13 +0000410 PreprocessorOpts.DisablePCHValidation = true;
Douglas Gregor28233422010-07-27 14:52:07 +0000411
412 // Keep track of the override buffer;
413 SavedMainFileBuffer = OverrideMainBuffer;
Douglas Gregorc0659ec2010-08-02 20:51:39 +0000414
415 // The stored diagnostic has the old source manager in it; update
416 // the locations to refer into the new source manager. Since we've
417 // been careful to make sure that the source manager's state
418 // before and after are identical, so that we can reuse the source
419 // location itself.
420 for (unsigned I = 0, N = StoredDiagnostics.size(); I != N; ++I) {
421 FullSourceLoc Loc(StoredDiagnostics[I].getLocation(),
422 getSourceManager());
423 StoredDiagnostics[I].setLocation(Loc);
424 }
Douglas Gregorf4f6c9d2010-07-26 21:36:20 +0000425 }
426
Douglas Gregorabc563f2010-07-19 21:46:24 +0000427 llvm::OwningPtr<TopLevelDeclTrackerAction> Act;
428 Act.reset(new TopLevelDeclTrackerAction(*this));
Daniel Dunbarf772d1e2009-12-04 08:17:33 +0000429 if (!Act->BeginSourceFile(Clang, Clang.getFrontendOpts().Inputs[0].second,
Daniel Dunbard3598a62010-06-07 23:23:06 +0000430 Clang.getFrontendOpts().Inputs[0].first))
Daniel Dunbar521bf9c2009-12-01 09:51:01 +0000431 goto error;
Douglas Gregorabc563f2010-07-19 21:46:24 +0000432
Daniel Dunbarf772d1e2009-12-04 08:17:33 +0000433 Act->Execute();
Douglas Gregorabc563f2010-07-19 21:46:24 +0000434
Daniel Dunbar64a32ba2009-12-01 21:57:33 +0000435 // Steal the created target, context, and preprocessor, and take back the
436 // source and file managers.
Douglas Gregorabc563f2010-07-19 21:46:24 +0000437 Ctx.reset(Clang.takeASTContext());
438 PP.reset(Clang.takePreprocessor());
Daniel Dunbar521bf9c2009-12-01 09:51:01 +0000439 Clang.takeSourceManager();
440 Clang.takeFileManager();
Douglas Gregorabc563f2010-07-19 21:46:24 +0000441 Target.reset(Clang.takeTarget());
442
Daniel Dunbarf772d1e2009-12-04 08:17:33 +0000443 Act->EndSourceFile();
Douglas Gregorf4f6c9d2010-07-26 21:36:20 +0000444
445 // Remove the overridden buffer we used for the preamble.
Douglas Gregorc0659ec2010-08-02 20:51:39 +0000446 if (OverrideMainBuffer)
Douglas Gregorf4f6c9d2010-07-26 21:36:20 +0000447 PreprocessorOpts.eraseRemappedFile(
448 PreprocessorOpts.remapped_file_buffer_end() - 1);
Douglas Gregorabc563f2010-07-19 21:46:24 +0000449
Daniel Dunbar521bf9c2009-12-01 09:51:01 +0000450 Clang.takeDiagnosticClient();
Douglas Gregorabc563f2010-07-19 21:46:24 +0000451
452 Invocation.reset(Clang.takeInvocation());
453 return false;
454
Daniel Dunbar521bf9c2009-12-01 09:51:01 +0000455error:
Douglas Gregorf4f6c9d2010-07-26 21:36:20 +0000456 // Remove the overridden buffer we used for the preamble.
Douglas Gregorfae3b2f2010-07-27 00:27:13 +0000457 if (OverrideMainBuffer) {
Douglas Gregorf4f6c9d2010-07-26 21:36:20 +0000458 PreprocessorOpts.eraseRemappedFile(
459 PreprocessorOpts.remapped_file_buffer_end() - 1);
Douglas Gregorfae3b2f2010-07-27 00:27:13 +0000460 PreprocessorOpts.DisablePCHValidation = true;
461 }
Douglas Gregorf4f6c9d2010-07-26 21:36:20 +0000462
Daniel Dunbar521bf9c2009-12-01 09:51:01 +0000463 Clang.takeSourceManager();
464 Clang.takeFileManager();
465 Clang.takeDiagnosticClient();
Douglas Gregorabc563f2010-07-19 21:46:24 +0000466 Invocation.reset(Clang.takeInvocation());
467 return true;
468}
469
Douglas Gregor44c181a2010-07-23 00:33:23 +0000470/// \brief Simple function to retrieve a path for a preamble precompiled header.
471static std::string GetPreamblePCHPath() {
472 // FIXME: This is lame; sys::Path should provide this function (in particular,
473 // it should know how to find the temporary files dir).
474 // FIXME: This is really lame. I copied this code from the Driver!
475 std::string Error;
476 const char *TmpDir = ::getenv("TMPDIR");
477 if (!TmpDir)
478 TmpDir = ::getenv("TEMP");
479 if (!TmpDir)
480 TmpDir = ::getenv("TMP");
481 if (!TmpDir)
482 TmpDir = "/tmp";
483 llvm::sys::Path P(TmpDir);
484 P.appendComponent("preamble");
485 if (P.createTemporaryFileOnDisk())
486 return std::string();
487
488 P.appendSuffix("pch");
489 return P.str();
490}
491
Douglas Gregorf4f6c9d2010-07-26 21:36:20 +0000492/// \brief Compute the preamble for the main file, providing the source buffer
493/// that corresponds to the main file along with a pair (bytes, start-of-line)
494/// that describes the preamble.
495std::pair<llvm::MemoryBuffer *, std::pair<unsigned, bool> >
Douglas Gregor175c4a92010-07-23 23:58:40 +0000496ASTUnit::ComputePreamble(CompilerInvocation &Invocation, bool &CreatedBuffer) {
497 FrontendOptions &FrontendOpts = Invocation.getFrontendOpts();
Douglas Gregor44c181a2010-07-23 00:33:23 +0000498 PreprocessorOptions &PreprocessorOpts
Douglas Gregor175c4a92010-07-23 23:58:40 +0000499 = Invocation.getPreprocessorOpts();
500 CreatedBuffer = false;
501
Douglas Gregor44c181a2010-07-23 00:33:23 +0000502 // Try to determine if the main file has been remapped, either from the
503 // command line (to another file) or directly through the compiler invocation
504 // (to a memory buffer).
Douglas Gregor175c4a92010-07-23 23:58:40 +0000505 llvm::MemoryBuffer *Buffer = 0;
Douglas Gregor44c181a2010-07-23 00:33:23 +0000506 llvm::sys::PathWithStatus MainFilePath(FrontendOpts.Inputs[0].second);
507 if (const llvm::sys::FileStatus *MainFileStatus = MainFilePath.getFileStatus()) {
508 // Check whether there is a file-file remapping of the main file
509 for (PreprocessorOptions::remapped_file_iterator
Douglas Gregor175c4a92010-07-23 23:58:40 +0000510 M = PreprocessorOpts.remapped_file_begin(),
511 E = PreprocessorOpts.remapped_file_end();
Douglas Gregor44c181a2010-07-23 00:33:23 +0000512 M != E;
513 ++M) {
514 llvm::sys::PathWithStatus MPath(M->first);
515 if (const llvm::sys::FileStatus *MStatus = MPath.getFileStatus()) {
516 if (MainFileStatus->uniqueID == MStatus->uniqueID) {
517 // We found a remapping. Try to load the resulting, remapped source.
Douglas Gregor175c4a92010-07-23 23:58:40 +0000518 if (CreatedBuffer) {
Douglas Gregor44c181a2010-07-23 00:33:23 +0000519 delete Buffer;
Douglas Gregor175c4a92010-07-23 23:58:40 +0000520 CreatedBuffer = false;
521 }
522
Douglas Gregor44c181a2010-07-23 00:33:23 +0000523 Buffer = llvm::MemoryBuffer::getFile(M->second);
524 if (!Buffer)
Douglas Gregorf4f6c9d2010-07-26 21:36:20 +0000525 return std::make_pair((llvm::MemoryBuffer*)0,
526 std::make_pair(0, true));
Douglas Gregor175c4a92010-07-23 23:58:40 +0000527 CreatedBuffer = true;
Douglas Gregor44c181a2010-07-23 00:33:23 +0000528
Douglas Gregor175c4a92010-07-23 23:58:40 +0000529 // Remove this remapping. We've captured the buffer already.
Douglas Gregor44c181a2010-07-23 00:33:23 +0000530 M = PreprocessorOpts.eraseRemappedFile(M);
531 E = PreprocessorOpts.remapped_file_end();
532 }
533 }
534 }
535
536 // Check whether there is a file-buffer remapping. It supercedes the
537 // file-file remapping.
538 for (PreprocessorOptions::remapped_file_buffer_iterator
539 M = PreprocessorOpts.remapped_file_buffer_begin(),
540 E = PreprocessorOpts.remapped_file_buffer_end();
541 M != E;
542 ++M) {
543 llvm::sys::PathWithStatus MPath(M->first);
544 if (const llvm::sys::FileStatus *MStatus = MPath.getFileStatus()) {
545 if (MainFileStatus->uniqueID == MStatus->uniqueID) {
546 // We found a remapping.
Douglas Gregor175c4a92010-07-23 23:58:40 +0000547 if (CreatedBuffer) {
Douglas Gregor44c181a2010-07-23 00:33:23 +0000548 delete Buffer;
Douglas Gregor175c4a92010-07-23 23:58:40 +0000549 CreatedBuffer = false;
550 }
Douglas Gregor44c181a2010-07-23 00:33:23 +0000551
Douglas Gregor175c4a92010-07-23 23:58:40 +0000552 Buffer = const_cast<llvm::MemoryBuffer *>(M->second);
553
554 // Remove this remapping. We've captured the buffer already.
Douglas Gregor44c181a2010-07-23 00:33:23 +0000555 M = PreprocessorOpts.eraseRemappedFile(M);
556 E = PreprocessorOpts.remapped_file_buffer_end();
557 }
558 }
Douglas Gregor175c4a92010-07-23 23:58:40 +0000559 }
Douglas Gregor44c181a2010-07-23 00:33:23 +0000560 }
561
562 // If the main source file was not remapped, load it now.
563 if (!Buffer) {
564 Buffer = llvm::MemoryBuffer::getFile(FrontendOpts.Inputs[0].second);
565 if (!Buffer)
Douglas Gregorf4f6c9d2010-07-26 21:36:20 +0000566 return std::make_pair((llvm::MemoryBuffer*)0, std::make_pair(0, true));
Douglas Gregor175c4a92010-07-23 23:58:40 +0000567
568 CreatedBuffer = true;
Douglas Gregor44c181a2010-07-23 00:33:23 +0000569 }
570
Douglas Gregor175c4a92010-07-23 23:58:40 +0000571 return std::make_pair(Buffer, Lexer::ComputePreamble(Buffer));
572}
573
Douglas Gregor754f3492010-07-24 00:38:13 +0000574static llvm::MemoryBuffer *CreatePaddedMainFileBuffer(llvm::MemoryBuffer *Old,
575 bool DeleteOld,
576 unsigned NewSize,
577 llvm::StringRef NewName) {
578 llvm::MemoryBuffer *Result
579 = llvm::MemoryBuffer::getNewUninitMemBuffer(NewSize, NewName);
580 memcpy(const_cast<char*>(Result->getBufferStart()),
581 Old->getBufferStart(), Old->getBufferSize());
582 memset(const_cast<char*>(Result->getBufferStart()) + Old->getBufferSize(),
Douglas Gregorf4f6c9d2010-07-26 21:36:20 +0000583 ' ', NewSize - Old->getBufferSize() - 1);
584 const_cast<char*>(Result->getBufferEnd())[-1] = '\n';
Douglas Gregor754f3492010-07-24 00:38:13 +0000585
586 if (DeleteOld)
587 delete Old;
588
589 return Result;
590}
591
Douglas Gregor175c4a92010-07-23 23:58:40 +0000592/// \brief Attempt to build or re-use a precompiled preamble when (re-)parsing
593/// the source file.
594///
595/// This routine will compute the preamble of the main source file. If a
596/// non-trivial preamble is found, it will precompile that preamble into a
597/// precompiled header so that the precompiled preamble can be used to reduce
598/// reparsing time. If a precompiled preamble has already been constructed,
599/// this routine will determine if it is still valid and, if so, avoid
600/// rebuilding the precompiled preamble.
601///
Douglas Gregor754f3492010-07-24 00:38:13 +0000602/// \returns If the precompiled preamble can be used, returns a newly-allocated
603/// buffer that should be used in place of the main file when doing so.
604/// Otherwise, returns a NULL pointer.
605llvm::MemoryBuffer *ASTUnit::BuildPrecompiledPreamble() {
Douglas Gregor175c4a92010-07-23 23:58:40 +0000606 CompilerInvocation PreambleInvocation(*Invocation);
607 FrontendOptions &FrontendOpts = PreambleInvocation.getFrontendOpts();
608 PreprocessorOptions &PreprocessorOpts
609 = PreambleInvocation.getPreprocessorOpts();
610
611 bool CreatedPreambleBuffer = false;
Douglas Gregorf4f6c9d2010-07-26 21:36:20 +0000612 std::pair<llvm::MemoryBuffer *, std::pair<unsigned, bool> > NewPreamble
Douglas Gregor175c4a92010-07-23 23:58:40 +0000613 = ComputePreamble(PreambleInvocation, CreatedPreambleBuffer);
614
Douglas Gregorf4f6c9d2010-07-26 21:36:20 +0000615 if (!NewPreamble.second.first) {
Douglas Gregor175c4a92010-07-23 23:58:40 +0000616 // We couldn't find a preamble in the main source. Clear out the current
617 // preamble, if we have one. It's obviously no good any more.
618 Preamble.clear();
619 if (!PreambleFile.empty()) {
Douglas Gregor385103b2010-07-30 20:58:08 +0000620 llvm::sys::Path(PreambleFile).eraseFromDisk();
Douglas Gregor175c4a92010-07-23 23:58:40 +0000621 PreambleFile.clear();
622 }
623 if (CreatedPreambleBuffer)
624 delete NewPreamble.first;
625
Douglas Gregor754f3492010-07-24 00:38:13 +0000626 return 0;
Douglas Gregor175c4a92010-07-23 23:58:40 +0000627 }
628
629 if (!Preamble.empty()) {
630 // We've previously computed a preamble. Check whether we have the same
631 // preamble now that we did before, and that there's enough space in
632 // the main-file buffer within the precompiled preamble to fit the
633 // new main file.
Douglas Gregorf4f6c9d2010-07-26 21:36:20 +0000634 if (Preamble.size() == NewPreamble.second.first &&
635 PreambleEndsAtStartOfLine == NewPreamble.second.second &&
Douglas Gregor592508e2010-07-24 00:42:07 +0000636 NewPreamble.first->getBufferSize() < PreambleReservedSize-2 &&
Douglas Gregor175c4a92010-07-23 23:58:40 +0000637 memcmp(&Preamble[0], NewPreamble.first->getBufferStart(),
Douglas Gregorf4f6c9d2010-07-26 21:36:20 +0000638 NewPreamble.second.first) == 0) {
Douglas Gregor175c4a92010-07-23 23:58:40 +0000639 // The preamble has not changed. We may be able to re-use the precompiled
640 // preamble.
Douglas Gregorc0659ec2010-08-02 20:51:39 +0000641
Douglas Gregorcc5888d2010-07-31 00:40:00 +0000642 // Check that none of the files used by the preamble have changed.
643 bool AnyFileChanged = false;
644
645 // First, make a record of those files that have been overridden via
646 // remapping or unsaved_files.
647 llvm::StringMap<std::pair<off_t, time_t> > OverriddenFiles;
648 for (PreprocessorOptions::remapped_file_iterator
649 R = PreprocessorOpts.remapped_file_begin(),
650 REnd = PreprocessorOpts.remapped_file_end();
651 !AnyFileChanged && R != REnd;
652 ++R) {
653 struct stat StatBuf;
654 if (stat(R->second.c_str(), &StatBuf)) {
655 // If we can't stat the file we're remapping to, assume that something
656 // horrible happened.
657 AnyFileChanged = true;
658 break;
659 }
Douglas Gregor754f3492010-07-24 00:38:13 +0000660
Douglas Gregorcc5888d2010-07-31 00:40:00 +0000661 OverriddenFiles[R->first] = std::make_pair(StatBuf.st_size,
662 StatBuf.st_mtime);
663 }
664 for (PreprocessorOptions::remapped_file_buffer_iterator
665 R = PreprocessorOpts.remapped_file_buffer_begin(),
666 REnd = PreprocessorOpts.remapped_file_buffer_end();
667 !AnyFileChanged && R != REnd;
668 ++R) {
669 // FIXME: Should we actually compare the contents of file->buffer
670 // remappings?
671 OverriddenFiles[R->first] = std::make_pair(R->second->getBufferSize(),
672 0);
673 }
674
675 // Check whether anything has changed.
676 for (llvm::StringMap<std::pair<off_t, time_t> >::iterator
677 F = FilesInPreamble.begin(), FEnd = FilesInPreamble.end();
678 !AnyFileChanged && F != FEnd;
679 ++F) {
680 llvm::StringMap<std::pair<off_t, time_t> >::iterator Overridden
681 = OverriddenFiles.find(F->first());
682 if (Overridden != OverriddenFiles.end()) {
683 // This file was remapped; check whether the newly-mapped file
684 // matches up with the previous mapping.
685 if (Overridden->second != F->second)
686 AnyFileChanged = true;
687 continue;
688 }
689
690 // The file was not remapped; check whether it has changed on disk.
691 struct stat StatBuf;
692 if (stat(F->first(), &StatBuf)) {
693 // If we can't stat the file, assume that something horrible happened.
694 AnyFileChanged = true;
695 } else if (StatBuf.st_size != F->second.first ||
696 StatBuf.st_mtime != F->second.second)
697 AnyFileChanged = true;
698 }
699
700 if (!AnyFileChanged) {
Douglas Gregorc0659ec2010-08-02 20:51:39 +0000701 // Okay! We can re-use the precompiled preamble.
702
703 // Set the state of the diagnostic object to mimic its state
704 // after parsing the preamble.
705 getDiagnostics().Reset();
706 getDiagnostics().setNumWarnings(NumWarningsInPreamble);
707 if (StoredDiagnostics.size() > NumStoredDiagnosticsInPreamble)
708 StoredDiagnostics.erase(
709 StoredDiagnostics.begin() + NumStoredDiagnosticsInPreamble,
710 StoredDiagnostics.end());
711
712 // Create a version of the main file buffer that is padded to
713 // buffer size we reserved when creating the preamble.
Douglas Gregorcc5888d2010-07-31 00:40:00 +0000714 return CreatePaddedMainFileBuffer(NewPreamble.first,
715 CreatedPreambleBuffer,
716 PreambleReservedSize,
717 FrontendOpts.Inputs[0].second);
718 }
Douglas Gregor175c4a92010-07-23 23:58:40 +0000719 }
720
721 // We can't reuse the previously-computed preamble. Build a new one.
722 Preamble.clear();
Douglas Gregor385103b2010-07-30 20:58:08 +0000723 llvm::sys::Path(PreambleFile).eraseFromDisk();
Douglas Gregor175c4a92010-07-23 23:58:40 +0000724 }
725
726 // We did not previously compute a preamble, or it can't be reused anyway.
Douglas Gregor385103b2010-07-30 20:58:08 +0000727 llvm::Timer *PreambleTimer = 0;
728 if (TimerGroup.get()) {
729 PreambleTimer = new llvm::Timer("Precompiling preamble", *TimerGroup);
730 PreambleTimer->startTimer();
731 Timers.push_back(PreambleTimer);
732 }
Douglas Gregor44c181a2010-07-23 00:33:23 +0000733
734 // Create a new buffer that stores the preamble. The buffer also contains
735 // extra space for the original contents of the file (which will be present
736 // when we actually parse the file) along with more room in case the file
Douglas Gregor175c4a92010-07-23 23:58:40 +0000737 // grows.
738 PreambleReservedSize = NewPreamble.first->getBufferSize();
739 if (PreambleReservedSize < 4096)
Douglas Gregorf4f6c9d2010-07-26 21:36:20 +0000740 PreambleReservedSize = 8191;
Douglas Gregor44c181a2010-07-23 00:33:23 +0000741 else
Douglas Gregor175c4a92010-07-23 23:58:40 +0000742 PreambleReservedSize *= 2;
743
Douglas Gregorc0659ec2010-08-02 20:51:39 +0000744 // Save the preamble text for later; we'll need to compare against it for
745 // subsequent reparses.
746 Preamble.assign(NewPreamble.first->getBufferStart(),
747 NewPreamble.first->getBufferStart()
748 + NewPreamble.second.first);
749 PreambleEndsAtStartOfLine = NewPreamble.second.second;
750
Douglas Gregor44c181a2010-07-23 00:33:23 +0000751 llvm::MemoryBuffer *PreambleBuffer
Douglas Gregor175c4a92010-07-23 23:58:40 +0000752 = llvm::MemoryBuffer::getNewUninitMemBuffer(PreambleReservedSize,
Douglas Gregor44c181a2010-07-23 00:33:23 +0000753 FrontendOpts.Inputs[0].second);
754 memcpy(const_cast<char*>(PreambleBuffer->getBufferStart()),
Douglas Gregor175c4a92010-07-23 23:58:40 +0000755 NewPreamble.first->getBufferStart(), Preamble.size());
756 memset(const_cast<char*>(PreambleBuffer->getBufferStart()) + Preamble.size(),
Douglas Gregorf4f6c9d2010-07-26 21:36:20 +0000757 ' ', PreambleReservedSize - Preamble.size() - 1);
758 const_cast<char*>(PreambleBuffer->getBufferEnd())[-1] = '\n';
Douglas Gregor44c181a2010-07-23 00:33:23 +0000759
760 // Remap the main source file to the preamble buffer.
Douglas Gregor175c4a92010-07-23 23:58:40 +0000761 llvm::sys::PathWithStatus MainFilePath(FrontendOpts.Inputs[0].second);
Douglas Gregor44c181a2010-07-23 00:33:23 +0000762 PreprocessorOpts.addRemappedFile(MainFilePath.str(), PreambleBuffer);
763
764 // Tell the compiler invocation to generate a temporary precompiled header.
765 FrontendOpts.ProgramAction = frontend::GeneratePCH;
766 // FIXME: Set ChainedPCH, once it is ready.
767 // FIXME: Generate the precompiled header into memory?
Douglas Gregor385103b2010-07-30 20:58:08 +0000768 FrontendOpts.OutputFile = GetPreamblePCHPath();
Douglas Gregor44c181a2010-07-23 00:33:23 +0000769
770 // Create the compiler instance to use for building the precompiled preamble.
771 CompilerInstance Clang;
772 Clang.setInvocation(&PreambleInvocation);
773 OriginalSourceFile = Clang.getFrontendOpts().Inputs[0].second;
774
775 // Set up diagnostics.
776 Clang.setDiagnostics(&getDiagnostics());
777 Clang.setDiagnosticClient(getDiagnostics().getClient());
778
779 // Create the target instance.
780 Clang.setTarget(TargetInfo::CreateTargetInfo(Clang.getDiagnostics(),
781 Clang.getTargetOpts()));
782 if (!Clang.hasTarget()) {
783 Clang.takeDiagnosticClient();
Douglas Gregor175c4a92010-07-23 23:58:40 +0000784 llvm::sys::Path(FrontendOpts.OutputFile).eraseFromDisk();
785 Preamble.clear();
786 if (CreatedPreambleBuffer)
787 delete NewPreamble.first;
Douglas Gregor385103b2010-07-30 20:58:08 +0000788 if (PreambleTimer)
789 PreambleTimer->stopTimer();
Douglas Gregor175c4a92010-07-23 23:58:40 +0000790
Douglas Gregor754f3492010-07-24 00:38:13 +0000791 return 0;
Douglas Gregor44c181a2010-07-23 00:33:23 +0000792 }
793
794 // Inform the target of the language options.
795 //
796 // FIXME: We shouldn't need to do this, the target should be immutable once
797 // created. This complexity should be lifted elsewhere.
798 Clang.getTarget().setForcedLangOptions(Clang.getLangOpts());
799
800 assert(Clang.getFrontendOpts().Inputs.size() == 1 &&
801 "Invocation must have exactly one source file!");
802 assert(Clang.getFrontendOpts().Inputs[0].first != IK_AST &&
803 "FIXME: AST inputs not yet supported here!");
804 assert(Clang.getFrontendOpts().Inputs[0].first != IK_LLVM_IR &&
805 "IR inputs not support here!");
806
807 // Clear out old caches and data.
808 StoredDiagnostics.clear();
809
810 // Capture any diagnostics that would otherwise be dropped.
811 CaptureDroppedDiagnostics Capture(CaptureDiagnostics,
Douglas Gregorc0659ec2010-08-02 20:51:39 +0000812 getDiagnostics(),
Douglas Gregor44c181a2010-07-23 00:33:23 +0000813 StoredDiagnostics);
814
815 // Create a file manager object to provide access to and cache the filesystem.
816 Clang.setFileManager(new FileManager);
817
818 // Create the source manager.
819 Clang.setSourceManager(new SourceManager(getDiagnostics()));
820
821 // FIXME: Eventually, we'll have to track top-level declarations here, too.
822 llvm::OwningPtr<GeneratePCHAction> Act;
823 Act.reset(new GeneratePCHAction);
824 if (!Act->BeginSourceFile(Clang, Clang.getFrontendOpts().Inputs[0].second,
825 Clang.getFrontendOpts().Inputs[0].first)) {
826 Clang.takeDiagnosticClient();
827 Clang.takeInvocation();
Douglas Gregor175c4a92010-07-23 23:58:40 +0000828 llvm::sys::Path(FrontendOpts.OutputFile).eraseFromDisk();
829 Preamble.clear();
830 if (CreatedPreambleBuffer)
831 delete NewPreamble.first;
Douglas Gregor385103b2010-07-30 20:58:08 +0000832 if (PreambleTimer)
833 PreambleTimer->stopTimer();
834
Douglas Gregor754f3492010-07-24 00:38:13 +0000835 return 0;
Douglas Gregor44c181a2010-07-23 00:33:23 +0000836 }
837
838 Act->Execute();
839 Act->EndSourceFile();
840 Clang.takeDiagnosticClient();
841 Clang.takeInvocation();
842
Douglas Gregor175c4a92010-07-23 23:58:40 +0000843 if (Diagnostics->getNumErrors() > 0) {
844 // There were errors parsing the preamble, so no precompiled header was
845 // generated. Forget that we even tried.
846 // FIXME: Should we leave a note for ourselves to try again?
847 llvm::sys::Path(FrontendOpts.OutputFile).eraseFromDisk();
848 Preamble.clear();
849 if (CreatedPreambleBuffer)
850 delete NewPreamble.first;
Douglas Gregor385103b2010-07-30 20:58:08 +0000851 if (PreambleTimer)
852 PreambleTimer->stopTimer();
Douglas Gregor385103b2010-07-30 20:58:08 +0000853
Douglas Gregor754f3492010-07-24 00:38:13 +0000854 return 0;
Douglas Gregor175c4a92010-07-23 23:58:40 +0000855 }
856
857 // Keep track of the preamble we precompiled.
858 PreambleFile = FrontendOpts.OutputFile;
Douglas Gregorc0659ec2010-08-02 20:51:39 +0000859 NumStoredDiagnosticsInPreamble = StoredDiagnostics.size();
860 NumWarningsInPreamble = getDiagnostics().getNumWarnings();
Douglas Gregorcc5888d2010-07-31 00:40:00 +0000861
862 // Keep track of all of the files that the source manager knows about,
863 // so we can verify whether they have changed or not.
864 FilesInPreamble.clear();
865 SourceManager &SourceMgr = Clang.getSourceManager();
866 const llvm::MemoryBuffer *MainFileBuffer
867 = SourceMgr.getBuffer(SourceMgr.getMainFileID());
868 for (SourceManager::fileinfo_iterator F = SourceMgr.fileinfo_begin(),
869 FEnd = SourceMgr.fileinfo_end();
870 F != FEnd;
871 ++F) {
872 const FileEntry *File = F->second->Entry;
873 if (!File || F->second->getRawBuffer() == MainFileBuffer)
874 continue;
875
876 FilesInPreamble[File->getName()]
877 = std::make_pair(F->second->getSize(), File->getModificationTime());
878 }
879
Douglas Gregor385103b2010-07-30 20:58:08 +0000880 if (PreambleTimer)
881 PreambleTimer->stopTimer();
882
Douglas Gregor754f3492010-07-24 00:38:13 +0000883 return CreatePaddedMainFileBuffer(NewPreamble.first,
884 CreatedPreambleBuffer,
885 PreambleReservedSize,
886 FrontendOpts.Inputs[0].second);
Douglas Gregor44c181a2010-07-23 00:33:23 +0000887}
Douglas Gregorabc563f2010-07-19 21:46:24 +0000888
889ASTUnit *ASTUnit::LoadFromCompilerInvocation(CompilerInvocation *CI,
890 llvm::IntrusiveRefCntPtr<Diagnostic> Diags,
891 bool OnlyLocalDecls,
Douglas Gregor44c181a2010-07-23 00:33:23 +0000892 bool CaptureDiagnostics,
893 bool PrecompilePreamble) {
Douglas Gregorabc563f2010-07-19 21:46:24 +0000894 if (!Diags.getPtr()) {
895 // No diagnostics engine was provided, so create our own diagnostics object
896 // with the default options.
897 DiagnosticOptions DiagOpts;
898 Diags = CompilerInstance::createDiagnostics(DiagOpts, 0, 0);
899 }
900
901 // Create the AST unit.
902 llvm::OwningPtr<ASTUnit> AST;
903 AST.reset(new ASTUnit(false));
904 AST->Diagnostics = Diags;
905 AST->CaptureDiagnostics = CaptureDiagnostics;
906 AST->OnlyLocalDecls = OnlyLocalDecls;
907 AST->Invocation.reset(CI);
Douglas Gregorf4f6c9d2010-07-26 21:36:20 +0000908 CI->getPreprocessorOpts().RetainRemappedFileBuffers = true;
Douglas Gregorabc563f2010-07-19 21:46:24 +0000909
Douglas Gregor385103b2010-07-30 20:58:08 +0000910 if (getenv("LIBCLANG_TIMING"))
911 AST->TimerGroup.reset(
912 new llvm::TimerGroup(CI->getFrontendOpts().Inputs[0].second));
913
914
Douglas Gregor754f3492010-07-24 00:38:13 +0000915 llvm::MemoryBuffer *OverrideMainBuffer = 0;
Douglas Gregorfd0b8702010-07-28 22:12:37 +0000916 // FIXME: When C++ PCH is ready, allow use of it for a precompiled preamble.
917 if (PrecompilePreamble && !CI->getLangOpts().CPlusPlus)
Douglas Gregor754f3492010-07-24 00:38:13 +0000918 OverrideMainBuffer = AST->BuildPrecompiledPreamble();
Douglas Gregor44c181a2010-07-23 00:33:23 +0000919
Douglas Gregor385103b2010-07-30 20:58:08 +0000920 llvm::Timer *ParsingTimer = 0;
921 if (AST->TimerGroup.get()) {
922 ParsingTimer = new llvm::Timer("Initial parse", *AST->TimerGroup);
923 ParsingTimer->startTimer();
924 AST->Timers.push_back(ParsingTimer);
925 }
Douglas Gregorabc563f2010-07-19 21:46:24 +0000926
Douglas Gregor385103b2010-07-30 20:58:08 +0000927 bool Failed = AST->Parse(OverrideMainBuffer);
928 if (ParsingTimer)
929 ParsingTimer->stopTimer();
930
931 return Failed? 0 : AST.take();
Daniel Dunbar521bf9c2009-12-01 09:51:01 +0000932}
Daniel Dunbar7b556682009-12-02 03:23:45 +0000933
934ASTUnit *ASTUnit::LoadFromCommandLine(const char **ArgBegin,
935 const char **ArgEnd,
Douglas Gregor28019772010-04-05 23:52:57 +0000936 llvm::IntrusiveRefCntPtr<Diagnostic> Diags,
Daniel Dunbar869824e2009-12-13 03:46:13 +0000937 llvm::StringRef ResourceFilesPath,
Daniel Dunbar7b556682009-12-02 03:23:45 +0000938 bool OnlyLocalDecls,
Douglas Gregor4db64a42010-01-23 00:14:00 +0000939 RemappedFile *RemappedFiles,
Douglas Gregora88084b2010-02-18 18:08:43 +0000940 unsigned NumRemappedFiles,
Douglas Gregor44c181a2010-07-23 00:33:23 +0000941 bool CaptureDiagnostics,
942 bool PrecompilePreamble) {
Douglas Gregor28019772010-04-05 23:52:57 +0000943 if (!Diags.getPtr()) {
Douglas Gregor3687e9d2010-04-05 21:10:19 +0000944 // No diagnostics engine was provided, so create our own diagnostics object
945 // with the default options.
946 DiagnosticOptions DiagOpts;
Douglas Gregor28019772010-04-05 23:52:57 +0000947 Diags = CompilerInstance::createDiagnostics(DiagOpts, 0, 0);
Douglas Gregor3687e9d2010-04-05 21:10:19 +0000948 }
949
Daniel Dunbar7b556682009-12-02 03:23:45 +0000950 llvm::SmallVector<const char *, 16> Args;
951 Args.push_back("<clang>"); // FIXME: Remove dummy argument.
952 Args.insert(Args.end(), ArgBegin, ArgEnd);
953
954 // FIXME: Find a cleaner way to force the driver into restricted modes. We
955 // also want to force it to use clang.
956 Args.push_back("-fsyntax-only");
957
Daniel Dunbar869824e2009-12-13 03:46:13 +0000958 // FIXME: We shouldn't have to pass in the path info.
Daniel Dunbar0bbad512010-07-19 00:44:04 +0000959 driver::Driver TheDriver("clang", llvm::sys::getHostTriple(),
Douglas Gregor3687e9d2010-04-05 21:10:19 +0000960 "a.out", false, false, *Diags);
Daniel Dunbar3bd54cc2010-01-25 00:44:02 +0000961
962 // Don't check that inputs exist, they have been remapped.
963 TheDriver.setCheckInputsExist(false);
964
Daniel Dunbar7b556682009-12-02 03:23:45 +0000965 llvm::OwningPtr<driver::Compilation> C(
966 TheDriver.BuildCompilation(Args.size(), Args.data()));
967
968 // We expect to get back exactly one command job, if we didn't something
969 // failed.
970 const driver::JobList &Jobs = C->getJobs();
971 if (Jobs.size() != 1 || !isa<driver::Command>(Jobs.begin())) {
972 llvm::SmallString<256> Msg;
973 llvm::raw_svector_ostream OS(Msg);
974 C->PrintJob(OS, C->getJobs(), "; ", true);
Douglas Gregor3687e9d2010-04-05 21:10:19 +0000975 Diags->Report(diag::err_fe_expected_compiler_job) << OS.str();
Daniel Dunbar7b556682009-12-02 03:23:45 +0000976 return 0;
977 }
978
979 const driver::Command *Cmd = cast<driver::Command>(*Jobs.begin());
980 if (llvm::StringRef(Cmd->getCreator().getName()) != "clang") {
Douglas Gregor3687e9d2010-04-05 21:10:19 +0000981 Diags->Report(diag::err_fe_expected_clang_command);
Daniel Dunbar7b556682009-12-02 03:23:45 +0000982 return 0;
983 }
984
985 const driver::ArgStringList &CCArgs = Cmd->getArguments();
Daniel Dunbar807b0612010-01-30 21:47:16 +0000986 llvm::OwningPtr<CompilerInvocation> CI(new CompilerInvocation);
Dan Gohmancb421fa2010-04-19 16:39:44 +0000987 CompilerInvocation::CreateFromArgs(*CI,
988 const_cast<const char **>(CCArgs.data()),
989 const_cast<const char **>(CCArgs.data()) +
Douglas Gregor44c181a2010-07-23 00:33:23 +0000990 CCArgs.size(),
Douglas Gregor3687e9d2010-04-05 21:10:19 +0000991 *Diags);
Daniel Dunbar1e69fe32009-12-13 03:45:58 +0000992
Douglas Gregor4db64a42010-01-23 00:14:00 +0000993 // Override any files that need remapping
994 for (unsigned I = 0; I != NumRemappedFiles; ++I)
Daniel Dunbar807b0612010-01-30 21:47:16 +0000995 CI->getPreprocessorOpts().addRemappedFile(RemappedFiles[I].first,
Daniel Dunbarb26d4832010-02-16 01:55:04 +0000996 RemappedFiles[I].second);
Douglas Gregor4db64a42010-01-23 00:14:00 +0000997
Daniel Dunbar8b9adfe2009-12-15 00:06:45 +0000998 // Override the resources path.
Daniel Dunbar807b0612010-01-30 21:47:16 +0000999 CI->getHeaderSearchOpts().ResourceDir = ResourceFilesPath;
Daniel Dunbar7b556682009-12-02 03:23:45 +00001000
Daniel Dunbarb26d4832010-02-16 01:55:04 +00001001 CI->getFrontendOpts().DisableFree = true;
Douglas Gregora88084b2010-02-18 18:08:43 +00001002 return LoadFromCompilerInvocation(CI.take(), Diags, OnlyLocalDecls,
Douglas Gregor44c181a2010-07-23 00:33:23 +00001003 CaptureDiagnostics, PrecompilePreamble);
Daniel Dunbar7b556682009-12-02 03:23:45 +00001004}
Douglas Gregorabc563f2010-07-19 21:46:24 +00001005
1006bool ASTUnit::Reparse(RemappedFile *RemappedFiles, unsigned NumRemappedFiles) {
1007 if (!Invocation.get())
1008 return true;
1009
Douglas Gregor385103b2010-07-30 20:58:08 +00001010 llvm::Timer *ReparsingTimer = 0;
1011 if (TimerGroup.get()) {
1012 ReparsingTimer = new llvm::Timer("Reparse", *TimerGroup);
1013 ReparsingTimer->startTimer();
1014 Timers.push_back(ReparsingTimer);
1015 }
1016
Douglas Gregorcc5888d2010-07-31 00:40:00 +00001017 // Remap files.
1018 // FIXME: Do we want to remove old mappings for these files?
1019 Invocation->getPreprocessorOpts().clearRemappedFiles();
1020 for (unsigned I = 0; I != NumRemappedFiles; ++I)
1021 Invocation->getPreprocessorOpts().addRemappedFile(RemappedFiles[I].first,
1022 RemappedFiles[I].second);
1023
Douglas Gregor175c4a92010-07-23 23:58:40 +00001024 // If we have a preamble file lying around, build or reuse the precompiled
1025 // preamble.
Douglas Gregor754f3492010-07-24 00:38:13 +00001026 llvm::MemoryBuffer *OverrideMainBuffer = 0;
Douglas Gregor175c4a92010-07-23 23:58:40 +00001027 if (!PreambleFile.empty())
Douglas Gregor754f3492010-07-24 00:38:13 +00001028 OverrideMainBuffer = BuildPrecompiledPreamble();
Douglas Gregor175c4a92010-07-23 23:58:40 +00001029
Douglas Gregorabc563f2010-07-19 21:46:24 +00001030 // Clear out the diagnostics state.
Douglas Gregorc0659ec2010-08-02 20:51:39 +00001031 if (!OverrideMainBuffer)
1032 getDiagnostics().Reset();
Douglas Gregorabc563f2010-07-19 21:46:24 +00001033
Douglas Gregor175c4a92010-07-23 23:58:40 +00001034 // Parse the sources
Douglas Gregor754f3492010-07-24 00:38:13 +00001035 bool Result = Parse(OverrideMainBuffer);
Douglas Gregor385103b2010-07-30 20:58:08 +00001036 if (ReparsingTimer)
1037 ReparsingTimer->stopTimer();
Douglas Gregor175c4a92010-07-23 23:58:40 +00001038 return Result;
Douglas Gregorabc563f2010-07-19 21:46:24 +00001039}