1636404a3SDaniel Dunbar //===--- CompilerInstance.cpp ---------------------------------------------===//
2636404a3SDaniel Dunbar //
3636404a3SDaniel Dunbar //                     The LLVM Compiler Infrastructure
4636404a3SDaniel Dunbar //
5636404a3SDaniel Dunbar // This file is distributed under the University of Illinois Open Source
6636404a3SDaniel Dunbar // License. See LICENSE.TXT for details.
7636404a3SDaniel Dunbar //
8636404a3SDaniel Dunbar //===----------------------------------------------------------------------===//
9636404a3SDaniel Dunbar 
10636404a3SDaniel Dunbar #include "clang/Frontend/CompilerInstance.h"
1156d9c293SDaniel Dunbar #include "clang/AST/ASTConsumer.h"
12df3e30c4SDaniel Dunbar #include "clang/AST/ASTContext.h"
13636404a3SDaniel Dunbar #include "clang/Basic/Diagnostic.h"
14546a676aSDaniel Dunbar #include "clang/Basic/FileManager.h"
15546a676aSDaniel Dunbar #include "clang/Basic/SourceManager.h"
16636404a3SDaniel Dunbar #include "clang/Basic/TargetInfo.h"
174f2bc55dSDaniel Dunbar #include "clang/Basic/Version.h"
18aaa148fdSDaniel Dunbar #include "clang/Lex/HeaderSearch.h"
19aaa148fdSDaniel Dunbar #include "clang/Lex/Preprocessor.h"
20aaa148fdSDaniel Dunbar #include "clang/Lex/PTHManager.h"
217d75afc5SDaniel Dunbar #include "clang/Frontend/ChainedDiagnosticClient.h"
224f2bc55dSDaniel Dunbar #include "clang/Frontend/FrontendAction.h"
23599313efSDaniel Dunbar #include "clang/Frontend/PCHReader.h"
24f7093b5aSDaniel Dunbar #include "clang/Frontend/FrontendDiagnostic.h"
257d75afc5SDaniel Dunbar #include "clang/Frontend/TextDiagnosticPrinter.h"
2650ec0da0SDaniel Dunbar #include "clang/Frontend/VerifyDiagnosticsClient.h"
27aaa148fdSDaniel Dunbar #include "clang/Frontend/Utils.h"
28f7093b5aSDaniel Dunbar #include "clang/Sema/CodeCompleteConsumer.h"
29636404a3SDaniel Dunbar #include "llvm/LLVMContext.h"
30409e890fSDaniel Dunbar #include "llvm/Support/MemoryBuffer.h"
317d75afc5SDaniel Dunbar #include "llvm/Support/raw_ostream.h"
325505dff8SKovarththanan Rajaratnam #include "llvm/Support/Timer.h"
334f2bc55dSDaniel Dunbar #include "llvm/System/Host.h"
34566eeb2dSDaniel Dunbar #include "llvm/System/Path.h"
35f09935f1SDouglas Gregor #include "llvm/System/Program.h"
36636404a3SDaniel Dunbar using namespace clang;
37636404a3SDaniel Dunbar 
38e922d9bdSDaniel Dunbar CompilerInstance::CompilerInstance()
39e922d9bdSDaniel Dunbar   : Invocation(new CompilerInvocation()) {
40636404a3SDaniel Dunbar }
41636404a3SDaniel Dunbar 
42636404a3SDaniel Dunbar CompilerInstance::~CompilerInstance() {
43e922d9bdSDaniel Dunbar }
44e922d9bdSDaniel Dunbar 
45e922d9bdSDaniel Dunbar void CompilerInstance::setLLVMContext(llvm::LLVMContext *Value) {
46e922d9bdSDaniel Dunbar   LLVMContext.reset(Value);
47636404a3SDaniel Dunbar }
48546a676aSDaniel Dunbar 
4968242254SDaniel Dunbar void CompilerInstance::setInvocation(CompilerInvocation *Value) {
5068242254SDaniel Dunbar   Invocation.reset(Value);
5168242254SDaniel Dunbar }
5268242254SDaniel Dunbar 
53e01dc86dSDaniel Dunbar void CompilerInstance::setDiagnostics(Diagnostic *Value) {
54e01dc86dSDaniel Dunbar   Diagnostics.reset(Value);
55e01dc86dSDaniel Dunbar }
56e01dc86dSDaniel Dunbar 
57e01dc86dSDaniel Dunbar void CompilerInstance::setDiagnosticClient(DiagnosticClient *Value) {
58e01dc86dSDaniel Dunbar   DiagClient.reset(Value);
59e01dc86dSDaniel Dunbar }
60e01dc86dSDaniel Dunbar 
61e01dc86dSDaniel Dunbar void CompilerInstance::setTarget(TargetInfo *Value) {
62e01dc86dSDaniel Dunbar   Target.reset(Value);
63e01dc86dSDaniel Dunbar }
64e01dc86dSDaniel Dunbar 
65e01dc86dSDaniel Dunbar void CompilerInstance::setFileManager(FileManager *Value) {
66e01dc86dSDaniel Dunbar   FileMgr.reset(Value);
67e01dc86dSDaniel Dunbar }
68e01dc86dSDaniel Dunbar 
69e01dc86dSDaniel Dunbar void CompilerInstance::setSourceManager(SourceManager *Value) {
70e01dc86dSDaniel Dunbar   SourceMgr.reset(Value);
71e01dc86dSDaniel Dunbar }
72e01dc86dSDaniel Dunbar 
73e01dc86dSDaniel Dunbar void CompilerInstance::setPreprocessor(Preprocessor *Value) {
74e01dc86dSDaniel Dunbar   PP.reset(Value);
75e01dc86dSDaniel Dunbar }
76e01dc86dSDaniel Dunbar 
77e01dc86dSDaniel Dunbar void CompilerInstance::setASTContext(ASTContext *Value) {
78e01dc86dSDaniel Dunbar   Context.reset(Value);
79e01dc86dSDaniel Dunbar }
80e01dc86dSDaniel Dunbar 
8156d9c293SDaniel Dunbar void CompilerInstance::setASTConsumer(ASTConsumer *Value) {
8256d9c293SDaniel Dunbar   Consumer.reset(Value);
8356d9c293SDaniel Dunbar }
8456d9c293SDaniel Dunbar 
85e01dc86dSDaniel Dunbar void CompilerInstance::setCodeCompletionConsumer(CodeCompleteConsumer *Value) {
86e01dc86dSDaniel Dunbar   CompletionConsumer.reset(Value);
87e01dc86dSDaniel Dunbar }
88e01dc86dSDaniel Dunbar 
897d75afc5SDaniel Dunbar // Diagnostics
90ac0605e9SDouglas Gregor namespace {
91ac0605e9SDouglas Gregor   class BinaryDiagnosticSerializer : public DiagnosticClient {
92ac0605e9SDouglas Gregor     llvm::raw_ostream &OS;
93ac0605e9SDouglas Gregor     SourceManager *SourceMgr;
94ac0605e9SDouglas Gregor   public:
95ac0605e9SDouglas Gregor     explicit BinaryDiagnosticSerializer(llvm::raw_ostream &OS)
96ac0605e9SDouglas Gregor       : OS(OS), SourceMgr(0) { }
97ac0605e9SDouglas Gregor 
98ac0605e9SDouglas Gregor     virtual void HandleDiagnostic(Diagnostic::Level DiagLevel,
99ac0605e9SDouglas Gregor                                   const DiagnosticInfo &Info);
100ac0605e9SDouglas Gregor   };
101ac0605e9SDouglas Gregor }
102ac0605e9SDouglas Gregor 
103ac0605e9SDouglas Gregor void BinaryDiagnosticSerializer::HandleDiagnostic(Diagnostic::Level DiagLevel,
104ac0605e9SDouglas Gregor                                                   const DiagnosticInfo &Info) {
10533cdd810SDouglas Gregor   StoredDiagnostic(DiagLevel, Info).Serialize(OS);
106ac0605e9SDouglas Gregor }
1077d75afc5SDaniel Dunbar 
1087d75afc5SDaniel Dunbar static void SetUpBuildDumpLog(const DiagnosticOptions &DiagOpts,
1097d75afc5SDaniel Dunbar                               unsigned argc, char **argv,
1107d75afc5SDaniel Dunbar                               llvm::OwningPtr<DiagnosticClient> &DiagClient) {
1117d75afc5SDaniel Dunbar   std::string ErrorInfo;
1127d75afc5SDaniel Dunbar   llvm::raw_ostream *OS =
1137d75afc5SDaniel Dunbar     new llvm::raw_fd_ostream(DiagOpts.DumpBuildInformation.c_str(), ErrorInfo);
1147d75afc5SDaniel Dunbar   if (!ErrorInfo.empty()) {
1157d75afc5SDaniel Dunbar     // FIXME: Do not fail like this.
1167d75afc5SDaniel Dunbar     llvm::errs() << "error opening -dump-build-information file '"
1177d75afc5SDaniel Dunbar                  << DiagOpts.DumpBuildInformation << "', option ignored!\n";
1187d75afc5SDaniel Dunbar     delete OS;
1197d75afc5SDaniel Dunbar     return;
1207d75afc5SDaniel Dunbar   }
1217d75afc5SDaniel Dunbar 
122520d1e6cSDaniel Dunbar   (*OS) << "clang -cc1 command line arguments: ";
1237d75afc5SDaniel Dunbar   for (unsigned i = 0; i != argc; ++i)
1247d75afc5SDaniel Dunbar     (*OS) << argv[i] << ' ';
1257d75afc5SDaniel Dunbar   (*OS) << '\n';
1267d75afc5SDaniel Dunbar 
1277d75afc5SDaniel Dunbar   // Chain in a diagnostic client which will log the diagnostics.
1287d75afc5SDaniel Dunbar   DiagnosticClient *Logger =
1297d75afc5SDaniel Dunbar     new TextDiagnosticPrinter(*OS, DiagOpts, /*OwnsOutputStream=*/true);
1307d75afc5SDaniel Dunbar   DiagClient.reset(new ChainedDiagnosticClient(DiagClient.take(), Logger));
1317d75afc5SDaniel Dunbar }
1327d75afc5SDaniel Dunbar 
1337d75afc5SDaniel Dunbar void CompilerInstance::createDiagnostics(int Argc, char **Argv) {
1347d75afc5SDaniel Dunbar   Diagnostics.reset(createDiagnostics(getDiagnosticOpts(), Argc, Argv));
1357d75afc5SDaniel Dunbar 
1367d75afc5SDaniel Dunbar   if (Diagnostics)
1377d75afc5SDaniel Dunbar     DiagClient.reset(Diagnostics->getClient());
1387d75afc5SDaniel Dunbar }
1397d75afc5SDaniel Dunbar 
1407d75afc5SDaniel Dunbar Diagnostic *CompilerInstance::createDiagnostics(const DiagnosticOptions &Opts,
1417d75afc5SDaniel Dunbar                                                 int Argc, char **Argv) {
1421b39a2edSDaniel Dunbar   llvm::OwningPtr<Diagnostic> Diags(new Diagnostic());
1431b39a2edSDaniel Dunbar 
1447d75afc5SDaniel Dunbar   // Create the diagnostic client for reporting errors or for
1457d75afc5SDaniel Dunbar   // implementing -verify.
146ac0605e9SDouglas Gregor   llvm::OwningPtr<DiagnosticClient> DiagClient;
147ac0605e9SDouglas Gregor   if (Opts.BinaryOutput) {
148ac0605e9SDouglas Gregor     if (llvm::sys::Program::ChangeStderrToBinary()) {
149ac0605e9SDouglas Gregor       // We weren't able to set standard error to binary, which is a
150ac0605e9SDouglas Gregor       // bit of a problem. So, just create a text diagnostic printer
151ac0605e9SDouglas Gregor       // to complain about this problem, and pretend that the user
152ac0605e9SDouglas Gregor       // didn't try to use binary output.
153ac0605e9SDouglas Gregor       DiagClient.reset(new TextDiagnosticPrinter(llvm::errs(), Opts));
154ac0605e9SDouglas Gregor       Diags->setClient(DiagClient.take());
155ac0605e9SDouglas Gregor       Diags->Report(diag::err_fe_stderr_binary);
156ac0605e9SDouglas Gregor       return Diags.take();
157ac0605e9SDouglas Gregor     } else {
158ac0605e9SDouglas Gregor       DiagClient.reset(new BinaryDiagnosticSerializer(llvm::errs()));
159ac0605e9SDouglas Gregor     }
160ac0605e9SDouglas Gregor   } else {
161ac0605e9SDouglas Gregor     DiagClient.reset(new TextDiagnosticPrinter(llvm::errs(), Opts));
162ac0605e9SDouglas Gregor   }
16350ec0da0SDaniel Dunbar 
16450ec0da0SDaniel Dunbar   // Chain in -verify checker, if requested.
16550ec0da0SDaniel Dunbar   if (Opts.VerifyDiagnostics)
1661b39a2edSDaniel Dunbar     DiagClient.reset(new VerifyDiagnosticsClient(*Diags, DiagClient.take()));
1677d75afc5SDaniel Dunbar 
1687d75afc5SDaniel Dunbar   if (!Opts.DumpBuildInformation.empty())
1697d75afc5SDaniel Dunbar     SetUpBuildDumpLog(Opts, Argc, Argv, DiagClient);
1707d75afc5SDaniel Dunbar 
1717d75afc5SDaniel Dunbar   // Configure our handling of diagnostics.
1721b39a2edSDaniel Dunbar   Diags->setClient(DiagClient.take());
1737d75afc5SDaniel Dunbar   if (ProcessWarningOptions(*Diags, Opts))
1747d75afc5SDaniel Dunbar     return 0;
1757d75afc5SDaniel Dunbar 
1761b39a2edSDaniel Dunbar   return Diags.take();
1777d75afc5SDaniel Dunbar }
1787d75afc5SDaniel Dunbar 
1797d75afc5SDaniel Dunbar // File Manager
1807d75afc5SDaniel Dunbar 
181546a676aSDaniel Dunbar void CompilerInstance::createFileManager() {
182546a676aSDaniel Dunbar   FileMgr.reset(new FileManager());
183546a676aSDaniel Dunbar }
184546a676aSDaniel Dunbar 
1857d75afc5SDaniel Dunbar // Source Manager
1867d75afc5SDaniel Dunbar 
187546a676aSDaniel Dunbar void CompilerInstance::createSourceManager() {
188e0fbb83bSDouglas Gregor   SourceMgr.reset(new SourceManager(getDiagnostics()));
189546a676aSDaniel Dunbar }
190aaa148fdSDaniel Dunbar 
1917d75afc5SDaniel Dunbar // Preprocessor
1927d75afc5SDaniel Dunbar 
193aaa148fdSDaniel Dunbar void CompilerInstance::createPreprocessor() {
194aaa148fdSDaniel Dunbar   PP.reset(createPreprocessor(getDiagnostics(), getLangOpts(),
195aaa148fdSDaniel Dunbar                               getPreprocessorOpts(), getHeaderSearchOpts(),
196aaa148fdSDaniel Dunbar                               getDependencyOutputOpts(), getTarget(),
1973f7b8b27SFariborz Jahanian                               getFrontendOpts(), getSourceManager(),
1983f7b8b27SFariborz Jahanian                               getFileManager()));
199aaa148fdSDaniel Dunbar }
200aaa148fdSDaniel Dunbar 
201aaa148fdSDaniel Dunbar Preprocessor *
202aaa148fdSDaniel Dunbar CompilerInstance::createPreprocessor(Diagnostic &Diags,
203aaa148fdSDaniel Dunbar                                      const LangOptions &LangInfo,
204aaa148fdSDaniel Dunbar                                      const PreprocessorOptions &PPOpts,
205aaa148fdSDaniel Dunbar                                      const HeaderSearchOptions &HSOpts,
206aaa148fdSDaniel Dunbar                                      const DependencyOutputOptions &DepOpts,
207aaa148fdSDaniel Dunbar                                      const TargetInfo &Target,
2083f7b8b27SFariborz Jahanian                                      const FrontendOptions &FEOpts,
209aaa148fdSDaniel Dunbar                                      SourceManager &SourceMgr,
210aaa148fdSDaniel Dunbar                                      FileManager &FileMgr) {
211aaa148fdSDaniel Dunbar   // Create a PTH manager if we are using some form of a token cache.
212aaa148fdSDaniel Dunbar   PTHManager *PTHMgr = 0;
213d6ea9028SDaniel Dunbar   if (!PPOpts.TokenCache.empty())
214d6ea9028SDaniel Dunbar     PTHMgr = PTHManager::Create(PPOpts.TokenCache, Diags);
215aaa148fdSDaniel Dunbar 
216aaa148fdSDaniel Dunbar   // Create the Preprocessor.
217aaa148fdSDaniel Dunbar   HeaderSearch *HeaderInfo = new HeaderSearch(FileMgr);
218aaa148fdSDaniel Dunbar   Preprocessor *PP = new Preprocessor(Diags, LangInfo, Target,
219aaa148fdSDaniel Dunbar                                       SourceMgr, *HeaderInfo, PTHMgr,
220aaa148fdSDaniel Dunbar                                       /*OwnsHeaderSearch=*/true);
221aaa148fdSDaniel Dunbar 
222aaa148fdSDaniel Dunbar   // Note that this is different then passing PTHMgr to Preprocessor's ctor.
223aaa148fdSDaniel Dunbar   // That argument is used as the IdentifierInfoLookup argument to
224aaa148fdSDaniel Dunbar   // IdentifierTable's ctor.
225aaa148fdSDaniel Dunbar   if (PTHMgr) {
226aaa148fdSDaniel Dunbar     PTHMgr->setPreprocessor(PP);
227aaa148fdSDaniel Dunbar     PP->setPTHManager(PTHMgr);
228aaa148fdSDaniel Dunbar   }
229aaa148fdSDaniel Dunbar 
2303f7b8b27SFariborz Jahanian   InitializePreprocessor(*PP, PPOpts, HSOpts, FEOpts);
231aaa148fdSDaniel Dunbar 
232aaa148fdSDaniel Dunbar   // Handle generating dependencies, if requested.
233aaa148fdSDaniel Dunbar   if (!DepOpts.OutputFile.empty())
234aaa148fdSDaniel Dunbar     AttachDependencyFileGen(*PP, DepOpts);
235aaa148fdSDaniel Dunbar 
236aaa148fdSDaniel Dunbar   return PP;
237aaa148fdSDaniel Dunbar }
238df3e30c4SDaniel Dunbar 
239df3e30c4SDaniel Dunbar // ASTContext
240df3e30c4SDaniel Dunbar 
241df3e30c4SDaniel Dunbar void CompilerInstance::createASTContext() {
242df3e30c4SDaniel Dunbar   Preprocessor &PP = getPreprocessor();
243df3e30c4SDaniel Dunbar   Context.reset(new ASTContext(getLangOpts(), PP.getSourceManager(),
244df3e30c4SDaniel Dunbar                                getTarget(), PP.getIdentifierTable(),
245df3e30c4SDaniel Dunbar                                PP.getSelectorTable(), PP.getBuiltinInfo(),
246df3e30c4SDaniel Dunbar                                /*FreeMemory=*/ !getFrontendOpts().DisableFree,
247df3e30c4SDaniel Dunbar                                /*size_reserve=*/ 0));
248df3e30c4SDaniel Dunbar }
249599313efSDaniel Dunbar 
250599313efSDaniel Dunbar // ExternalASTSource
251599313efSDaniel Dunbar 
252599313efSDaniel Dunbar void CompilerInstance::createPCHExternalASTSource(llvm::StringRef Path) {
253599313efSDaniel Dunbar   llvm::OwningPtr<ExternalASTSource> Source;
254599313efSDaniel Dunbar   Source.reset(createPCHExternalASTSource(Path, getHeaderSearchOpts().Sysroot,
255599313efSDaniel Dunbar                                           getPreprocessor(), getASTContext()));
256599313efSDaniel Dunbar   getASTContext().setExternalSource(Source);
257599313efSDaniel Dunbar }
258599313efSDaniel Dunbar 
259599313efSDaniel Dunbar ExternalASTSource *
260599313efSDaniel Dunbar CompilerInstance::createPCHExternalASTSource(llvm::StringRef Path,
261599313efSDaniel Dunbar                                              const std::string &Sysroot,
262599313efSDaniel Dunbar                                              Preprocessor &PP,
263599313efSDaniel Dunbar                                              ASTContext &Context) {
264599313efSDaniel Dunbar   llvm::OwningPtr<PCHReader> Reader;
265599313efSDaniel Dunbar   Reader.reset(new PCHReader(PP, &Context,
266599313efSDaniel Dunbar                              Sysroot.empty() ? 0 : Sysroot.c_str()));
267599313efSDaniel Dunbar 
268599313efSDaniel Dunbar   switch (Reader->ReadPCH(Path)) {
269599313efSDaniel Dunbar   case PCHReader::Success:
270599313efSDaniel Dunbar     // Set the predefines buffer as suggested by the PCH reader. Typically, the
271599313efSDaniel Dunbar     // predefines buffer will be empty.
272599313efSDaniel Dunbar     PP.setPredefines(Reader->getSuggestedPredefines());
273599313efSDaniel Dunbar     return Reader.take();
274599313efSDaniel Dunbar 
275599313efSDaniel Dunbar   case PCHReader::Failure:
276599313efSDaniel Dunbar     // Unrecoverable failure: don't even try to process the input file.
277599313efSDaniel Dunbar     break;
278599313efSDaniel Dunbar 
279599313efSDaniel Dunbar   case PCHReader::IgnorePCH:
280599313efSDaniel Dunbar     // No suitable PCH file could be found. Return an error.
281599313efSDaniel Dunbar     break;
282599313efSDaniel Dunbar   }
283599313efSDaniel Dunbar 
284599313efSDaniel Dunbar   return 0;
285599313efSDaniel Dunbar }
286f7093b5aSDaniel Dunbar 
287f7093b5aSDaniel Dunbar // Code Completion
288f7093b5aSDaniel Dunbar 
289f7093b5aSDaniel Dunbar void CompilerInstance::createCodeCompletionConsumer() {
290f7093b5aSDaniel Dunbar   const ParsedSourceLocation &Loc = getFrontendOpts().CodeCompletionAt;
291f7093b5aSDaniel Dunbar   CompletionConsumer.reset(
292f7093b5aSDaniel Dunbar     createCodeCompletionConsumer(getPreprocessor(),
293f7093b5aSDaniel Dunbar                                  Loc.FileName, Loc.Line, Loc.Column,
294f7093b5aSDaniel Dunbar                                  getFrontendOpts().DebugCodeCompletionPrinter,
295f7093b5aSDaniel Dunbar                                  getFrontendOpts().ShowMacrosInCodeCompletion,
296f7093b5aSDaniel Dunbar                                  llvm::outs()));
297*00a0cf70SDouglas Gregor   if (!CompletionConsumer)
298*00a0cf70SDouglas Gregor     return;
299f09935f1SDouglas Gregor 
300f09935f1SDouglas Gregor   if (CompletionConsumer->isOutputBinary() &&
301f09935f1SDouglas Gregor       llvm::sys::Program::ChangeStdoutToBinary()) {
302f09935f1SDouglas Gregor     getPreprocessor().getDiagnostics().Report(diag::err_fe_stdout_binary);
303f09935f1SDouglas Gregor     CompletionConsumer.reset();
304f09935f1SDouglas Gregor   }
305f7093b5aSDaniel Dunbar }
306f7093b5aSDaniel Dunbar 
3075505dff8SKovarththanan Rajaratnam void CompilerInstance::createFrontendTimer() {
3085505dff8SKovarththanan Rajaratnam   FrontendTimer.reset(new llvm::Timer("Clang front-end timer"));
3095505dff8SKovarththanan Rajaratnam }
3105505dff8SKovarththanan Rajaratnam 
311f7093b5aSDaniel Dunbar CodeCompleteConsumer *
312f7093b5aSDaniel Dunbar CompilerInstance::createCodeCompletionConsumer(Preprocessor &PP,
313f7093b5aSDaniel Dunbar                                                const std::string &Filename,
314f7093b5aSDaniel Dunbar                                                unsigned Line,
315f7093b5aSDaniel Dunbar                                                unsigned Column,
316f7093b5aSDaniel Dunbar                                                bool UseDebugPrinter,
317f7093b5aSDaniel Dunbar                                                bool ShowMacros,
318f7093b5aSDaniel Dunbar                                                llvm::raw_ostream &OS) {
319f7093b5aSDaniel Dunbar   // Tell the source manager to chop off the given file at a specific
320f7093b5aSDaniel Dunbar   // line and column.
321f7093b5aSDaniel Dunbar   const FileEntry *Entry = PP.getFileManager().getFile(Filename);
322f7093b5aSDaniel Dunbar   if (!Entry) {
323f7093b5aSDaniel Dunbar     PP.getDiagnostics().Report(diag::err_fe_invalid_code_complete_file)
324f7093b5aSDaniel Dunbar       << Filename;
325f7093b5aSDaniel Dunbar     return 0;
326f7093b5aSDaniel Dunbar   }
327f7093b5aSDaniel Dunbar 
328f7093b5aSDaniel Dunbar   // Truncate the named file at the given line/column.
32953ad6b94SDouglas Gregor   PP.SetCodeCompletionPoint(Entry, Line, Column);
330f7093b5aSDaniel Dunbar 
331f7093b5aSDaniel Dunbar   // Set up the creation routine for code-completion.
332f7093b5aSDaniel Dunbar   if (UseDebugPrinter)
333f7093b5aSDaniel Dunbar     return new PrintingCodeCompleteConsumer(ShowMacros, OS);
334f7093b5aSDaniel Dunbar   else
335f7093b5aSDaniel Dunbar     return new CIndexCodeCompleteConsumer(ShowMacros, OS);
336f7093b5aSDaniel Dunbar }
337566eeb2dSDaniel Dunbar 
338566eeb2dSDaniel Dunbar // Output Files
339566eeb2dSDaniel Dunbar 
340566eeb2dSDaniel Dunbar void CompilerInstance::addOutputFile(llvm::StringRef Path,
341566eeb2dSDaniel Dunbar                                      llvm::raw_ostream *OS) {
342566eeb2dSDaniel Dunbar   assert(OS && "Attempt to add empty stream to output list!");
343566eeb2dSDaniel Dunbar   OutputFiles.push_back(std::make_pair(Path, OS));
344566eeb2dSDaniel Dunbar }
345566eeb2dSDaniel Dunbar 
3461c558cd7SKovarththanan Rajaratnam void CompilerInstance::clearOutputFiles(bool EraseFiles) {
347566eeb2dSDaniel Dunbar   for (std::list< std::pair<std::string, llvm::raw_ostream*> >::iterator
348566eeb2dSDaniel Dunbar          it = OutputFiles.begin(), ie = OutputFiles.end(); it != ie; ++it) {
349566eeb2dSDaniel Dunbar     delete it->second;
350566eeb2dSDaniel Dunbar     if (EraseFiles && !it->first.empty())
351566eeb2dSDaniel Dunbar       llvm::sys::Path(it->first).eraseFromDisk();
352566eeb2dSDaniel Dunbar   }
353566eeb2dSDaniel Dunbar   OutputFiles.clear();
354566eeb2dSDaniel Dunbar }
355566eeb2dSDaniel Dunbar 
356420b0f1bSDaniel Dunbar llvm::raw_fd_ostream *
357420b0f1bSDaniel Dunbar CompilerInstance::createDefaultOutputFile(bool Binary,
358420b0f1bSDaniel Dunbar                                           llvm::StringRef InFile,
359420b0f1bSDaniel Dunbar                                           llvm::StringRef Extension) {
360420b0f1bSDaniel Dunbar   return createOutputFile(getFrontendOpts().OutputFile, Binary,
361420b0f1bSDaniel Dunbar                           InFile, Extension);
362420b0f1bSDaniel Dunbar }
363420b0f1bSDaniel Dunbar 
364420b0f1bSDaniel Dunbar llvm::raw_fd_ostream *
365420b0f1bSDaniel Dunbar CompilerInstance::createOutputFile(llvm::StringRef OutputPath,
366420b0f1bSDaniel Dunbar                                    bool Binary,
367420b0f1bSDaniel Dunbar                                    llvm::StringRef InFile,
368420b0f1bSDaniel Dunbar                                    llvm::StringRef Extension) {
369420b0f1bSDaniel Dunbar   std::string Error, OutputPathName;
370420b0f1bSDaniel Dunbar   llvm::raw_fd_ostream *OS = createOutputFile(OutputPath, Error, Binary,
371420b0f1bSDaniel Dunbar                                               InFile, Extension,
372420b0f1bSDaniel Dunbar                                               &OutputPathName);
373420b0f1bSDaniel Dunbar   if (!OS) {
3747554699aSDaniel Dunbar     getDiagnostics().Report(diag::err_fe_unable_to_open_output)
3757554699aSDaniel Dunbar       << OutputPath << Error;
3767554699aSDaniel Dunbar     return 0;
377420b0f1bSDaniel Dunbar   }
378420b0f1bSDaniel Dunbar 
379420b0f1bSDaniel Dunbar   // Add the output file -- but don't try to remove "-", since this means we are
380420b0f1bSDaniel Dunbar   // using stdin.
381420b0f1bSDaniel Dunbar   addOutputFile((OutputPathName != "-") ? OutputPathName : "", OS);
382420b0f1bSDaniel Dunbar 
383420b0f1bSDaniel Dunbar   return OS;
384420b0f1bSDaniel Dunbar }
385420b0f1bSDaniel Dunbar 
386420b0f1bSDaniel Dunbar llvm::raw_fd_ostream *
387420b0f1bSDaniel Dunbar CompilerInstance::createOutputFile(llvm::StringRef OutputPath,
388420b0f1bSDaniel Dunbar                                    std::string &Error,
389420b0f1bSDaniel Dunbar                                    bool Binary,
390420b0f1bSDaniel Dunbar                                    llvm::StringRef InFile,
391420b0f1bSDaniel Dunbar                                    llvm::StringRef Extension,
392420b0f1bSDaniel Dunbar                                    std::string *ResultPathName) {
393420b0f1bSDaniel Dunbar   std::string OutFile;
394420b0f1bSDaniel Dunbar   if (!OutputPath.empty()) {
395420b0f1bSDaniel Dunbar     OutFile = OutputPath;
396420b0f1bSDaniel Dunbar   } else if (InFile == "-") {
397420b0f1bSDaniel Dunbar     OutFile = "-";
398420b0f1bSDaniel Dunbar   } else if (!Extension.empty()) {
399420b0f1bSDaniel Dunbar     llvm::sys::Path Path(InFile);
400420b0f1bSDaniel Dunbar     Path.eraseSuffix();
401420b0f1bSDaniel Dunbar     Path.appendSuffix(Extension);
402420b0f1bSDaniel Dunbar     OutFile = Path.str();
403420b0f1bSDaniel Dunbar   } else {
404420b0f1bSDaniel Dunbar     OutFile = "-";
405420b0f1bSDaniel Dunbar   }
406420b0f1bSDaniel Dunbar 
4072eaef18eSDaniel Dunbar   llvm::OwningPtr<llvm::raw_fd_ostream> OS(
408420b0f1bSDaniel Dunbar     new llvm::raw_fd_ostream(OutFile.c_str(), Error,
4092eaef18eSDaniel Dunbar                              (Binary ? llvm::raw_fd_ostream::F_Binary : 0)));
4102eaef18eSDaniel Dunbar   if (!Error.empty())
411420b0f1bSDaniel Dunbar     return 0;
412420b0f1bSDaniel Dunbar 
413420b0f1bSDaniel Dunbar   if (ResultPathName)
414420b0f1bSDaniel Dunbar     *ResultPathName = OutFile;
415420b0f1bSDaniel Dunbar 
4162eaef18eSDaniel Dunbar   return OS.take();
417420b0f1bSDaniel Dunbar }
418409e890fSDaniel Dunbar 
419409e890fSDaniel Dunbar // Initialization Utilities
420409e890fSDaniel Dunbar 
421409e890fSDaniel Dunbar bool CompilerInstance::InitializeSourceManager(llvm::StringRef InputFile) {
422409e890fSDaniel Dunbar   return InitializeSourceManager(InputFile, getDiagnostics(), getFileManager(),
423409e890fSDaniel Dunbar                                  getSourceManager(), getFrontendOpts());
424409e890fSDaniel Dunbar }
425409e890fSDaniel Dunbar 
426409e890fSDaniel Dunbar bool CompilerInstance::InitializeSourceManager(llvm::StringRef InputFile,
427409e890fSDaniel Dunbar                                                Diagnostic &Diags,
428409e890fSDaniel Dunbar                                                FileManager &FileMgr,
429409e890fSDaniel Dunbar                                                SourceManager &SourceMgr,
430409e890fSDaniel Dunbar                                                const FrontendOptions &Opts) {
431409e890fSDaniel Dunbar   // Figure out where to get and map in the main file.
432409e890fSDaniel Dunbar   if (Opts.EmptyInputOnly) {
433409e890fSDaniel Dunbar     const char *EmptyStr = "";
434409e890fSDaniel Dunbar     llvm::MemoryBuffer *SB =
435409e890fSDaniel Dunbar       llvm::MemoryBuffer::getMemBuffer(EmptyStr, EmptyStr, "<empty input>");
436409e890fSDaniel Dunbar     SourceMgr.createMainFileIDForMemBuffer(SB);
437409e890fSDaniel Dunbar   } else if (InputFile != "-") {
438409e890fSDaniel Dunbar     const FileEntry *File = FileMgr.getFile(InputFile);
439409e890fSDaniel Dunbar     if (File) SourceMgr.createMainFileID(File, SourceLocation());
440409e890fSDaniel Dunbar     if (SourceMgr.getMainFileID().isInvalid()) {
441409e890fSDaniel Dunbar       Diags.Report(diag::err_fe_error_reading) << InputFile;
442409e890fSDaniel Dunbar       return false;
443409e890fSDaniel Dunbar     }
444409e890fSDaniel Dunbar   } else {
445409e890fSDaniel Dunbar     llvm::MemoryBuffer *SB = llvm::MemoryBuffer::getSTDIN();
446409e890fSDaniel Dunbar     SourceMgr.createMainFileIDForMemBuffer(SB);
447409e890fSDaniel Dunbar     if (SourceMgr.getMainFileID().isInvalid()) {
448409e890fSDaniel Dunbar       Diags.Report(diag::err_fe_error_reading_stdin);
449409e890fSDaniel Dunbar       return false;
450409e890fSDaniel Dunbar     }
451409e890fSDaniel Dunbar   }
452409e890fSDaniel Dunbar 
453409e890fSDaniel Dunbar   return true;
454409e890fSDaniel Dunbar }
4554f2bc55dSDaniel Dunbar 
4564f2bc55dSDaniel Dunbar // High-Level Operations
4574f2bc55dSDaniel Dunbar 
4584f2bc55dSDaniel Dunbar bool CompilerInstance::ExecuteAction(FrontendAction &Act) {
4594f2bc55dSDaniel Dunbar   assert(hasDiagnostics() && "Diagnostics engine is not initialized!");
4604f2bc55dSDaniel Dunbar   assert(!getFrontendOpts().ShowHelp && "Client must handle '-help'!");
4614f2bc55dSDaniel Dunbar   assert(!getFrontendOpts().ShowVersion && "Client must handle '-version'!");
4624f2bc55dSDaniel Dunbar 
4634f2bc55dSDaniel Dunbar   // FIXME: Take this as an argument, once all the APIs we used have moved to
4644f2bc55dSDaniel Dunbar   // taking it as an input instead of hard-coding llvm::errs.
4654f2bc55dSDaniel Dunbar   llvm::raw_ostream &OS = llvm::errs();
4664f2bc55dSDaniel Dunbar 
4674f2bc55dSDaniel Dunbar   // Create the target instance.
4684f2bc55dSDaniel Dunbar   setTarget(TargetInfo::CreateTargetInfo(getDiagnostics(), getTargetOpts()));
4694f2bc55dSDaniel Dunbar   if (!hasTarget())
4704f2bc55dSDaniel Dunbar     return false;
4714f2bc55dSDaniel Dunbar 
4724f2bc55dSDaniel Dunbar   // Inform the target of the language options.
4734f2bc55dSDaniel Dunbar   //
4744f2bc55dSDaniel Dunbar   // FIXME: We shouldn't need to do this, the target should be immutable once
4754f2bc55dSDaniel Dunbar   // created. This complexity should be lifted elsewhere.
4764f2bc55dSDaniel Dunbar   getTarget().setForcedLangOptions(getLangOpts());
4774f2bc55dSDaniel Dunbar 
4784f2bc55dSDaniel Dunbar   // Validate/process some options.
4794f2bc55dSDaniel Dunbar   if (getHeaderSearchOpts().Verbose)
4804f2bc55dSDaniel Dunbar     OS << "clang -cc1 version " CLANG_VERSION_STRING
4814f2bc55dSDaniel Dunbar        << " based upon " << PACKAGE_STRING
4824f2bc55dSDaniel Dunbar        << " hosted on " << llvm::sys::getHostTriple() << "\n";
4834f2bc55dSDaniel Dunbar 
4844f2bc55dSDaniel Dunbar   if (getFrontendOpts().ShowTimers)
4854f2bc55dSDaniel Dunbar     createFrontendTimer();
4864f2bc55dSDaniel Dunbar 
4874f2bc55dSDaniel Dunbar   for (unsigned i = 0, e = getFrontendOpts().Inputs.size(); i != e; ++i) {
4884f2bc55dSDaniel Dunbar     const std::string &InFile = getFrontendOpts().Inputs[i].second;
4894f2bc55dSDaniel Dunbar 
4904f2bc55dSDaniel Dunbar     // If we aren't using an AST file, setup the file and source managers and
4914f2bc55dSDaniel Dunbar     // the preprocessor.
4924f2bc55dSDaniel Dunbar     bool IsAST = getFrontendOpts().Inputs[i].first == FrontendOptions::IK_AST;
4934f2bc55dSDaniel Dunbar     if (!IsAST) {
4944f2bc55dSDaniel Dunbar       if (!i) {
4954f2bc55dSDaniel Dunbar         // Create a file manager object to provide access to and cache the
4964f2bc55dSDaniel Dunbar         // filesystem.
4974f2bc55dSDaniel Dunbar         createFileManager();
4984f2bc55dSDaniel Dunbar 
4994f2bc55dSDaniel Dunbar         // Create the source manager.
5004f2bc55dSDaniel Dunbar         createSourceManager();
5014f2bc55dSDaniel Dunbar       } else {
5024f2bc55dSDaniel Dunbar         // Reset the ID tables if we are reusing the SourceManager.
5034f2bc55dSDaniel Dunbar         getSourceManager().clearIDTables();
5044f2bc55dSDaniel Dunbar       }
5054f2bc55dSDaniel Dunbar 
5064f2bc55dSDaniel Dunbar       // Create the preprocessor.
5074f2bc55dSDaniel Dunbar       createPreprocessor();
5084f2bc55dSDaniel Dunbar     }
5094f2bc55dSDaniel Dunbar 
5104f2bc55dSDaniel Dunbar     if (Act.BeginSourceFile(*this, InFile, IsAST)) {
5114f2bc55dSDaniel Dunbar       Act.Execute();
5124f2bc55dSDaniel Dunbar       Act.EndSourceFile();
5134f2bc55dSDaniel Dunbar     }
5144f2bc55dSDaniel Dunbar   }
5154f2bc55dSDaniel Dunbar 
5164f2bc55dSDaniel Dunbar   if (getDiagnosticOpts().ShowCarets)
5174f2bc55dSDaniel Dunbar     if (unsigned NumDiagnostics = getDiagnostics().getNumDiagnostics())
5184f2bc55dSDaniel Dunbar       OS << NumDiagnostics << " diagnostic"
5194f2bc55dSDaniel Dunbar          << (NumDiagnostics == 1 ? "" : "s")
5204f2bc55dSDaniel Dunbar          << " generated.\n";
5214f2bc55dSDaniel Dunbar 
5224f2bc55dSDaniel Dunbar   if (getFrontendOpts().ShowStats) {
5234f2bc55dSDaniel Dunbar     getFileManager().PrintStats();
5244f2bc55dSDaniel Dunbar     OS << "\n";
5254f2bc55dSDaniel Dunbar   }
5264f2bc55dSDaniel Dunbar 
5274f2bc55dSDaniel Dunbar   // Return the appropriate status when verifying diagnostics.
5284f2bc55dSDaniel Dunbar   //
5294f2bc55dSDaniel Dunbar   // FIXME: If we could make getNumErrors() do the right thing, we wouldn't need
5304f2bc55dSDaniel Dunbar   // this.
5314f2bc55dSDaniel Dunbar   if (getDiagnosticOpts().VerifyDiagnostics)
5324f2bc55dSDaniel Dunbar     return !static_cast<VerifyDiagnosticsClient&>(
5334f2bc55dSDaniel Dunbar       getDiagnosticClient()).HadErrors();
5344f2bc55dSDaniel Dunbar 
5354f2bc55dSDaniel Dunbar   return !getDiagnostics().getNumErrors();
5364f2bc55dSDaniel Dunbar }
5374f2bc55dSDaniel Dunbar 
5384f2bc55dSDaniel Dunbar 
539