blob: 4bfefd60d5d27e681678398ff5b569f50ef3899a [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"
Argyrios Kyrtzidis0853a022009-06-20 08:08:23 +000036using namespace clang;
37
Douglas Gregor3687e9d2010-04-05 21:10:19 +000038ASTUnit::ASTUnit(bool _MainFileIsAST)
Douglas Gregorabc563f2010-07-19 21:46:24 +000039 : CaptureDiagnostics(false), MainFileIsAST(_MainFileIsAST),
40 ConcurrencyCheckValue(CheckUnlocked) { }
Douglas Gregor3687e9d2010-04-05 21:10:19 +000041
Daniel Dunbar521bf9c2009-12-01 09:51:01 +000042ASTUnit::~ASTUnit() {
Douglas Gregorbdf60622010-03-05 21:16:25 +000043 ConcurrencyCheckValue = CheckLocked;
Douglas Gregorabc563f2010-07-19 21:46:24 +000044 CleanTemporaryFiles();
45}
46
47void ASTUnit::CleanTemporaryFiles() {
Douglas Gregor313e26c2010-02-18 23:35:40 +000048 for (unsigned I = 0, N = TemporaryFiles.size(); I != N; ++I)
49 TemporaryFiles[I].eraseFromDisk();
Douglas Gregorabc563f2010-07-19 21:46:24 +000050 TemporaryFiles.clear();
Steve Naroffe19944c2009-10-15 22:23:48 +000051}
Argyrios Kyrtzidis0853a022009-06-20 08:08:23 +000052
53namespace {
54
55/// \brief Gathers information from PCHReader that will be used to initialize
56/// a Preprocessor.
Benjamin Kramerbd218282009-11-28 10:07:24 +000057class PCHInfoCollector : public PCHReaderListener {
Argyrios Kyrtzidis0853a022009-06-20 08:08:23 +000058 LangOptions &LangOpt;
59 HeaderSearch &HSI;
60 std::string &TargetTriple;
61 std::string &Predefines;
62 unsigned &Counter;
Mike Stump1eb44332009-09-09 15:08:12 +000063
Argyrios Kyrtzidis0853a022009-06-20 08:08:23 +000064 unsigned NumHeaderInfos;
Mike Stump1eb44332009-09-09 15:08:12 +000065
Argyrios Kyrtzidis0853a022009-06-20 08:08:23 +000066public:
67 PCHInfoCollector(LangOptions &LangOpt, HeaderSearch &HSI,
68 std::string &TargetTriple, std::string &Predefines,
69 unsigned &Counter)
70 : LangOpt(LangOpt), HSI(HSI), TargetTriple(TargetTriple),
71 Predefines(Predefines), Counter(Counter), NumHeaderInfos(0) {}
Mike Stump1eb44332009-09-09 15:08:12 +000072
Argyrios Kyrtzidis0853a022009-06-20 08:08:23 +000073 virtual bool ReadLanguageOptions(const LangOptions &LangOpts) {
74 LangOpt = LangOpts;
75 return false;
76 }
Mike Stump1eb44332009-09-09 15:08:12 +000077
Daniel Dunbardc3c0d22009-11-11 00:52:11 +000078 virtual bool ReadTargetTriple(llvm::StringRef Triple) {
Argyrios Kyrtzidis0853a022009-06-20 08:08:23 +000079 TargetTriple = Triple;
80 return false;
81 }
Mike Stump1eb44332009-09-09 15:08:12 +000082
Sebastian Redlcb481aa2010-07-14 23:29:55 +000083 virtual bool ReadPredefinesBuffer(const PCHPredefinesBlocks &Buffers,
Daniel Dunbar7b5a1212009-11-11 05:29:04 +000084 llvm::StringRef OriginalFileName,
Argyrios Kyrtzidis0853a022009-06-20 08:08:23 +000085 std::string &SuggestedPredefines) {
Sebastian Redlcb481aa2010-07-14 23:29:55 +000086 Predefines = Buffers[0].Data;
87 for (unsigned I = 1, N = Buffers.size(); I != N; ++I) {
88 Predefines += Buffers[I].Data;
89 }
Argyrios Kyrtzidis0853a022009-06-20 08:08:23 +000090 return false;
91 }
Mike Stump1eb44332009-09-09 15:08:12 +000092
Douglas Gregorec1afbf2010-03-16 19:09:18 +000093 virtual void ReadHeaderFileInfo(const HeaderFileInfo &HFI, unsigned ID) {
Argyrios Kyrtzidis0853a022009-06-20 08:08:23 +000094 HSI.setHeaderFileInfoForUID(HFI, NumHeaderInfos++);
95 }
Mike Stump1eb44332009-09-09 15:08:12 +000096
Argyrios Kyrtzidis0853a022009-06-20 08:08:23 +000097 virtual void ReadCounter(unsigned Value) {
98 Counter = Value;
99 }
100};
101
Douglas Gregora88084b2010-02-18 18:08:43 +0000102class StoredDiagnosticClient : public DiagnosticClient {
103 llvm::SmallVectorImpl<StoredDiagnostic> &StoredDiags;
104
105public:
106 explicit StoredDiagnosticClient(
107 llvm::SmallVectorImpl<StoredDiagnostic> &StoredDiags)
108 : StoredDiags(StoredDiags) { }
109
110 virtual void HandleDiagnostic(Diagnostic::Level Level,
111 const DiagnosticInfo &Info);
112};
113
114/// \brief RAII object that optionally captures diagnostics, if
115/// there is no diagnostic client to capture them already.
116class CaptureDroppedDiagnostics {
117 Diagnostic &Diags;
118 StoredDiagnosticClient Client;
119 DiagnosticClient *PreviousClient;
120
121public:
122 CaptureDroppedDiagnostics(bool RequestCapture, Diagnostic &Diags,
123 llvm::SmallVectorImpl<StoredDiagnostic> &StoredDiags)
124 : Diags(Diags), Client(StoredDiags), PreviousClient(Diags.getClient())
125 {
126 if (RequestCapture || Diags.getClient() == 0)
127 Diags.setClient(&Client);
128 }
129
130 ~CaptureDroppedDiagnostics() {
131 Diags.setClient(PreviousClient);
132 }
133};
134
Argyrios Kyrtzidis0853a022009-06-20 08:08:23 +0000135} // anonymous namespace
136
Douglas Gregora88084b2010-02-18 18:08:43 +0000137void StoredDiagnosticClient::HandleDiagnostic(Diagnostic::Level Level,
138 const DiagnosticInfo &Info) {
139 StoredDiags.push_back(StoredDiagnostic(Level, Info));
140}
141
Steve Naroff77accc12009-09-03 18:19:54 +0000142const std::string &ASTUnit::getOriginalSourceFileName() {
Daniel Dunbar68d40e22009-12-02 08:44:16 +0000143 return OriginalSourceFile;
Steve Naroff77accc12009-09-03 18:19:54 +0000144}
Argyrios Kyrtzidis0853a022009-06-20 08:08:23 +0000145
Steve Naroffe19944c2009-10-15 22:23:48 +0000146const std::string &ASTUnit::getPCHFileName() {
Daniel Dunbarc7822db2009-12-02 21:47:43 +0000147 assert(isMainFileAST() && "Not an ASTUnit from a PCH file!");
Benjamin Kramer7297c182010-01-30 16:23:25 +0000148 return static_cast<PCHReader *>(Ctx->getExternalSource())->getFileName();
Steve Naroffe19944c2009-10-15 22:23:48 +0000149}
150
Argyrios Kyrtzidis0853a022009-06-20 08:08:23 +0000151ASTUnit *ASTUnit::LoadFromPCHFile(const std::string &Filename,
Douglas Gregor28019772010-04-05 23:52:57 +0000152 llvm::IntrusiveRefCntPtr<Diagnostic> Diags,
Ted Kremenek5cf48762009-10-17 00:34:24 +0000153 bool OnlyLocalDecls,
Douglas Gregor4db64a42010-01-23 00:14:00 +0000154 RemappedFile *RemappedFiles,
Douglas Gregora88084b2010-02-18 18:08:43 +0000155 unsigned NumRemappedFiles,
156 bool CaptureDiagnostics) {
Douglas Gregor3687e9d2010-04-05 21:10:19 +0000157 llvm::OwningPtr<ASTUnit> AST(new ASTUnit(true));
158
Douglas Gregor28019772010-04-05 23:52:57 +0000159 if (!Diags.getPtr()) {
Douglas Gregor3687e9d2010-04-05 21:10:19 +0000160 // No diagnostics engine was provided, so create our own diagnostics object
161 // with the default options.
162 DiagnosticOptions DiagOpts;
Douglas Gregor28019772010-04-05 23:52:57 +0000163 Diags = CompilerInstance::createDiagnostics(DiagOpts, 0, 0);
Douglas Gregor3687e9d2010-04-05 21:10:19 +0000164 }
Douglas Gregorabc563f2010-07-19 21:46:24 +0000165
166 AST->CaptureDiagnostics = CaptureDiagnostics;
Douglas Gregor7d1d49d2009-10-16 20:01:17 +0000167 AST->OnlyLocalDecls = OnlyLocalDecls;
Douglas Gregor28019772010-04-05 23:52:57 +0000168 AST->Diagnostics = Diags;
Douglas Gregor3687e9d2010-04-05 21:10:19 +0000169 AST->FileMgr.reset(new FileManager);
170 AST->SourceMgr.reset(new SourceManager(AST->getDiagnostics()));
Steve Naroff36c44642009-10-19 14:34:22 +0000171 AST->HeaderInfo.reset(new HeaderSearch(AST->getFileManager()));
Argyrios Kyrtzidis0853a022009-06-20 08:08:23 +0000172
Douglas Gregora88084b2010-02-18 18:08:43 +0000173 // If requested, capture diagnostics in the ASTUnit.
Douglas Gregor3687e9d2010-04-05 21:10:19 +0000174 CaptureDroppedDiagnostics Capture(CaptureDiagnostics, AST->getDiagnostics(),
Douglas Gregor405634b2010-04-05 18:10:21 +0000175 AST->StoredDiagnostics);
Douglas Gregora88084b2010-02-18 18:08:43 +0000176
Douglas Gregor4db64a42010-01-23 00:14:00 +0000177 for (unsigned I = 0; I != NumRemappedFiles; ++I) {
178 // Create the file entry for the file that we're mapping from.
179 const FileEntry *FromFile
180 = AST->getFileManager().getVirtualFile(RemappedFiles[I].first,
181 RemappedFiles[I].second->getBufferSize(),
182 0);
183 if (!FromFile) {
Douglas Gregor3687e9d2010-04-05 21:10:19 +0000184 AST->getDiagnostics().Report(diag::err_fe_remap_missing_from_file)
Douglas Gregor4db64a42010-01-23 00:14:00 +0000185 << RemappedFiles[I].first;
Douglas Gregorc8dfe5e2010-02-27 01:32:48 +0000186 delete RemappedFiles[I].second;
Douglas Gregor4db64a42010-01-23 00:14:00 +0000187 continue;
188 }
189
190 // Override the contents of the "from" file with the contents of
191 // the "to" file.
192 AST->getSourceManager().overrideFileContents(FromFile,
193 RemappedFiles[I].second);
194 }
195
Argyrios Kyrtzidis0853a022009-06-20 08:08:23 +0000196 // Gather Info for preprocessor construction later on.
Mike Stump1eb44332009-09-09 15:08:12 +0000197
Argyrios Kyrtzidis0853a022009-06-20 08:08:23 +0000198 LangOptions LangInfo;
199 HeaderSearch &HeaderInfo = *AST->HeaderInfo.get();
200 std::string TargetTriple;
201 std::string Predefines;
202 unsigned Counter;
203
Daniel Dunbarbce6f622009-09-03 05:59:50 +0000204 llvm::OwningPtr<PCHReader> Reader;
Argyrios Kyrtzidis0853a022009-06-20 08:08:23 +0000205 llvm::OwningPtr<ExternalASTSource> Source;
206
Ted Kremenekfc062212009-10-19 21:44:57 +0000207 Reader.reset(new PCHReader(AST->getSourceManager(), AST->getFileManager(),
Douglas Gregor3687e9d2010-04-05 21:10:19 +0000208 AST->getDiagnostics()));
Daniel Dunbarcc318932009-09-03 05:59:35 +0000209 Reader->setListener(new PCHInfoCollector(LangInfo, HeaderInfo, TargetTriple,
210 Predefines, Counter));
211
212 switch (Reader->ReadPCH(Filename)) {
Argyrios Kyrtzidis0853a022009-06-20 08:08:23 +0000213 case PCHReader::Success:
214 break;
Mike Stump1eb44332009-09-09 15:08:12 +0000215
Argyrios Kyrtzidis0853a022009-06-20 08:08:23 +0000216 case PCHReader::Failure:
Argyrios Kyrtzidis106c9982009-06-25 18:22:30 +0000217 case PCHReader::IgnorePCH:
Douglas Gregor3687e9d2010-04-05 21:10:19 +0000218 AST->getDiagnostics().Report(diag::err_fe_unable_to_load_pch);
Argyrios Kyrtzidis0853a022009-06-20 08:08:23 +0000219 return NULL;
Argyrios Kyrtzidis0853a022009-06-20 08:08:23 +0000220 }
Mike Stump1eb44332009-09-09 15:08:12 +0000221
Daniel Dunbar68d40e22009-12-02 08:44:16 +0000222 AST->OriginalSourceFile = Reader->getOriginalSourceFile();
223
Argyrios Kyrtzidis0853a022009-06-20 08:08:23 +0000224 // PCH loaded successfully. Now create the preprocessor.
Mike Stump1eb44332009-09-09 15:08:12 +0000225
Argyrios Kyrtzidis0853a022009-06-20 08:08:23 +0000226 // Get information about the target being compiled for.
Daniel Dunbard58c03f2009-11-15 06:48:46 +0000227 //
228 // FIXME: This is broken, we should store the TargetOptions in the PCH.
229 TargetOptions TargetOpts;
230 TargetOpts.ABI = "";
Charles Davis98b7c5c2010-06-11 01:06:47 +0000231 TargetOpts.CXXABI = "itanium";
Daniel Dunbard58c03f2009-11-15 06:48:46 +0000232 TargetOpts.CPU = "";
233 TargetOpts.Features.clear();
234 TargetOpts.Triple = TargetTriple;
Douglas Gregor3687e9d2010-04-05 21:10:19 +0000235 AST->Target.reset(TargetInfo::CreateTargetInfo(AST->getDiagnostics(),
236 TargetOpts));
237 AST->PP.reset(new Preprocessor(AST->getDiagnostics(), LangInfo,
238 *AST->Target.get(),
Daniel Dunbar31b87d82009-09-21 03:03:39 +0000239 AST->getSourceManager(), HeaderInfo));
Argyrios Kyrtzidis0853a022009-06-20 08:08:23 +0000240 Preprocessor &PP = *AST->PP.get();
241
Daniel Dunbard5b61262009-09-21 03:03:47 +0000242 PP.setPredefines(Reader->getSuggestedPredefines());
Argyrios Kyrtzidis0853a022009-06-20 08:08:23 +0000243 PP.setCounterValue(Counter);
Daniel Dunbarcc318932009-09-03 05:59:35 +0000244 Reader->setPreprocessor(PP);
Mike Stump1eb44332009-09-09 15:08:12 +0000245
Argyrios Kyrtzidis0853a022009-06-20 08:08:23 +0000246 // Create and initialize the ASTContext.
247
248 AST->Ctx.reset(new ASTContext(LangInfo,
Daniel Dunbar31b87d82009-09-21 03:03:39 +0000249 AST->getSourceManager(),
Argyrios Kyrtzidis0853a022009-06-20 08:08:23 +0000250 *AST->Target.get(),
251 PP.getIdentifierTable(),
252 PP.getSelectorTable(),
253 PP.getBuiltinInfo(),
Daniel Dunbarb26d4832010-02-16 01:55:04 +0000254 /* FreeMemory = */ false,
Argyrios Kyrtzidis0853a022009-06-20 08:08:23 +0000255 /* size_reserve = */0));
256 ASTContext &Context = *AST->Ctx.get();
Mike Stump1eb44332009-09-09 15:08:12 +0000257
Daniel Dunbarcc318932009-09-03 05:59:35 +0000258 Reader->InitializeContext(Context);
Mike Stump1eb44332009-09-09 15:08:12 +0000259
Argyrios Kyrtzidis0853a022009-06-20 08:08:23 +0000260 // Attach the PCH reader to the AST context as an external AST
261 // source, so that declarations will be deserialized from the
262 // PCH file as needed.
Daniel Dunbarcc318932009-09-03 05:59:35 +0000263 Source.reset(Reader.take());
Argyrios Kyrtzidis0853a022009-06-20 08:08:23 +0000264 Context.setExternalSource(Source);
265
Mike Stump1eb44332009-09-09 15:08:12 +0000266 return AST.take();
Argyrios Kyrtzidis0853a022009-06-20 08:08:23 +0000267}
Daniel Dunbar521bf9c2009-12-01 09:51:01 +0000268
269namespace {
270
Daniel Dunbarf772d1e2009-12-04 08:17:33 +0000271class TopLevelDeclTrackerConsumer : public ASTConsumer {
272 ASTUnit &Unit;
273
274public:
275 TopLevelDeclTrackerConsumer(ASTUnit &_Unit) : Unit(_Unit) {}
276
277 void HandleTopLevelDecl(DeclGroupRef D) {
Ted Kremenekda5a4282010-05-03 20:16:35 +0000278 for (DeclGroupRef::iterator it = D.begin(), ie = D.end(); it != ie; ++it) {
279 Decl *D = *it;
280 // FIXME: Currently ObjC method declarations are incorrectly being
281 // reported as top-level declarations, even though their DeclContext
282 // is the containing ObjC @interface/@implementation. This is a
283 // fundamental problem in the parser right now.
284 if (isa<ObjCMethodDecl>(D))
285 continue;
286 Unit.getTopLevelDecls().push_back(D);
287 }
Daniel Dunbarf772d1e2009-12-04 08:17:33 +0000288 }
289};
290
291class TopLevelDeclTrackerAction : public ASTFrontendAction {
292public:
293 ASTUnit &Unit;
294
Daniel Dunbar521bf9c2009-12-01 09:51:01 +0000295 virtual ASTConsumer *CreateASTConsumer(CompilerInstance &CI,
296 llvm::StringRef InFile) {
Daniel Dunbarf772d1e2009-12-04 08:17:33 +0000297 return new TopLevelDeclTrackerConsumer(Unit);
Daniel Dunbar521bf9c2009-12-01 09:51:01 +0000298 }
299
300public:
Daniel Dunbarf772d1e2009-12-04 08:17:33 +0000301 TopLevelDeclTrackerAction(ASTUnit &_Unit) : Unit(_Unit) {}
302
Daniel Dunbar521bf9c2009-12-01 09:51:01 +0000303 virtual bool hasCodeCompletionSupport() const { return false; }
304};
305
306}
307
Douglas Gregorabc563f2010-07-19 21:46:24 +0000308/// Parse the source file into a translation unit using the given compiler
309/// invocation, replacing the current translation unit.
310///
311/// \returns True if a failure occurred that causes the ASTUnit not to
312/// contain any translation-unit information, false otherwise.
313bool ASTUnit::Parse() {
314 if (!Invocation.get())
315 return true;
316
Daniel Dunbar521bf9c2009-12-01 09:51:01 +0000317 // Create the compiler instance to use for building the AST.
Daniel Dunbarcb6dda12009-12-02 08:43:56 +0000318 CompilerInstance Clang;
Douglas Gregorabc563f2010-07-19 21:46:24 +0000319 Clang.setInvocation(Invocation.take());
320 OriginalSourceFile = Clang.getFrontendOpts().Inputs[0].second;
321
322 // Set up diagnostics.
323 Clang.setDiagnostics(&getDiagnostics());
324 Clang.setDiagnosticClient(getDiagnostics().getClient());
Douglas Gregor3687e9d2010-04-05 21:10:19 +0000325
Daniel Dunbar521bf9c2009-12-01 09:51:01 +0000326 // Create the target instance.
327 Clang.setTarget(TargetInfo::CreateTargetInfo(Clang.getDiagnostics(),
328 Clang.getTargetOpts()));
Douglas Gregora88084b2010-02-18 18:08:43 +0000329 if (!Clang.hasTarget()) {
Douglas Gregora88084b2010-02-18 18:08:43 +0000330 Clang.takeDiagnosticClient();
Douglas Gregorabc563f2010-07-19 21:46:24 +0000331 return true;
Douglas Gregora88084b2010-02-18 18:08:43 +0000332 }
Douglas Gregorabc563f2010-07-19 21:46:24 +0000333
Daniel Dunbar521bf9c2009-12-01 09:51:01 +0000334 // Inform the target of the language options.
335 //
336 // FIXME: We shouldn't need to do this, the target should be immutable once
337 // created. This complexity should be lifted elsewhere.
338 Clang.getTarget().setForcedLangOptions(Clang.getLangOpts());
Douglas Gregorabc563f2010-07-19 21:46:24 +0000339
Daniel Dunbar521bf9c2009-12-01 09:51:01 +0000340 assert(Clang.getFrontendOpts().Inputs.size() == 1 &&
341 "Invocation must have exactly one source file!");
Daniel Dunbarc34ce3f2010-06-07 23:22:09 +0000342 assert(Clang.getFrontendOpts().Inputs[0].first != IK_AST &&
Daniel Dunbar521bf9c2009-12-01 09:51:01 +0000343 "FIXME: AST inputs not yet supported here!");
Daniel Dunbarfaddc3e2010-06-07 23:26:47 +0000344 assert(Clang.getFrontendOpts().Inputs[0].first != IK_LLVM_IR &&
345 "IR inputs not support here!");
Daniel Dunbar521bf9c2009-12-01 09:51:01 +0000346
Douglas Gregorabc563f2010-07-19 21:46:24 +0000347 // Configure the various subsystems.
348 // FIXME: Should we retain the previous file manager?
349 FileMgr.reset(new FileManager);
350 SourceMgr.reset(new SourceManager(getDiagnostics()));
351 Ctx.reset();
352 PP.reset();
353
354 // Clear out old caches and data.
355 TopLevelDecls.clear();
356 StoredDiagnostics.clear();
357 CleanTemporaryFiles();
358 PreprocessedEntitiesByFile.clear();
359
Douglas Gregora88084b2010-02-18 18:08:43 +0000360 // Capture any diagnostics that would otherwise be dropped.
361 CaptureDroppedDiagnostics Capture(CaptureDiagnostics,
362 Clang.getDiagnostics(),
Douglas Gregorabc563f2010-07-19 21:46:24 +0000363 StoredDiagnostics);
364
Daniel Dunbar521bf9c2009-12-01 09:51:01 +0000365 // Create a file manager object to provide access to and cache the filesystem.
Douglas Gregorabc563f2010-07-19 21:46:24 +0000366 Clang.setFileManager(&getFileManager());
367
Daniel Dunbar521bf9c2009-12-01 09:51:01 +0000368 // Create the source manager.
Douglas Gregorabc563f2010-07-19 21:46:24 +0000369 Clang.setSourceManager(&getSourceManager());
370
371 llvm::OwningPtr<TopLevelDeclTrackerAction> Act;
372 Act.reset(new TopLevelDeclTrackerAction(*this));
Daniel Dunbarf772d1e2009-12-04 08:17:33 +0000373 if (!Act->BeginSourceFile(Clang, Clang.getFrontendOpts().Inputs[0].second,
Daniel Dunbard3598a62010-06-07 23:23:06 +0000374 Clang.getFrontendOpts().Inputs[0].first))
Daniel Dunbar521bf9c2009-12-01 09:51:01 +0000375 goto error;
Douglas Gregorabc563f2010-07-19 21:46:24 +0000376
Daniel Dunbarf772d1e2009-12-04 08:17:33 +0000377 Act->Execute();
Douglas Gregorabc563f2010-07-19 21:46:24 +0000378
Daniel Dunbar64a32ba2009-12-01 21:57:33 +0000379 // Steal the created target, context, and preprocessor, and take back the
380 // source and file managers.
Douglas Gregorabc563f2010-07-19 21:46:24 +0000381 Ctx.reset(Clang.takeASTContext());
382 PP.reset(Clang.takePreprocessor());
Daniel Dunbar521bf9c2009-12-01 09:51:01 +0000383 Clang.takeSourceManager();
384 Clang.takeFileManager();
Douglas Gregorabc563f2010-07-19 21:46:24 +0000385 Target.reset(Clang.takeTarget());
386
Daniel Dunbarf772d1e2009-12-04 08:17:33 +0000387 Act->EndSourceFile();
Douglas Gregorabc563f2010-07-19 21:46:24 +0000388
Daniel Dunbar521bf9c2009-12-01 09:51:01 +0000389 Clang.takeDiagnosticClient();
Douglas Gregorabc563f2010-07-19 21:46:24 +0000390
391 Invocation.reset(Clang.takeInvocation());
392 return false;
393
Daniel Dunbar521bf9c2009-12-01 09:51:01 +0000394error:
395 Clang.takeSourceManager();
396 Clang.takeFileManager();
397 Clang.takeDiagnosticClient();
Douglas Gregorabc563f2010-07-19 21:46:24 +0000398 Invocation.reset(Clang.takeInvocation());
399 return true;
400}
401
402
403ASTUnit *ASTUnit::LoadFromCompilerInvocation(CompilerInvocation *CI,
404 llvm::IntrusiveRefCntPtr<Diagnostic> Diags,
405 bool OnlyLocalDecls,
406 bool CaptureDiagnostics) {
407 if (!Diags.getPtr()) {
408 // No diagnostics engine was provided, so create our own diagnostics object
409 // with the default options.
410 DiagnosticOptions DiagOpts;
411 Diags = CompilerInstance::createDiagnostics(DiagOpts, 0, 0);
412 }
413
414 // Create the AST unit.
415 llvm::OwningPtr<ASTUnit> AST;
416 AST.reset(new ASTUnit(false));
417 AST->Diagnostics = Diags;
418 AST->CaptureDiagnostics = CaptureDiagnostics;
419 AST->OnlyLocalDecls = OnlyLocalDecls;
420 AST->Invocation.reset(CI);
421
422 if (!AST->Parse())
423 return AST.take();
424
Daniel Dunbar521bf9c2009-12-01 09:51:01 +0000425 return 0;
426}
Daniel Dunbar7b556682009-12-02 03:23:45 +0000427
428ASTUnit *ASTUnit::LoadFromCommandLine(const char **ArgBegin,
429 const char **ArgEnd,
Douglas Gregor28019772010-04-05 23:52:57 +0000430 llvm::IntrusiveRefCntPtr<Diagnostic> Diags,
Daniel Dunbar869824e2009-12-13 03:46:13 +0000431 llvm::StringRef ResourceFilesPath,
Daniel Dunbar7b556682009-12-02 03:23:45 +0000432 bool OnlyLocalDecls,
Douglas Gregor4db64a42010-01-23 00:14:00 +0000433 RemappedFile *RemappedFiles,
Douglas Gregora88084b2010-02-18 18:08:43 +0000434 unsigned NumRemappedFiles,
Douglas Gregor94dc8f62010-03-19 16:15:56 +0000435 bool CaptureDiagnostics) {
Douglas Gregor28019772010-04-05 23:52:57 +0000436 if (!Diags.getPtr()) {
Douglas Gregor3687e9d2010-04-05 21:10:19 +0000437 // No diagnostics engine was provided, so create our own diagnostics object
438 // with the default options.
439 DiagnosticOptions DiagOpts;
Douglas Gregor28019772010-04-05 23:52:57 +0000440 Diags = CompilerInstance::createDiagnostics(DiagOpts, 0, 0);
Douglas Gregor3687e9d2010-04-05 21:10:19 +0000441 }
442
Daniel Dunbar7b556682009-12-02 03:23:45 +0000443 llvm::SmallVector<const char *, 16> Args;
444 Args.push_back("<clang>"); // FIXME: Remove dummy argument.
445 Args.insert(Args.end(), ArgBegin, ArgEnd);
446
447 // FIXME: Find a cleaner way to force the driver into restricted modes. We
448 // also want to force it to use clang.
449 Args.push_back("-fsyntax-only");
450
Daniel Dunbar869824e2009-12-13 03:46:13 +0000451 // FIXME: We shouldn't have to pass in the path info.
Daniel Dunbar0bbad512010-07-19 00:44:04 +0000452 driver::Driver TheDriver("clang", llvm::sys::getHostTriple(),
Douglas Gregor3687e9d2010-04-05 21:10:19 +0000453 "a.out", false, false, *Diags);
Daniel Dunbar3bd54cc2010-01-25 00:44:02 +0000454
455 // Don't check that inputs exist, they have been remapped.
456 TheDriver.setCheckInputsExist(false);
457
Daniel Dunbar7b556682009-12-02 03:23:45 +0000458 llvm::OwningPtr<driver::Compilation> C(
459 TheDriver.BuildCompilation(Args.size(), Args.data()));
460
461 // We expect to get back exactly one command job, if we didn't something
462 // failed.
463 const driver::JobList &Jobs = C->getJobs();
464 if (Jobs.size() != 1 || !isa<driver::Command>(Jobs.begin())) {
465 llvm::SmallString<256> Msg;
466 llvm::raw_svector_ostream OS(Msg);
467 C->PrintJob(OS, C->getJobs(), "; ", true);
Douglas Gregor3687e9d2010-04-05 21:10:19 +0000468 Diags->Report(diag::err_fe_expected_compiler_job) << OS.str();
Daniel Dunbar7b556682009-12-02 03:23:45 +0000469 return 0;
470 }
471
472 const driver::Command *Cmd = cast<driver::Command>(*Jobs.begin());
473 if (llvm::StringRef(Cmd->getCreator().getName()) != "clang") {
Douglas Gregor3687e9d2010-04-05 21:10:19 +0000474 Diags->Report(diag::err_fe_expected_clang_command);
Daniel Dunbar7b556682009-12-02 03:23:45 +0000475 return 0;
476 }
477
478 const driver::ArgStringList &CCArgs = Cmd->getArguments();
Daniel Dunbar807b0612010-01-30 21:47:16 +0000479 llvm::OwningPtr<CompilerInvocation> CI(new CompilerInvocation);
Dan Gohmancb421fa2010-04-19 16:39:44 +0000480 CompilerInvocation::CreateFromArgs(*CI,
481 const_cast<const char **>(CCArgs.data()),
482 const_cast<const char **>(CCArgs.data()) +
483 CCArgs.size(),
Douglas Gregor3687e9d2010-04-05 21:10:19 +0000484 *Diags);
Daniel Dunbar1e69fe32009-12-13 03:45:58 +0000485
Douglas Gregor4db64a42010-01-23 00:14:00 +0000486 // Override any files that need remapping
487 for (unsigned I = 0; I != NumRemappedFiles; ++I)
Daniel Dunbar807b0612010-01-30 21:47:16 +0000488 CI->getPreprocessorOpts().addRemappedFile(RemappedFiles[I].first,
Daniel Dunbarb26d4832010-02-16 01:55:04 +0000489 RemappedFiles[I].second);
Douglas Gregor4db64a42010-01-23 00:14:00 +0000490
Daniel Dunbar8b9adfe2009-12-15 00:06:45 +0000491 // Override the resources path.
Daniel Dunbar807b0612010-01-30 21:47:16 +0000492 CI->getHeaderSearchOpts().ResourceDir = ResourceFilesPath;
Daniel Dunbar7b556682009-12-02 03:23:45 +0000493
Daniel Dunbarb26d4832010-02-16 01:55:04 +0000494 CI->getFrontendOpts().DisableFree = true;
Douglas Gregora88084b2010-02-18 18:08:43 +0000495 return LoadFromCompilerInvocation(CI.take(), Diags, OnlyLocalDecls,
Douglas Gregor94dc8f62010-03-19 16:15:56 +0000496 CaptureDiagnostics);
Daniel Dunbar7b556682009-12-02 03:23:45 +0000497}
Douglas Gregorabc563f2010-07-19 21:46:24 +0000498
499bool ASTUnit::Reparse(RemappedFile *RemappedFiles, unsigned NumRemappedFiles) {
500 if (!Invocation.get())
501 return true;
502
503 // Clear out the diagnostics state.
504 getDiagnostics().Reset();
505
506 // Remap files.
507 Invocation->getPreprocessorOpts().clearRemappedFiles();
508 for (unsigned I = 0; I != NumRemappedFiles; ++I)
509 Invocation->getPreprocessorOpts().addRemappedFile(RemappedFiles[I].first,
510 RemappedFiles[I].second);
511
512 return Parse();
513}