blob: 8e1dbcb9d24954cef8b6512a961d12c40ce6c0f2 [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"
Douglas Gregorf18d0d82010-08-12 23:31:19 +000011#include "clang/Sema/Sema.h"
Daniel Dunbar12ce6942009-11-14 02:47:17 +000012#include "clang/AST/ASTConsumer.h"
Daniel Dunbar5eb81002009-11-13 08:20:47 +000013#include "clang/AST/ASTContext.h"
Daniel Dunbar2a79e162009-11-13 03:51:44 +000014#include "clang/Basic/Diagnostic.h"
Daniel Dunbar16b74492009-11-13 04:12:06 +000015#include "clang/Basic/FileManager.h"
16#include "clang/Basic/SourceManager.h"
Daniel Dunbar2a79e162009-11-13 03:51:44 +000017#include "clang/Basic/TargetInfo.h"
Daniel Dunbar0397af22010-01-13 00:48:06 +000018#include "clang/Basic/Version.h"
Daniel Dunbar22dacfa2009-11-13 05:52:11 +000019#include "clang/Lex/HeaderSearch.h"
20#include "clang/Lex/Preprocessor.h"
21#include "clang/Lex/PTHManager.h"
Daniel Dunbar0fbb3d92009-11-13 05:52:34 +000022#include "clang/Frontend/ChainedDiagnosticClient.h"
Daniel Dunbar0397af22010-01-13 00:48:06 +000023#include "clang/Frontend/FrontendAction.h"
Douglas Gregor4557e472010-08-17 18:31:01 +000024#include "clang/Frontend/PCHReader.h"
Daniel Dunbarc2f484f2009-11-13 09:36:05 +000025#include "clang/Frontend/FrontendDiagnostic.h"
Daniel Dunbar0fbb3d92009-11-13 05:52:34 +000026#include "clang/Frontend/TextDiagnosticPrinter.h"
Daniel Dunbarf79dced2009-11-14 03:24:39 +000027#include "clang/Frontend/VerifyDiagnosticsClient.h"
Daniel Dunbar22dacfa2009-11-13 05:52:11 +000028#include "clang/Frontend/Utils.h"
Daniel Dunbarc2f484f2009-11-13 09:36:05 +000029#include "clang/Sema/CodeCompleteConsumer.h"
Daniel Dunbar2a79e162009-11-13 03:51:44 +000030#include "llvm/LLVMContext.h"
Daniel Dunbarccb6cb62009-11-14 07:53:04 +000031#include "llvm/Support/MemoryBuffer.h"
Daniel Dunbar0fbb3d92009-11-13 05:52:34 +000032#include "llvm/Support/raw_ostream.h"
Douglas Gregor95dd5582010-03-30 17:33:59 +000033#include "llvm/ADT/Statistic.h"
Kovarththanan Rajaratnamf79bafa2009-11-29 09:57:35 +000034#include "llvm/Support/Timer.h"
Daniel Dunbar0397af22010-01-13 00:48:06 +000035#include "llvm/System/Host.h"
Daniel Dunbara9204832009-11-13 10:37:48 +000036#include "llvm/System/Path.h"
Douglas Gregor2b4074f2009-12-01 05:55:20 +000037#include "llvm/System/Program.h"
Daniel Dunbar2a79e162009-11-13 03:51:44 +000038using namespace clang;
39
Daniel Dunbar42e9f8e42010-02-16 01:54:47 +000040CompilerInstance::CompilerInstance()
Sebastian Redlffaab3e2010-07-30 00:29:29 +000041 : Invocation(new CompilerInvocation()) {
Daniel Dunbar6228ca02010-01-30 21:47:07 +000042}
Daniel Dunbar2a79e162009-11-13 03:51:44 +000043
44CompilerInstance::~CompilerInstance() {
Daniel Dunbar42e9f8e42010-02-16 01:54:47 +000045}
46
47void CompilerInstance::setLLVMContext(llvm::LLVMContext *Value) {
48 LLVMContext.reset(Value);
Daniel Dunbar2a79e162009-11-13 03:51:44 +000049}
Daniel Dunbar16b74492009-11-13 04:12:06 +000050
Daniel Dunbar6228ca02010-01-30 21:47:07 +000051void CompilerInstance::setInvocation(CompilerInvocation *Value) {
52 Invocation.reset(Value);
53}
54
Daniel Dunbar8a9f5692009-11-14 01:20:40 +000055void CompilerInstance::setDiagnostics(Diagnostic *Value) {
Douglas Gregor28019772010-04-05 23:52:57 +000056 Diagnostics = Value;
Daniel Dunbar8a9f5692009-11-14 01:20:40 +000057}
58
59void CompilerInstance::setDiagnosticClient(DiagnosticClient *Value) {
60 DiagClient.reset(Value);
61}
62
63void CompilerInstance::setTarget(TargetInfo *Value) {
64 Target.reset(Value);
65}
66
67void CompilerInstance::setFileManager(FileManager *Value) {
68 FileMgr.reset(Value);
69}
70
71void CompilerInstance::setSourceManager(SourceManager *Value) {
72 SourceMgr.reset(Value);
73}
74
75void CompilerInstance::setPreprocessor(Preprocessor *Value) {
76 PP.reset(Value);
77}
78
79void CompilerInstance::setASTContext(ASTContext *Value) {
80 Context.reset(Value);
81}
82
Douglas Gregorf18d0d82010-08-12 23:31:19 +000083void CompilerInstance::setSema(Sema *S) {
84 TheSema.reset(S);
85}
86
Daniel Dunbar12ce6942009-11-14 02:47:17 +000087void CompilerInstance::setASTConsumer(ASTConsumer *Value) {
88 Consumer.reset(Value);
89}
90
Daniel Dunbar8a9f5692009-11-14 01:20:40 +000091void CompilerInstance::setCodeCompletionConsumer(CodeCompleteConsumer *Value) {
92 CompletionConsumer.reset(Value);
93}
94
Daniel Dunbar0fbb3d92009-11-13 05:52:34 +000095// Diagnostics
Douglas Gregord93256e2010-01-28 06:00:51 +000096namespace {
97 class BinaryDiagnosticSerializer : public DiagnosticClient {
98 llvm::raw_ostream &OS;
99 SourceManager *SourceMgr;
100 public:
101 explicit BinaryDiagnosticSerializer(llvm::raw_ostream &OS)
102 : OS(OS), SourceMgr(0) { }
Kovarththanan Rajaratname51dd7b2010-03-06 12:07:48 +0000103
Douglas Gregord93256e2010-01-28 06:00:51 +0000104 virtual void HandleDiagnostic(Diagnostic::Level DiagLevel,
105 const DiagnosticInfo &Info);
106 };
107}
108
109void BinaryDiagnosticSerializer::HandleDiagnostic(Diagnostic::Level DiagLevel,
110 const DiagnosticInfo &Info) {
Douglas Gregora88084b2010-02-18 18:08:43 +0000111 StoredDiagnostic(DiagLevel, Info).Serialize(OS);
Douglas Gregord93256e2010-01-28 06:00:51 +0000112}
Daniel Dunbar0fbb3d92009-11-13 05:52:34 +0000113
114static void SetUpBuildDumpLog(const DiagnosticOptions &DiagOpts,
115 unsigned argc, char **argv,
Kovarththanan Rajaratnam3d67b1e2010-03-17 09:24:48 +0000116 Diagnostic &Diags) {
Daniel Dunbar0fbb3d92009-11-13 05:52:34 +0000117 std::string ErrorInfo;
Kovarththanan Rajaratnam69247132010-03-17 09:47:30 +0000118 llvm::OwningPtr<llvm::raw_ostream> OS(
119 new llvm::raw_fd_ostream(DiagOpts.DumpBuildInformation.c_str(), ErrorInfo));
Daniel Dunbar0fbb3d92009-11-13 05:52:34 +0000120 if (!ErrorInfo.empty()) {
Kovarththanan Rajaratnam3d67b1e2010-03-17 09:24:48 +0000121 Diags.Report(diag::err_fe_unable_to_open_logfile)
122 << DiagOpts.DumpBuildInformation << ErrorInfo;
Daniel Dunbar0fbb3d92009-11-13 05:52:34 +0000123 return;
124 }
125
Daniel Dunbardd63b282009-12-11 23:04:35 +0000126 (*OS) << "clang -cc1 command line arguments: ";
Daniel Dunbar0fbb3d92009-11-13 05:52:34 +0000127 for (unsigned i = 0; i != argc; ++i)
128 (*OS) << argv[i] << ' ';
129 (*OS) << '\n';
130
131 // Chain in a diagnostic client which will log the diagnostics.
132 DiagnosticClient *Logger =
Kovarththanan Rajaratnam69247132010-03-17 09:47:30 +0000133 new TextDiagnosticPrinter(*OS.take(), DiagOpts, /*OwnsOutputStream=*/true);
Kovarththanan Rajaratnam3d67b1e2010-03-17 09:24:48 +0000134 Diags.setClient(new ChainedDiagnosticClient(Diags.getClient(), Logger));
Daniel Dunbar0fbb3d92009-11-13 05:52:34 +0000135}
136
137void CompilerInstance::createDiagnostics(int Argc, char **Argv) {
Douglas Gregor28019772010-04-05 23:52:57 +0000138 Diagnostics = createDiagnostics(getDiagnosticOpts(), Argc, Argv);
Daniel Dunbar0fbb3d92009-11-13 05:52:34 +0000139
140 if (Diagnostics)
141 DiagClient.reset(Diagnostics->getClient());
142}
143
Douglas Gregor28019772010-04-05 23:52:57 +0000144llvm::IntrusiveRefCntPtr<Diagnostic>
145CompilerInstance::createDiagnostics(const DiagnosticOptions &Opts,
146 int Argc, char **Argv) {
147 llvm::IntrusiveRefCntPtr<Diagnostic> Diags(new Diagnostic());
Daniel Dunbar221c7212009-11-14 07:53:24 +0000148
Daniel Dunbar0fbb3d92009-11-13 05:52:34 +0000149 // Create the diagnostic client for reporting errors or for
150 // implementing -verify.
Douglas Gregord93256e2010-01-28 06:00:51 +0000151 llvm::OwningPtr<DiagnosticClient> DiagClient;
152 if (Opts.BinaryOutput) {
153 if (llvm::sys::Program::ChangeStderrToBinary()) {
154 // We weren't able to set standard error to binary, which is a
155 // bit of a problem. So, just create a text diagnostic printer
156 // to complain about this problem, and pretend that the user
157 // didn't try to use binary output.
158 DiagClient.reset(new TextDiagnosticPrinter(llvm::errs(), Opts));
159 Diags->setClient(DiagClient.take());
160 Diags->Report(diag::err_fe_stderr_binary);
Douglas Gregor28019772010-04-05 23:52:57 +0000161 return Diags;
Douglas Gregord93256e2010-01-28 06:00:51 +0000162 } else {
163 DiagClient.reset(new BinaryDiagnosticSerializer(llvm::errs()));
164 }
165 } else {
166 DiagClient.reset(new TextDiagnosticPrinter(llvm::errs(), Opts));
167 }
Daniel Dunbarf79dced2009-11-14 03:24:39 +0000168
169 // Chain in -verify checker, if requested.
170 if (Opts.VerifyDiagnostics)
Daniel Dunbar221c7212009-11-14 07:53:24 +0000171 DiagClient.reset(new VerifyDiagnosticsClient(*Diags, DiagClient.take()));
Daniel Dunbar0fbb3d92009-11-13 05:52:34 +0000172
Kovarththanan Rajaratnam3d67b1e2010-03-17 09:24:48 +0000173 Diags->setClient(DiagClient.take());
Daniel Dunbar0fbb3d92009-11-13 05:52:34 +0000174 if (!Opts.DumpBuildInformation.empty())
Kovarththanan Rajaratnam3d67b1e2010-03-17 09:24:48 +0000175 SetUpBuildDumpLog(Opts, Argc, Argv, *Diags);
Daniel Dunbar0fbb3d92009-11-13 05:52:34 +0000176
177 // Configure our handling of diagnostics.
Kovarththanan Rajaratnam5bf932b2010-03-17 09:36:02 +0000178 ProcessWarningOptions(*Diags, Opts);
Daniel Dunbar0fbb3d92009-11-13 05:52:34 +0000179
Douglas Gregor28019772010-04-05 23:52:57 +0000180 return Diags;
Daniel Dunbar0fbb3d92009-11-13 05:52:34 +0000181}
182
183// File Manager
184
Daniel Dunbar16b74492009-11-13 04:12:06 +0000185void CompilerInstance::createFileManager() {
186 FileMgr.reset(new FileManager());
187}
188
Daniel Dunbar0fbb3d92009-11-13 05:52:34 +0000189// Source Manager
190
Daniel Dunbar16b74492009-11-13 04:12:06 +0000191void CompilerInstance::createSourceManager() {
Douglas Gregorf715ca12010-03-16 00:06:06 +0000192 SourceMgr.reset(new SourceManager(getDiagnostics()));
Daniel Dunbar16b74492009-11-13 04:12:06 +0000193}
Daniel Dunbar22dacfa2009-11-13 05:52:11 +0000194
Daniel Dunbar0fbb3d92009-11-13 05:52:34 +0000195// Preprocessor
196
Daniel Dunbar22dacfa2009-11-13 05:52:11 +0000197void CompilerInstance::createPreprocessor() {
198 PP.reset(createPreprocessor(getDiagnostics(), getLangOpts(),
199 getPreprocessorOpts(), getHeaderSearchOpts(),
200 getDependencyOutputOpts(), getTarget(),
Fariborz Jahanian7d957472010-01-13 18:51:17 +0000201 getFrontendOpts(), getSourceManager(),
202 getFileManager()));
Daniel Dunbar22dacfa2009-11-13 05:52:11 +0000203}
204
205Preprocessor *
206CompilerInstance::createPreprocessor(Diagnostic &Diags,
207 const LangOptions &LangInfo,
208 const PreprocessorOptions &PPOpts,
209 const HeaderSearchOptions &HSOpts,
210 const DependencyOutputOptions &DepOpts,
211 const TargetInfo &Target,
Fariborz Jahanian7d957472010-01-13 18:51:17 +0000212 const FrontendOptions &FEOpts,
Daniel Dunbar22dacfa2009-11-13 05:52:11 +0000213 SourceManager &SourceMgr,
214 FileManager &FileMgr) {
215 // Create a PTH manager if we are using some form of a token cache.
216 PTHManager *PTHMgr = 0;
Daniel Dunbar049d3a02009-11-17 05:52:41 +0000217 if (!PPOpts.TokenCache.empty())
218 PTHMgr = PTHManager::Create(PPOpts.TokenCache, Diags);
Daniel Dunbar22dacfa2009-11-13 05:52:11 +0000219
Daniel Dunbar22dacfa2009-11-13 05:52:11 +0000220 // Create the Preprocessor.
221 HeaderSearch *HeaderInfo = new HeaderSearch(FileMgr);
222 Preprocessor *PP = new Preprocessor(Diags, LangInfo, Target,
223 SourceMgr, *HeaderInfo, PTHMgr,
224 /*OwnsHeaderSearch=*/true);
225
226 // Note that this is different then passing PTHMgr to Preprocessor's ctor.
227 // That argument is used as the IdentifierInfoLookup argument to
228 // IdentifierTable's ctor.
229 if (PTHMgr) {
230 PTHMgr->setPreprocessor(PP);
231 PP->setPTHManager(PTHMgr);
232 }
233
Douglas Gregor94dc8f62010-03-19 16:15:56 +0000234 if (PPOpts.DetailedRecord)
235 PP->createPreprocessingRecord();
236
Fariborz Jahanian7d957472010-01-13 18:51:17 +0000237 InitializePreprocessor(*PP, PPOpts, HSOpts, FEOpts);
Daniel Dunbar22dacfa2009-11-13 05:52:11 +0000238
239 // Handle generating dependencies, if requested.
240 if (!DepOpts.OutputFile.empty())
241 AttachDependencyFileGen(*PP, DepOpts);
242
243 return PP;
244}
Daniel Dunbar5eb81002009-11-13 08:20:47 +0000245
246// ASTContext
247
248void CompilerInstance::createASTContext() {
249 Preprocessor &PP = getPreprocessor();
250 Context.reset(new ASTContext(getLangOpts(), PP.getSourceManager(),
251 getTarget(), PP.getIdentifierTable(),
252 PP.getSelectorTable(), PP.getBuiltinInfo(),
Daniel Dunbar5eb81002009-11-13 08:20:47 +0000253 /*size_reserve=*/ 0));
254}
Daniel Dunbar0f800392009-11-13 08:21:10 +0000255
256// ExternalASTSource
257
Douglas Gregorfae3b2f2010-07-27 00:27:13 +0000258void CompilerInstance::createPCHExternalASTSource(llvm::StringRef Path,
Sebastian Redlffaab3e2010-07-30 00:29:29 +0000259 bool DisablePCHValidation,
260 void *DeserializationListener){
Daniel Dunbar0f800392009-11-13 08:21:10 +0000261 llvm::OwningPtr<ExternalASTSource> Source;
262 Source.reset(createPCHExternalASTSource(Path, getHeaderSearchOpts().Sysroot,
Douglas Gregorfae3b2f2010-07-27 00:27:13 +0000263 DisablePCHValidation,
Sebastian Redlffaab3e2010-07-30 00:29:29 +0000264 getPreprocessor(), getASTContext(),
265 DeserializationListener));
Daniel Dunbar0f800392009-11-13 08:21:10 +0000266 getASTContext().setExternalSource(Source);
267}
268
269ExternalASTSource *
270CompilerInstance::createPCHExternalASTSource(llvm::StringRef Path,
271 const std::string &Sysroot,
Douglas Gregorfae3b2f2010-07-27 00:27:13 +0000272 bool DisablePCHValidation,
Daniel Dunbar0f800392009-11-13 08:21:10 +0000273 Preprocessor &PP,
Sebastian Redlffaab3e2010-07-30 00:29:29 +0000274 ASTContext &Context,
275 void *DeserializationListener) {
Daniel Dunbar0f800392009-11-13 08:21:10 +0000276 llvm::OwningPtr<PCHReader> Reader;
277 Reader.reset(new PCHReader(PP, &Context,
Douglas Gregorfae3b2f2010-07-27 00:27:13 +0000278 Sysroot.empty() ? 0 : Sysroot.c_str(),
279 DisablePCHValidation));
Daniel Dunbar0f800392009-11-13 08:21:10 +0000280
Sebastian Redlffaab3e2010-07-30 00:29:29 +0000281 Reader->setDeserializationListener(
282 static_cast<PCHDeserializationListener *>(DeserializationListener));
Daniel Dunbar0f800392009-11-13 08:21:10 +0000283 switch (Reader->ReadPCH(Path)) {
284 case PCHReader::Success:
285 // Set the predefines buffer as suggested by the PCH reader. Typically, the
286 // predefines buffer will be empty.
287 PP.setPredefines(Reader->getSuggestedPredefines());
288 return Reader.take();
289
290 case PCHReader::Failure:
291 // Unrecoverable failure: don't even try to process the input file.
292 break;
293
294 case PCHReader::IgnorePCH:
295 // No suitable PCH file could be found. Return an error.
296 break;
297 }
298
299 return 0;
300}
Daniel Dunbarc2f484f2009-11-13 09:36:05 +0000301
302// Code Completion
303
Douglas Gregor1abc6bc2010-08-04 16:47:14 +0000304static bool EnableCodeCompletion(Preprocessor &PP,
305 const std::string &Filename,
306 unsigned Line,
307 unsigned Column) {
308 // Tell the source manager to chop off the given file at a specific
309 // line and column.
310 const FileEntry *Entry = PP.getFileManager().getFile(Filename);
311 if (!Entry) {
312 PP.getDiagnostics().Report(diag::err_fe_invalid_code_complete_file)
313 << Filename;
314 return true;
315 }
316
317 // Truncate the named file at the given line/column.
318 PP.SetCodeCompletionPoint(Entry, Line, Column);
319 return false;
320}
321
Daniel Dunbarc2f484f2009-11-13 09:36:05 +0000322void CompilerInstance::createCodeCompletionConsumer() {
323 const ParsedSourceLocation &Loc = getFrontendOpts().CodeCompletionAt;
Douglas Gregor1abc6bc2010-08-04 16:47:14 +0000324 if (!CompletionConsumer) {
325 CompletionConsumer.reset(
326 createCodeCompletionConsumer(getPreprocessor(),
327 Loc.FileName, Loc.Line, Loc.Column,
328 getFrontendOpts().DebugCodeCompletionPrinter,
329 getFrontendOpts().ShowMacrosInCodeCompletion,
Douglas Gregord8e8a582010-05-25 21:41:55 +0000330 getFrontendOpts().ShowCodePatternsInCodeCompletion,
Douglas Gregor8071e422010-08-15 06:18:01 +0000331 getFrontendOpts().ShowGlobalSymbolsInCodeCompletion,
Douglas Gregor1abc6bc2010-08-04 16:47:14 +0000332 llvm::outs()));
333 if (!CompletionConsumer)
334 return;
335 } else if (EnableCodeCompletion(getPreprocessor(), Loc.FileName,
336 Loc.Line, Loc.Column)) {
337 CompletionConsumer.reset();
Douglas Gregorc3d43b72010-03-16 06:04:47 +0000338 return;
Douglas Gregor1abc6bc2010-08-04 16:47:14 +0000339 }
Douglas Gregor2b4074f2009-12-01 05:55:20 +0000340
341 if (CompletionConsumer->isOutputBinary() &&
342 llvm::sys::Program::ChangeStdoutToBinary()) {
343 getPreprocessor().getDiagnostics().Report(diag::err_fe_stdout_binary);
344 CompletionConsumer.reset();
345 }
Daniel Dunbarc2f484f2009-11-13 09:36:05 +0000346}
347
Kovarththanan Rajaratnamf79bafa2009-11-29 09:57:35 +0000348void CompilerInstance::createFrontendTimer() {
349 FrontendTimer.reset(new llvm::Timer("Clang front-end timer"));
350}
351
Daniel Dunbarc2f484f2009-11-13 09:36:05 +0000352CodeCompleteConsumer *
353CompilerInstance::createCodeCompletionConsumer(Preprocessor &PP,
354 const std::string &Filename,
355 unsigned Line,
356 unsigned Column,
357 bool UseDebugPrinter,
358 bool ShowMacros,
Douglas Gregord8e8a582010-05-25 21:41:55 +0000359 bool ShowCodePatterns,
Douglas Gregor8071e422010-08-15 06:18:01 +0000360 bool ShowGlobals,
Daniel Dunbarc2f484f2009-11-13 09:36:05 +0000361 llvm::raw_ostream &OS) {
Douglas Gregor1abc6bc2010-08-04 16:47:14 +0000362 if (EnableCodeCompletion(PP, Filename, Line, Column))
Daniel Dunbarc2f484f2009-11-13 09:36:05 +0000363 return 0;
Daniel Dunbarc2f484f2009-11-13 09:36:05 +0000364
365 // Set up the creation routine for code-completion.
366 if (UseDebugPrinter)
Douglas Gregor8071e422010-08-15 06:18:01 +0000367 return new PrintingCodeCompleteConsumer(ShowMacros, ShowCodePatterns,
368 ShowGlobals, OS);
Daniel Dunbarc2f484f2009-11-13 09:36:05 +0000369 else
Douglas Gregor8071e422010-08-15 06:18:01 +0000370 return new CIndexCodeCompleteConsumer(ShowMacros, ShowCodePatterns,
371 ShowGlobals, OS);
Daniel Dunbarc2f484f2009-11-13 09:36:05 +0000372}
Daniel Dunbara9204832009-11-13 10:37:48 +0000373
Douglas Gregorf18d0d82010-08-12 23:31:19 +0000374void CompilerInstance::createSema(bool CompleteTranslationUnit,
375 CodeCompleteConsumer *CompletionConsumer) {
376 TheSema.reset(new Sema(getPreprocessor(), getASTContext(), getASTConsumer(),
377 CompleteTranslationUnit, CompletionConsumer));
378}
379
Daniel Dunbara9204832009-11-13 10:37:48 +0000380// Output Files
381
382void CompilerInstance::addOutputFile(llvm::StringRef Path,
383 llvm::raw_ostream *OS) {
384 assert(OS && "Attempt to add empty stream to output list!");
385 OutputFiles.push_back(std::make_pair(Path, OS));
386}
387
Kovarththanan Rajaratname51dd7b2010-03-06 12:07:48 +0000388void CompilerInstance::clearOutputFiles(bool EraseFiles) {
Daniel Dunbara9204832009-11-13 10:37:48 +0000389 for (std::list< std::pair<std::string, llvm::raw_ostream*> >::iterator
390 it = OutputFiles.begin(), ie = OutputFiles.end(); it != ie; ++it) {
391 delete it->second;
392 if (EraseFiles && !it->first.empty())
393 llvm::sys::Path(it->first).eraseFromDisk();
394 }
395 OutputFiles.clear();
396}
397
Daniel Dunbarf482d592009-11-13 18:32:08 +0000398llvm::raw_fd_ostream *
399CompilerInstance::createDefaultOutputFile(bool Binary,
400 llvm::StringRef InFile,
401 llvm::StringRef Extension) {
402 return createOutputFile(getFrontendOpts().OutputFile, Binary,
403 InFile, Extension);
404}
405
406llvm::raw_fd_ostream *
407CompilerInstance::createOutputFile(llvm::StringRef OutputPath,
408 bool Binary,
409 llvm::StringRef InFile,
410 llvm::StringRef Extension) {
411 std::string Error, OutputPathName;
412 llvm::raw_fd_ostream *OS = createOutputFile(OutputPath, Error, Binary,
413 InFile, Extension,
414 &OutputPathName);
415 if (!OS) {
Daniel Dunbar36043592009-12-03 09:13:30 +0000416 getDiagnostics().Report(diag::err_fe_unable_to_open_output)
417 << OutputPath << Error;
418 return 0;
Daniel Dunbarf482d592009-11-13 18:32:08 +0000419 }
420
421 // Add the output file -- but don't try to remove "-", since this means we are
422 // using stdin.
423 addOutputFile((OutputPathName != "-") ? OutputPathName : "", OS);
424
425 return OS;
426}
427
428llvm::raw_fd_ostream *
429CompilerInstance::createOutputFile(llvm::StringRef OutputPath,
430 std::string &Error,
431 bool Binary,
432 llvm::StringRef InFile,
433 llvm::StringRef Extension,
434 std::string *ResultPathName) {
435 std::string OutFile;
436 if (!OutputPath.empty()) {
437 OutFile = OutputPath;
438 } else if (InFile == "-") {
439 OutFile = "-";
440 } else if (!Extension.empty()) {
441 llvm::sys::Path Path(InFile);
442 Path.eraseSuffix();
443 Path.appendSuffix(Extension);
444 OutFile = Path.str();
445 } else {
446 OutFile = "-";
447 }
448
Daniel Dunbarfc971022009-11-20 22:32:38 +0000449 llvm::OwningPtr<llvm::raw_fd_ostream> OS(
Daniel Dunbarf482d592009-11-13 18:32:08 +0000450 new llvm::raw_fd_ostream(OutFile.c_str(), Error,
Daniel Dunbarfc971022009-11-20 22:32:38 +0000451 (Binary ? llvm::raw_fd_ostream::F_Binary : 0)));
452 if (!Error.empty())
Daniel Dunbarf482d592009-11-13 18:32:08 +0000453 return 0;
454
455 if (ResultPathName)
456 *ResultPathName = OutFile;
457
Daniel Dunbarfc971022009-11-20 22:32:38 +0000458 return OS.take();
Daniel Dunbarf482d592009-11-13 18:32:08 +0000459}
Daniel Dunbarccb6cb62009-11-14 07:53:04 +0000460
461// Initialization Utilities
462
463bool CompilerInstance::InitializeSourceManager(llvm::StringRef InputFile) {
464 return InitializeSourceManager(InputFile, getDiagnostics(), getFileManager(),
465 getSourceManager(), getFrontendOpts());
466}
467
468bool CompilerInstance::InitializeSourceManager(llvm::StringRef InputFile,
469 Diagnostic &Diags,
470 FileManager &FileMgr,
471 SourceManager &SourceMgr,
472 const FrontendOptions &Opts) {
473 // Figure out where to get and map in the main file.
Daniel Dunbar27585952010-03-19 19:44:04 +0000474 if (InputFile != "-") {
Daniel Dunbarccb6cb62009-11-14 07:53:04 +0000475 const FileEntry *File = FileMgr.getFile(InputFile);
476 if (File) SourceMgr.createMainFileID(File, SourceLocation());
477 if (SourceMgr.getMainFileID().isInvalid()) {
478 Diags.Report(diag::err_fe_error_reading) << InputFile;
479 return false;
480 }
481 } else {
482 llvm::MemoryBuffer *SB = llvm::MemoryBuffer::getSTDIN();
Dan Gohman6f118972010-05-27 17:33:40 +0000483 if (SB) SourceMgr.createMainFileIDForMemBuffer(SB);
Daniel Dunbarccb6cb62009-11-14 07:53:04 +0000484 if (SourceMgr.getMainFileID().isInvalid()) {
485 Diags.Report(diag::err_fe_error_reading_stdin);
486 return false;
487 }
488 }
489
490 return true;
491}
Daniel Dunbar0397af22010-01-13 00:48:06 +0000492
493// High-Level Operations
494
495bool CompilerInstance::ExecuteAction(FrontendAction &Act) {
496 assert(hasDiagnostics() && "Diagnostics engine is not initialized!");
497 assert(!getFrontendOpts().ShowHelp && "Client must handle '-help'!");
498 assert(!getFrontendOpts().ShowVersion && "Client must handle '-version'!");
499
500 // FIXME: Take this as an argument, once all the APIs we used have moved to
501 // taking it as an input instead of hard-coding llvm::errs.
502 llvm::raw_ostream &OS = llvm::errs();
503
504 // Create the target instance.
505 setTarget(TargetInfo::CreateTargetInfo(getDiagnostics(), getTargetOpts()));
506 if (!hasTarget())
507 return false;
508
509 // Inform the target of the language options.
510 //
511 // FIXME: We shouldn't need to do this, the target should be immutable once
512 // created. This complexity should be lifted elsewhere.
513 getTarget().setForcedLangOptions(getLangOpts());
514
515 // Validate/process some options.
516 if (getHeaderSearchOpts().Verbose)
517 OS << "clang -cc1 version " CLANG_VERSION_STRING
518 << " based upon " << PACKAGE_STRING
519 << " hosted on " << llvm::sys::getHostTriple() << "\n";
520
521 if (getFrontendOpts().ShowTimers)
522 createFrontendTimer();
523
Douglas Gregor95dd5582010-03-30 17:33:59 +0000524 if (getFrontendOpts().ShowStats)
525 llvm::EnableStatistics();
526
Daniel Dunbar0397af22010-01-13 00:48:06 +0000527 for (unsigned i = 0, e = getFrontendOpts().Inputs.size(); i != e; ++i) {
528 const std::string &InFile = getFrontendOpts().Inputs[i].second;
529
Daniel Dunbar20560482010-06-07 23:23:50 +0000530 // Reset the ID tables if we are reusing the SourceManager.
531 if (hasSourceManager())
532 getSourceManager().clearIDTables();
Daniel Dunbar0397af22010-01-13 00:48:06 +0000533
Daniel Dunbard3598a62010-06-07 23:23:06 +0000534 if (Act.BeginSourceFile(*this, InFile, getFrontendOpts().Inputs[i].first)) {
Daniel Dunbar0397af22010-01-13 00:48:06 +0000535 Act.Execute();
536 Act.EndSourceFile();
537 }
538 }
539
Chris Lattner53eee7b2010-04-07 18:47:42 +0000540 if (getDiagnosticOpts().ShowCarets) {
541 unsigned NumWarnings = getDiagnostics().getNumWarnings();
Douglas Gregor1864f2e2010-04-14 22:19:45 +0000542 unsigned NumErrors = getDiagnostics().getNumErrors() -
543 getDiagnostics().getNumErrorsSuppressed();
Chris Lattner53eee7b2010-04-07 18:47:42 +0000544
545 if (NumWarnings)
546 OS << NumWarnings << " warning" << (NumWarnings == 1 ? "" : "s");
547 if (NumWarnings && NumErrors)
548 OS << " and ";
549 if (NumErrors)
550 OS << NumErrors << " error" << (NumErrors == 1 ? "" : "s");
551 if (NumWarnings || NumErrors)
552 OS << " generated.\n";
553 }
Daniel Dunbar0397af22010-01-13 00:48:06 +0000554
Daniel Dunbar20560482010-06-07 23:23:50 +0000555 if (getFrontendOpts().ShowStats && hasFileManager()) {
Daniel Dunbar0397af22010-01-13 00:48:06 +0000556 getFileManager().PrintStats();
557 OS << "\n";
558 }
559
560 // Return the appropriate status when verifying diagnostics.
561 //
562 // FIXME: If we could make getNumErrors() do the right thing, we wouldn't need
563 // this.
564 if (getDiagnosticOpts().VerifyDiagnostics)
565 return !static_cast<VerifyDiagnosticsClient&>(
566 getDiagnosticClient()).HadErrors();
567
568 return !getDiagnostics().getNumErrors();
569}
570
571