blob: 5d399bd944eaf47251ec0ec897f6897da0b7722e [file] [log] [blame]
Daniel Dunbar2a79e162009-11-13 03:51:44 +00001//===--- CompilerInstance.cpp ---------------------------------------------===//
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#include "clang/Frontend/CompilerInstance.h"
Daniel Dunbar12ce6942009-11-14 02:47:17 +000011#include "clang/AST/ASTConsumer.h"
Daniel Dunbar5eb81002009-11-13 08:20:47 +000012#include "clang/AST/ASTContext.h"
Daniel Dunbar2a79e162009-11-13 03:51:44 +000013#include "clang/Basic/Diagnostic.h"
Daniel Dunbar16b74492009-11-13 04:12:06 +000014#include "clang/Basic/FileManager.h"
15#include "clang/Basic/SourceManager.h"
Daniel Dunbar2a79e162009-11-13 03:51:44 +000016#include "clang/Basic/TargetInfo.h"
Daniel Dunbar0397af22010-01-13 00:48:06 +000017#include "clang/Basic/Version.h"
Daniel Dunbar22dacfa2009-11-13 05:52:11 +000018#include "clang/Lex/HeaderSearch.h"
19#include "clang/Lex/Preprocessor.h"
20#include "clang/Lex/PTHManager.h"
Daniel Dunbar0fbb3d92009-11-13 05:52:34 +000021#include "clang/Frontend/ChainedDiagnosticClient.h"
Daniel Dunbar0397af22010-01-13 00:48:06 +000022#include "clang/Frontend/FrontendAction.h"
Daniel Dunbar0f800392009-11-13 08:21:10 +000023#include "clang/Frontend/PCHReader.h"
Daniel Dunbarc2f484f2009-11-13 09:36:05 +000024#include "clang/Frontend/FrontendDiagnostic.h"
Daniel Dunbar0fbb3d92009-11-13 05:52:34 +000025#include "clang/Frontend/TextDiagnosticPrinter.h"
Daniel Dunbarf79dced2009-11-14 03:24:39 +000026#include "clang/Frontend/VerifyDiagnosticsClient.h"
Daniel Dunbar22dacfa2009-11-13 05:52:11 +000027#include "clang/Frontend/Utils.h"
Daniel Dunbarc2f484f2009-11-13 09:36:05 +000028#include "clang/Sema/CodeCompleteConsumer.h"
Daniel Dunbar2a79e162009-11-13 03:51:44 +000029#include "llvm/LLVMContext.h"
Daniel Dunbarccb6cb62009-11-14 07:53:04 +000030#include "llvm/Support/MemoryBuffer.h"
Daniel Dunbar0fbb3d92009-11-13 05:52:34 +000031#include "llvm/Support/raw_ostream.h"
Kovarththanan Rajaratnamf79bafa2009-11-29 09:57:35 +000032#include "llvm/Support/Timer.h"
Daniel Dunbar0397af22010-01-13 00:48:06 +000033#include "llvm/System/Host.h"
Daniel Dunbara9204832009-11-13 10:37:48 +000034#include "llvm/System/Path.h"
Douglas Gregor2b4074f2009-12-01 05:55:20 +000035#include "llvm/System/Program.h"
Daniel Dunbar2a79e162009-11-13 03:51:44 +000036using namespace clang;
37
Daniel Dunbar42e9f8e42010-02-16 01:54:47 +000038CompilerInstance::CompilerInstance()
39 : Invocation(new CompilerInvocation()) {
Daniel Dunbar6228ca02010-01-30 21:47:07 +000040}
Daniel Dunbar2a79e162009-11-13 03:51:44 +000041
42CompilerInstance::~CompilerInstance() {
Daniel Dunbar42e9f8e42010-02-16 01:54:47 +000043}
44
45void CompilerInstance::setLLVMContext(llvm::LLVMContext *Value) {
46 LLVMContext.reset(Value);
Daniel Dunbar2a79e162009-11-13 03:51:44 +000047}
Daniel Dunbar16b74492009-11-13 04:12:06 +000048
Daniel Dunbar6228ca02010-01-30 21:47:07 +000049void CompilerInstance::setInvocation(CompilerInvocation *Value) {
50 Invocation.reset(Value);
51}
52
Daniel Dunbar8a9f5692009-11-14 01:20:40 +000053void CompilerInstance::setDiagnostics(Diagnostic *Value) {
54 Diagnostics.reset(Value);
55}
56
57void CompilerInstance::setDiagnosticClient(DiagnosticClient *Value) {
58 DiagClient.reset(Value);
59}
60
61void CompilerInstance::setTarget(TargetInfo *Value) {
62 Target.reset(Value);
63}
64
65void CompilerInstance::setFileManager(FileManager *Value) {
66 FileMgr.reset(Value);
67}
68
69void CompilerInstance::setSourceManager(SourceManager *Value) {
70 SourceMgr.reset(Value);
71}
72
73void CompilerInstance::setPreprocessor(Preprocessor *Value) {
74 PP.reset(Value);
75}
76
77void CompilerInstance::setASTContext(ASTContext *Value) {
78 Context.reset(Value);
79}
80
Daniel Dunbar12ce6942009-11-14 02:47:17 +000081void CompilerInstance::setASTConsumer(ASTConsumer *Value) {
82 Consumer.reset(Value);
83}
84
Daniel Dunbar8a9f5692009-11-14 01:20:40 +000085void CompilerInstance::setCodeCompletionConsumer(CodeCompleteConsumer *Value) {
86 CompletionConsumer.reset(Value);
87}
88
Daniel Dunbar0fbb3d92009-11-13 05:52:34 +000089// Diagnostics
Douglas Gregord93256e2010-01-28 06:00:51 +000090namespace {
91 class BinaryDiagnosticSerializer : public DiagnosticClient {
92 llvm::raw_ostream &OS;
93 SourceManager *SourceMgr;
94 public:
95 explicit BinaryDiagnosticSerializer(llvm::raw_ostream &OS)
96 : OS(OS), SourceMgr(0) { }
Kovarththanan Rajaratname51dd7b2010-03-06 12:07:48 +000097
Douglas Gregord93256e2010-01-28 06:00:51 +000098 virtual void HandleDiagnostic(Diagnostic::Level DiagLevel,
99 const DiagnosticInfo &Info);
100 };
101}
102
103void BinaryDiagnosticSerializer::HandleDiagnostic(Diagnostic::Level DiagLevel,
104 const DiagnosticInfo &Info) {
Douglas Gregora88084b2010-02-18 18:08:43 +0000105 StoredDiagnostic(DiagLevel, Info).Serialize(OS);
Douglas Gregord93256e2010-01-28 06:00:51 +0000106}
Daniel Dunbar0fbb3d92009-11-13 05:52:34 +0000107
108static void SetUpBuildDumpLog(const DiagnosticOptions &DiagOpts,
109 unsigned argc, char **argv,
Kovarththanan Rajaratnam3d67b1e2010-03-17 09:24:48 +0000110 Diagnostic &Diags) {
Daniel Dunbar0fbb3d92009-11-13 05:52:34 +0000111 std::string ErrorInfo;
Kovarththanan Rajaratnam69247132010-03-17 09:47:30 +0000112 llvm::OwningPtr<llvm::raw_ostream> OS(
113 new llvm::raw_fd_ostream(DiagOpts.DumpBuildInformation.c_str(), ErrorInfo));
Daniel Dunbar0fbb3d92009-11-13 05:52:34 +0000114 if (!ErrorInfo.empty()) {
Kovarththanan Rajaratnam3d67b1e2010-03-17 09:24:48 +0000115 Diags.Report(diag::err_fe_unable_to_open_logfile)
116 << DiagOpts.DumpBuildInformation << ErrorInfo;
Daniel Dunbar0fbb3d92009-11-13 05:52:34 +0000117 return;
118 }
119
Daniel Dunbardd63b282009-12-11 23:04:35 +0000120 (*OS) << "clang -cc1 command line arguments: ";
Daniel Dunbar0fbb3d92009-11-13 05:52:34 +0000121 for (unsigned i = 0; i != argc; ++i)
122 (*OS) << argv[i] << ' ';
123 (*OS) << '\n';
124
125 // Chain in a diagnostic client which will log the diagnostics.
126 DiagnosticClient *Logger =
Kovarththanan Rajaratnam69247132010-03-17 09:47:30 +0000127 new TextDiagnosticPrinter(*OS.take(), DiagOpts, /*OwnsOutputStream=*/true);
Kovarththanan Rajaratnam3d67b1e2010-03-17 09:24:48 +0000128 Diags.setClient(new ChainedDiagnosticClient(Diags.getClient(), Logger));
Daniel Dunbar0fbb3d92009-11-13 05:52:34 +0000129}
130
131void CompilerInstance::createDiagnostics(int Argc, char **Argv) {
132 Diagnostics.reset(createDiagnostics(getDiagnosticOpts(), Argc, Argv));
133
134 if (Diagnostics)
135 DiagClient.reset(Diagnostics->getClient());
136}
137
138Diagnostic *CompilerInstance::createDiagnostics(const DiagnosticOptions &Opts,
139 int Argc, char **Argv) {
Daniel Dunbar221c7212009-11-14 07:53:24 +0000140 llvm::OwningPtr<Diagnostic> Diags(new Diagnostic());
141
Daniel Dunbar0fbb3d92009-11-13 05:52:34 +0000142 // Create the diagnostic client for reporting errors or for
143 // implementing -verify.
Douglas Gregord93256e2010-01-28 06:00:51 +0000144 llvm::OwningPtr<DiagnosticClient> DiagClient;
145 if (Opts.BinaryOutput) {
146 if (llvm::sys::Program::ChangeStderrToBinary()) {
147 // We weren't able to set standard error to binary, which is a
148 // bit of a problem. So, just create a text diagnostic printer
149 // to complain about this problem, and pretend that the user
150 // didn't try to use binary output.
151 DiagClient.reset(new TextDiagnosticPrinter(llvm::errs(), Opts));
152 Diags->setClient(DiagClient.take());
153 Diags->Report(diag::err_fe_stderr_binary);
154 return Diags.take();
155 } else {
156 DiagClient.reset(new BinaryDiagnosticSerializer(llvm::errs()));
157 }
158 } else {
159 DiagClient.reset(new TextDiagnosticPrinter(llvm::errs(), Opts));
160 }
Daniel Dunbarf79dced2009-11-14 03:24:39 +0000161
162 // Chain in -verify checker, if requested.
163 if (Opts.VerifyDiagnostics)
Daniel Dunbar221c7212009-11-14 07:53:24 +0000164 DiagClient.reset(new VerifyDiagnosticsClient(*Diags, DiagClient.take()));
Daniel Dunbar0fbb3d92009-11-13 05:52:34 +0000165
Kovarththanan Rajaratnam3d67b1e2010-03-17 09:24:48 +0000166 Diags->setClient(DiagClient.take());
Daniel Dunbar0fbb3d92009-11-13 05:52:34 +0000167 if (!Opts.DumpBuildInformation.empty())
Kovarththanan Rajaratnam3d67b1e2010-03-17 09:24:48 +0000168 SetUpBuildDumpLog(Opts, Argc, Argv, *Diags);
Daniel Dunbar0fbb3d92009-11-13 05:52:34 +0000169
170 // Configure our handling of diagnostics.
Kovarththanan Rajaratnam5bf932b2010-03-17 09:36:02 +0000171 ProcessWarningOptions(*Diags, Opts);
Daniel Dunbar0fbb3d92009-11-13 05:52:34 +0000172
Daniel Dunbar221c7212009-11-14 07:53:24 +0000173 return Diags.take();
Daniel Dunbar0fbb3d92009-11-13 05:52:34 +0000174}
175
176// File Manager
177
Daniel Dunbar16b74492009-11-13 04:12:06 +0000178void CompilerInstance::createFileManager() {
179 FileMgr.reset(new FileManager());
180}
181
Daniel Dunbar0fbb3d92009-11-13 05:52:34 +0000182// Source Manager
183
Daniel Dunbar16b74492009-11-13 04:12:06 +0000184void CompilerInstance::createSourceManager() {
Douglas Gregorf715ca12010-03-16 00:06:06 +0000185 SourceMgr.reset(new SourceManager(getDiagnostics()));
Daniel Dunbar16b74492009-11-13 04:12:06 +0000186}
Daniel Dunbar22dacfa2009-11-13 05:52:11 +0000187
Daniel Dunbar0fbb3d92009-11-13 05:52:34 +0000188// Preprocessor
189
Daniel Dunbar22dacfa2009-11-13 05:52:11 +0000190void CompilerInstance::createPreprocessor() {
191 PP.reset(createPreprocessor(getDiagnostics(), getLangOpts(),
192 getPreprocessorOpts(), getHeaderSearchOpts(),
193 getDependencyOutputOpts(), getTarget(),
Fariborz Jahanian7d957472010-01-13 18:51:17 +0000194 getFrontendOpts(), getSourceManager(),
195 getFileManager()));
Daniel Dunbar22dacfa2009-11-13 05:52:11 +0000196}
197
198Preprocessor *
199CompilerInstance::createPreprocessor(Diagnostic &Diags,
200 const LangOptions &LangInfo,
201 const PreprocessorOptions &PPOpts,
202 const HeaderSearchOptions &HSOpts,
203 const DependencyOutputOptions &DepOpts,
204 const TargetInfo &Target,
Fariborz Jahanian7d957472010-01-13 18:51:17 +0000205 const FrontendOptions &FEOpts,
Daniel Dunbar22dacfa2009-11-13 05:52:11 +0000206 SourceManager &SourceMgr,
207 FileManager &FileMgr) {
208 // Create a PTH manager if we are using some form of a token cache.
209 PTHManager *PTHMgr = 0;
Daniel Dunbar049d3a02009-11-17 05:52:41 +0000210 if (!PPOpts.TokenCache.empty())
211 PTHMgr = PTHManager::Create(PPOpts.TokenCache, Diags);
Daniel Dunbar22dacfa2009-11-13 05:52:11 +0000212
Daniel Dunbar22dacfa2009-11-13 05:52:11 +0000213 // Create the Preprocessor.
214 HeaderSearch *HeaderInfo = new HeaderSearch(FileMgr);
215 Preprocessor *PP = new Preprocessor(Diags, LangInfo, Target,
216 SourceMgr, *HeaderInfo, PTHMgr,
217 /*OwnsHeaderSearch=*/true);
218
219 // Note that this is different then passing PTHMgr to Preprocessor's ctor.
220 // That argument is used as the IdentifierInfoLookup argument to
221 // IdentifierTable's ctor.
222 if (PTHMgr) {
223 PTHMgr->setPreprocessor(PP);
224 PP->setPTHManager(PTHMgr);
225 }
226
Fariborz Jahanian7d957472010-01-13 18:51:17 +0000227 InitializePreprocessor(*PP, PPOpts, HSOpts, FEOpts);
Daniel Dunbar22dacfa2009-11-13 05:52:11 +0000228
229 // Handle generating dependencies, if requested.
230 if (!DepOpts.OutputFile.empty())
231 AttachDependencyFileGen(*PP, DepOpts);
232
233 return PP;
234}
Daniel Dunbar5eb81002009-11-13 08:20:47 +0000235
236// ASTContext
237
238void CompilerInstance::createASTContext() {
239 Preprocessor &PP = getPreprocessor();
240 Context.reset(new ASTContext(getLangOpts(), PP.getSourceManager(),
241 getTarget(), PP.getIdentifierTable(),
242 PP.getSelectorTable(), PP.getBuiltinInfo(),
243 /*FreeMemory=*/ !getFrontendOpts().DisableFree,
244 /*size_reserve=*/ 0));
245}
Daniel Dunbar0f800392009-11-13 08:21:10 +0000246
247// ExternalASTSource
248
249void CompilerInstance::createPCHExternalASTSource(llvm::StringRef Path) {
250 llvm::OwningPtr<ExternalASTSource> Source;
251 Source.reset(createPCHExternalASTSource(Path, getHeaderSearchOpts().Sysroot,
252 getPreprocessor(), getASTContext()));
253 getASTContext().setExternalSource(Source);
254}
255
256ExternalASTSource *
257CompilerInstance::createPCHExternalASTSource(llvm::StringRef Path,
258 const std::string &Sysroot,
259 Preprocessor &PP,
260 ASTContext &Context) {
261 llvm::OwningPtr<PCHReader> Reader;
262 Reader.reset(new PCHReader(PP, &Context,
263 Sysroot.empty() ? 0 : Sysroot.c_str()));
264
265 switch (Reader->ReadPCH(Path)) {
266 case PCHReader::Success:
267 // Set the predefines buffer as suggested by the PCH reader. Typically, the
268 // predefines buffer will be empty.
269 PP.setPredefines(Reader->getSuggestedPredefines());
270 return Reader.take();
271
272 case PCHReader::Failure:
273 // Unrecoverable failure: don't even try to process the input file.
274 break;
275
276 case PCHReader::IgnorePCH:
277 // No suitable PCH file could be found. Return an error.
278 break;
279 }
280
281 return 0;
282}
Daniel Dunbarc2f484f2009-11-13 09:36:05 +0000283
284// Code Completion
285
286void CompilerInstance::createCodeCompletionConsumer() {
287 const ParsedSourceLocation &Loc = getFrontendOpts().CodeCompletionAt;
288 CompletionConsumer.reset(
289 createCodeCompletionConsumer(getPreprocessor(),
290 Loc.FileName, Loc.Line, Loc.Column,
291 getFrontendOpts().DebugCodeCompletionPrinter,
292 getFrontendOpts().ShowMacrosInCodeCompletion,
293 llvm::outs()));
Douglas Gregorc3d43b72010-03-16 06:04:47 +0000294 if (!CompletionConsumer)
295 return;
Douglas Gregor2b4074f2009-12-01 05:55:20 +0000296
297 if (CompletionConsumer->isOutputBinary() &&
298 llvm::sys::Program::ChangeStdoutToBinary()) {
299 getPreprocessor().getDiagnostics().Report(diag::err_fe_stdout_binary);
300 CompletionConsumer.reset();
301 }
Daniel Dunbarc2f484f2009-11-13 09:36:05 +0000302}
303
Kovarththanan Rajaratnamf79bafa2009-11-29 09:57:35 +0000304void CompilerInstance::createFrontendTimer() {
305 FrontendTimer.reset(new llvm::Timer("Clang front-end timer"));
306}
307
Daniel Dunbarc2f484f2009-11-13 09:36:05 +0000308CodeCompleteConsumer *
309CompilerInstance::createCodeCompletionConsumer(Preprocessor &PP,
310 const std::string &Filename,
311 unsigned Line,
312 unsigned Column,
313 bool UseDebugPrinter,
314 bool ShowMacros,
315 llvm::raw_ostream &OS) {
316 // Tell the source manager to chop off the given file at a specific
317 // line and column.
318 const FileEntry *Entry = PP.getFileManager().getFile(Filename);
319 if (!Entry) {
320 PP.getDiagnostics().Report(diag::err_fe_invalid_code_complete_file)
321 << Filename;
322 return 0;
323 }
324
325 // Truncate the named file at the given line/column.
Douglas Gregor29684422009-12-02 06:49:09 +0000326 PP.SetCodeCompletionPoint(Entry, Line, Column);
Daniel Dunbarc2f484f2009-11-13 09:36:05 +0000327
328 // Set up the creation routine for code-completion.
329 if (UseDebugPrinter)
330 return new PrintingCodeCompleteConsumer(ShowMacros, OS);
331 else
332 return new CIndexCodeCompleteConsumer(ShowMacros, OS);
333}
Daniel Dunbara9204832009-11-13 10:37:48 +0000334
335// Output Files
336
337void CompilerInstance::addOutputFile(llvm::StringRef Path,
338 llvm::raw_ostream *OS) {
339 assert(OS && "Attempt to add empty stream to output list!");
340 OutputFiles.push_back(std::make_pair(Path, OS));
341}
342
Kovarththanan Rajaratname51dd7b2010-03-06 12:07:48 +0000343void CompilerInstance::clearOutputFiles(bool EraseFiles) {
Daniel Dunbara9204832009-11-13 10:37:48 +0000344 for (std::list< std::pair<std::string, llvm::raw_ostream*> >::iterator
345 it = OutputFiles.begin(), ie = OutputFiles.end(); it != ie; ++it) {
346 delete it->second;
347 if (EraseFiles && !it->first.empty())
348 llvm::sys::Path(it->first).eraseFromDisk();
349 }
350 OutputFiles.clear();
351}
352
Daniel Dunbarf482d592009-11-13 18:32:08 +0000353llvm::raw_fd_ostream *
354CompilerInstance::createDefaultOutputFile(bool Binary,
355 llvm::StringRef InFile,
356 llvm::StringRef Extension) {
357 return createOutputFile(getFrontendOpts().OutputFile, Binary,
358 InFile, Extension);
359}
360
361llvm::raw_fd_ostream *
362CompilerInstance::createOutputFile(llvm::StringRef OutputPath,
363 bool Binary,
364 llvm::StringRef InFile,
365 llvm::StringRef Extension) {
366 std::string Error, OutputPathName;
367 llvm::raw_fd_ostream *OS = createOutputFile(OutputPath, Error, Binary,
368 InFile, Extension,
369 &OutputPathName);
370 if (!OS) {
Daniel Dunbar36043592009-12-03 09:13:30 +0000371 getDiagnostics().Report(diag::err_fe_unable_to_open_output)
372 << OutputPath << Error;
373 return 0;
Daniel Dunbarf482d592009-11-13 18:32:08 +0000374 }
375
376 // Add the output file -- but don't try to remove "-", since this means we are
377 // using stdin.
378 addOutputFile((OutputPathName != "-") ? OutputPathName : "", OS);
379
380 return OS;
381}
382
383llvm::raw_fd_ostream *
384CompilerInstance::createOutputFile(llvm::StringRef OutputPath,
385 std::string &Error,
386 bool Binary,
387 llvm::StringRef InFile,
388 llvm::StringRef Extension,
389 std::string *ResultPathName) {
390 std::string OutFile;
391 if (!OutputPath.empty()) {
392 OutFile = OutputPath;
393 } else if (InFile == "-") {
394 OutFile = "-";
395 } else if (!Extension.empty()) {
396 llvm::sys::Path Path(InFile);
397 Path.eraseSuffix();
398 Path.appendSuffix(Extension);
399 OutFile = Path.str();
400 } else {
401 OutFile = "-";
402 }
403
Daniel Dunbarfc971022009-11-20 22:32:38 +0000404 llvm::OwningPtr<llvm::raw_fd_ostream> OS(
Daniel Dunbarf482d592009-11-13 18:32:08 +0000405 new llvm::raw_fd_ostream(OutFile.c_str(), Error,
Daniel Dunbarfc971022009-11-20 22:32:38 +0000406 (Binary ? llvm::raw_fd_ostream::F_Binary : 0)));
407 if (!Error.empty())
Daniel Dunbarf482d592009-11-13 18:32:08 +0000408 return 0;
409
410 if (ResultPathName)
411 *ResultPathName = OutFile;
412
Daniel Dunbarfc971022009-11-20 22:32:38 +0000413 return OS.take();
Daniel Dunbarf482d592009-11-13 18:32:08 +0000414}
Daniel Dunbarccb6cb62009-11-14 07:53:04 +0000415
416// Initialization Utilities
417
418bool CompilerInstance::InitializeSourceManager(llvm::StringRef InputFile) {
419 return InitializeSourceManager(InputFile, getDiagnostics(), getFileManager(),
420 getSourceManager(), getFrontendOpts());
421}
422
423bool CompilerInstance::InitializeSourceManager(llvm::StringRef InputFile,
424 Diagnostic &Diags,
425 FileManager &FileMgr,
426 SourceManager &SourceMgr,
427 const FrontendOptions &Opts) {
428 // Figure out where to get and map in the main file.
429 if (Opts.EmptyInputOnly) {
430 const char *EmptyStr = "";
431 llvm::MemoryBuffer *SB =
432 llvm::MemoryBuffer::getMemBuffer(EmptyStr, EmptyStr, "<empty input>");
433 SourceMgr.createMainFileIDForMemBuffer(SB);
434 } else if (InputFile != "-") {
435 const FileEntry *File = FileMgr.getFile(InputFile);
436 if (File) SourceMgr.createMainFileID(File, SourceLocation());
437 if (SourceMgr.getMainFileID().isInvalid()) {
438 Diags.Report(diag::err_fe_error_reading) << InputFile;
439 return false;
440 }
441 } else {
442 llvm::MemoryBuffer *SB = llvm::MemoryBuffer::getSTDIN();
443 SourceMgr.createMainFileIDForMemBuffer(SB);
444 if (SourceMgr.getMainFileID().isInvalid()) {
445 Diags.Report(diag::err_fe_error_reading_stdin);
446 return false;
447 }
448 }
449
450 return true;
451}
Daniel Dunbar0397af22010-01-13 00:48:06 +0000452
453// High-Level Operations
454
455bool CompilerInstance::ExecuteAction(FrontendAction &Act) {
456 assert(hasDiagnostics() && "Diagnostics engine is not initialized!");
457 assert(!getFrontendOpts().ShowHelp && "Client must handle '-help'!");
458 assert(!getFrontendOpts().ShowVersion && "Client must handle '-version'!");
459
460 // FIXME: Take this as an argument, once all the APIs we used have moved to
461 // taking it as an input instead of hard-coding llvm::errs.
462 llvm::raw_ostream &OS = llvm::errs();
463
464 // Create the target instance.
465 setTarget(TargetInfo::CreateTargetInfo(getDiagnostics(), getTargetOpts()));
466 if (!hasTarget())
467 return false;
468
469 // Inform the target of the language options.
470 //
471 // FIXME: We shouldn't need to do this, the target should be immutable once
472 // created. This complexity should be lifted elsewhere.
473 getTarget().setForcedLangOptions(getLangOpts());
474
475 // Validate/process some options.
476 if (getHeaderSearchOpts().Verbose)
477 OS << "clang -cc1 version " CLANG_VERSION_STRING
478 << " based upon " << PACKAGE_STRING
479 << " hosted on " << llvm::sys::getHostTriple() << "\n";
480
481 if (getFrontendOpts().ShowTimers)
482 createFrontendTimer();
483
484 for (unsigned i = 0, e = getFrontendOpts().Inputs.size(); i != e; ++i) {
485 const std::string &InFile = getFrontendOpts().Inputs[i].second;
486
487 // If we aren't using an AST file, setup the file and source managers and
488 // the preprocessor.
489 bool IsAST = getFrontendOpts().Inputs[i].first == FrontendOptions::IK_AST;
490 if (!IsAST) {
491 if (!i) {
492 // Create a file manager object to provide access to and cache the
493 // filesystem.
494 createFileManager();
495
496 // Create the source manager.
497 createSourceManager();
498 } else {
499 // Reset the ID tables if we are reusing the SourceManager.
500 getSourceManager().clearIDTables();
501 }
502
503 // Create the preprocessor.
504 createPreprocessor();
505 }
506
507 if (Act.BeginSourceFile(*this, InFile, IsAST)) {
508 Act.Execute();
509 Act.EndSourceFile();
510 }
511 }
512
513 if (getDiagnosticOpts().ShowCarets)
514 if (unsigned NumDiagnostics = getDiagnostics().getNumDiagnostics())
515 OS << NumDiagnostics << " diagnostic"
516 << (NumDiagnostics == 1 ? "" : "s")
517 << " generated.\n";
518
519 if (getFrontendOpts().ShowStats) {
520 getFileManager().PrintStats();
521 OS << "\n";
522 }
523
524 // Return the appropriate status when verifying diagnostics.
525 //
526 // FIXME: If we could make getNumErrors() do the right thing, we wouldn't need
527 // this.
528 if (getDiagnosticOpts().VerifyDiagnostics)
529 return !static_cast<VerifyDiagnosticsClient&>(
530 getDiagnosticClient()).HadErrors();
531
532 return !getDiagnostics().getNumErrors();
533}
534
535