blob: 7b4932d787a1d78df733acd73b56befb2359d429 [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
Douglas Gregor94dc8f62010-03-19 16:15:56 +0000227 if (PPOpts.DetailedRecord)
228 PP->createPreprocessingRecord();
229
Fariborz Jahanian7d957472010-01-13 18:51:17 +0000230 InitializePreprocessor(*PP, PPOpts, HSOpts, FEOpts);
Daniel Dunbar22dacfa2009-11-13 05:52:11 +0000231
232 // Handle generating dependencies, if requested.
233 if (!DepOpts.OutputFile.empty())
234 AttachDependencyFileGen(*PP, DepOpts);
235
236 return PP;
237}
Daniel Dunbar5eb81002009-11-13 08:20:47 +0000238
239// ASTContext
240
241void CompilerInstance::createASTContext() {
242 Preprocessor &PP = getPreprocessor();
243 Context.reset(new ASTContext(getLangOpts(), PP.getSourceManager(),
244 getTarget(), PP.getIdentifierTable(),
245 PP.getSelectorTable(), PP.getBuiltinInfo(),
246 /*FreeMemory=*/ !getFrontendOpts().DisableFree,
247 /*size_reserve=*/ 0));
248}
Daniel Dunbar0f800392009-11-13 08:21:10 +0000249
250// ExternalASTSource
251
252void CompilerInstance::createPCHExternalASTSource(llvm::StringRef Path) {
253 llvm::OwningPtr<ExternalASTSource> Source;
254 Source.reset(createPCHExternalASTSource(Path, getHeaderSearchOpts().Sysroot,
255 getPreprocessor(), getASTContext()));
256 getASTContext().setExternalSource(Source);
257}
258
259ExternalASTSource *
260CompilerInstance::createPCHExternalASTSource(llvm::StringRef Path,
261 const std::string &Sysroot,
262 Preprocessor &PP,
263 ASTContext &Context) {
264 llvm::OwningPtr<PCHReader> Reader;
265 Reader.reset(new PCHReader(PP, &Context,
266 Sysroot.empty() ? 0 : Sysroot.c_str()));
267
268 switch (Reader->ReadPCH(Path)) {
269 case PCHReader::Success:
270 // Set the predefines buffer as suggested by the PCH reader. Typically, the
271 // predefines buffer will be empty.
272 PP.setPredefines(Reader->getSuggestedPredefines());
273 return Reader.take();
274
275 case PCHReader::Failure:
276 // Unrecoverable failure: don't even try to process the input file.
277 break;
278
279 case PCHReader::IgnorePCH:
280 // No suitable PCH file could be found. Return an error.
281 break;
282 }
283
284 return 0;
285}
Daniel Dunbarc2f484f2009-11-13 09:36:05 +0000286
287// Code Completion
288
289void CompilerInstance::createCodeCompletionConsumer() {
290 const ParsedSourceLocation &Loc = getFrontendOpts().CodeCompletionAt;
291 CompletionConsumer.reset(
292 createCodeCompletionConsumer(getPreprocessor(),
293 Loc.FileName, Loc.Line, Loc.Column,
294 getFrontendOpts().DebugCodeCompletionPrinter,
295 getFrontendOpts().ShowMacrosInCodeCompletion,
296 llvm::outs()));
Douglas Gregorc3d43b72010-03-16 06:04:47 +0000297 if (!CompletionConsumer)
298 return;
Douglas Gregor2b4074f2009-12-01 05:55:20 +0000299
300 if (CompletionConsumer->isOutputBinary() &&
301 llvm::sys::Program::ChangeStdoutToBinary()) {
302 getPreprocessor().getDiagnostics().Report(diag::err_fe_stdout_binary);
303 CompletionConsumer.reset();
304 }
Daniel Dunbarc2f484f2009-11-13 09:36:05 +0000305}
306
Kovarththanan Rajaratnamf79bafa2009-11-29 09:57:35 +0000307void CompilerInstance::createFrontendTimer() {
308 FrontendTimer.reset(new llvm::Timer("Clang front-end timer"));
309}
310
Daniel Dunbarc2f484f2009-11-13 09:36:05 +0000311CodeCompleteConsumer *
312CompilerInstance::createCodeCompletionConsumer(Preprocessor &PP,
313 const std::string &Filename,
314 unsigned Line,
315 unsigned Column,
316 bool UseDebugPrinter,
317 bool ShowMacros,
318 llvm::raw_ostream &OS) {
319 // Tell the source manager to chop off the given file at a specific
320 // line and column.
321 const FileEntry *Entry = PP.getFileManager().getFile(Filename);
322 if (!Entry) {
323 PP.getDiagnostics().Report(diag::err_fe_invalid_code_complete_file)
324 << Filename;
325 return 0;
326 }
327
328 // Truncate the named file at the given line/column.
Douglas Gregor29684422009-12-02 06:49:09 +0000329 PP.SetCodeCompletionPoint(Entry, Line, Column);
Daniel Dunbarc2f484f2009-11-13 09:36:05 +0000330
331 // Set up the creation routine for code-completion.
332 if (UseDebugPrinter)
333 return new PrintingCodeCompleteConsumer(ShowMacros, OS);
334 else
335 return new CIndexCodeCompleteConsumer(ShowMacros, OS);
336}
Daniel Dunbara9204832009-11-13 10:37:48 +0000337
338// Output Files
339
340void CompilerInstance::addOutputFile(llvm::StringRef Path,
341 llvm::raw_ostream *OS) {
342 assert(OS && "Attempt to add empty stream to output list!");
343 OutputFiles.push_back(std::make_pair(Path, OS));
344}
345
Kovarththanan Rajaratname51dd7b2010-03-06 12:07:48 +0000346void CompilerInstance::clearOutputFiles(bool EraseFiles) {
Daniel Dunbara9204832009-11-13 10:37:48 +0000347 for (std::list< std::pair<std::string, llvm::raw_ostream*> >::iterator
348 it = OutputFiles.begin(), ie = OutputFiles.end(); it != ie; ++it) {
349 delete it->second;
350 if (EraseFiles && !it->first.empty())
351 llvm::sys::Path(it->first).eraseFromDisk();
352 }
353 OutputFiles.clear();
354}
355
Daniel Dunbarf482d592009-11-13 18:32:08 +0000356llvm::raw_fd_ostream *
357CompilerInstance::createDefaultOutputFile(bool Binary,
358 llvm::StringRef InFile,
359 llvm::StringRef Extension) {
360 return createOutputFile(getFrontendOpts().OutputFile, Binary,
361 InFile, Extension);
362}
363
364llvm::raw_fd_ostream *
365CompilerInstance::createOutputFile(llvm::StringRef OutputPath,
366 bool Binary,
367 llvm::StringRef InFile,
368 llvm::StringRef Extension) {
369 std::string Error, OutputPathName;
370 llvm::raw_fd_ostream *OS = createOutputFile(OutputPath, Error, Binary,
371 InFile, Extension,
372 &OutputPathName);
373 if (!OS) {
Daniel Dunbar36043592009-12-03 09:13:30 +0000374 getDiagnostics().Report(diag::err_fe_unable_to_open_output)
375 << OutputPath << Error;
376 return 0;
Daniel Dunbarf482d592009-11-13 18:32:08 +0000377 }
378
379 // Add the output file -- but don't try to remove "-", since this means we are
380 // using stdin.
381 addOutputFile((OutputPathName != "-") ? OutputPathName : "", OS);
382
383 return OS;
384}
385
386llvm::raw_fd_ostream *
387CompilerInstance::createOutputFile(llvm::StringRef OutputPath,
388 std::string &Error,
389 bool Binary,
390 llvm::StringRef InFile,
391 llvm::StringRef Extension,
392 std::string *ResultPathName) {
393 std::string OutFile;
394 if (!OutputPath.empty()) {
395 OutFile = OutputPath;
396 } else if (InFile == "-") {
397 OutFile = "-";
398 } else if (!Extension.empty()) {
399 llvm::sys::Path Path(InFile);
400 Path.eraseSuffix();
401 Path.appendSuffix(Extension);
402 OutFile = Path.str();
403 } else {
404 OutFile = "-";
405 }
406
Daniel Dunbarfc971022009-11-20 22:32:38 +0000407 llvm::OwningPtr<llvm::raw_fd_ostream> OS(
Daniel Dunbarf482d592009-11-13 18:32:08 +0000408 new llvm::raw_fd_ostream(OutFile.c_str(), Error,
Daniel Dunbarfc971022009-11-20 22:32:38 +0000409 (Binary ? llvm::raw_fd_ostream::F_Binary : 0)));
410 if (!Error.empty())
Daniel Dunbarf482d592009-11-13 18:32:08 +0000411 return 0;
412
413 if (ResultPathName)
414 *ResultPathName = OutFile;
415
Daniel Dunbarfc971022009-11-20 22:32:38 +0000416 return OS.take();
Daniel Dunbarf482d592009-11-13 18:32:08 +0000417}
Daniel Dunbarccb6cb62009-11-14 07:53:04 +0000418
419// Initialization Utilities
420
421bool CompilerInstance::InitializeSourceManager(llvm::StringRef InputFile) {
422 return InitializeSourceManager(InputFile, getDiagnostics(), getFileManager(),
423 getSourceManager(), getFrontendOpts());
424}
425
426bool CompilerInstance::InitializeSourceManager(llvm::StringRef InputFile,
427 Diagnostic &Diags,
428 FileManager &FileMgr,
429 SourceManager &SourceMgr,
430 const FrontendOptions &Opts) {
431 // Figure out where to get and map in the main file.
Daniel Dunbar27585952010-03-19 19:44:04 +0000432 if (InputFile != "-") {
Daniel Dunbarccb6cb62009-11-14 07:53:04 +0000433 const FileEntry *File = FileMgr.getFile(InputFile);
434 if (File) SourceMgr.createMainFileID(File, SourceLocation());
435 if (SourceMgr.getMainFileID().isInvalid()) {
436 Diags.Report(diag::err_fe_error_reading) << InputFile;
437 return false;
438 }
439 } else {
440 llvm::MemoryBuffer *SB = llvm::MemoryBuffer::getSTDIN();
441 SourceMgr.createMainFileIDForMemBuffer(SB);
442 if (SourceMgr.getMainFileID().isInvalid()) {
443 Diags.Report(diag::err_fe_error_reading_stdin);
444 return false;
445 }
446 }
447
448 return true;
449}
Daniel Dunbar0397af22010-01-13 00:48:06 +0000450
451// High-Level Operations
452
453bool CompilerInstance::ExecuteAction(FrontendAction &Act) {
454 assert(hasDiagnostics() && "Diagnostics engine is not initialized!");
455 assert(!getFrontendOpts().ShowHelp && "Client must handle '-help'!");
456 assert(!getFrontendOpts().ShowVersion && "Client must handle '-version'!");
457
458 // FIXME: Take this as an argument, once all the APIs we used have moved to
459 // taking it as an input instead of hard-coding llvm::errs.
460 llvm::raw_ostream &OS = llvm::errs();
461
462 // Create the target instance.
463 setTarget(TargetInfo::CreateTargetInfo(getDiagnostics(), getTargetOpts()));
464 if (!hasTarget())
465 return false;
466
467 // Inform the target of the language options.
468 //
469 // FIXME: We shouldn't need to do this, the target should be immutable once
470 // created. This complexity should be lifted elsewhere.
471 getTarget().setForcedLangOptions(getLangOpts());
472
473 // Validate/process some options.
474 if (getHeaderSearchOpts().Verbose)
475 OS << "clang -cc1 version " CLANG_VERSION_STRING
476 << " based upon " << PACKAGE_STRING
477 << " hosted on " << llvm::sys::getHostTriple() << "\n";
478
479 if (getFrontendOpts().ShowTimers)
480 createFrontendTimer();
481
482 for (unsigned i = 0, e = getFrontendOpts().Inputs.size(); i != e; ++i) {
483 const std::string &InFile = getFrontendOpts().Inputs[i].second;
484
485 // If we aren't using an AST file, setup the file and source managers and
486 // the preprocessor.
487 bool IsAST = getFrontendOpts().Inputs[i].first == FrontendOptions::IK_AST;
488 if (!IsAST) {
489 if (!i) {
490 // Create a file manager object to provide access to and cache the
491 // filesystem.
492 createFileManager();
493
494 // Create the source manager.
495 createSourceManager();
496 } else {
497 // Reset the ID tables if we are reusing the SourceManager.
498 getSourceManager().clearIDTables();
499 }
500
501 // Create the preprocessor.
502 createPreprocessor();
503 }
504
505 if (Act.BeginSourceFile(*this, InFile, IsAST)) {
506 Act.Execute();
507 Act.EndSourceFile();
508 }
509 }
510
511 if (getDiagnosticOpts().ShowCarets)
512 if (unsigned NumDiagnostics = getDiagnostics().getNumDiagnostics())
513 OS << NumDiagnostics << " diagnostic"
514 << (NumDiagnostics == 1 ? "" : "s")
515 << " generated.\n";
516
517 if (getFrontendOpts().ShowStats) {
518 getFileManager().PrintStats();
519 OS << "\n";
520 }
521
522 // Return the appropriate status when verifying diagnostics.
523 //
524 // FIXME: If we could make getNumErrors() do the right thing, we wouldn't need
525 // this.
526 if (getDiagnosticOpts().VerifyDiagnostics)
527 return !static_cast<VerifyDiagnosticsClient&>(
528 getDiagnosticClient()).HadErrors();
529
530 return !getDiagnostics().getNumErrors();
531}
532
533