CompilerInstance.cpp revision 210299
1293010Sadrian//===--- CompilerInstance.cpp ---------------------------------------------===//
2293010Sadrian//
3293010Sadrian//                     The LLVM Compiler Infrastructure
4293010Sadrian//
5293010Sadrian// This file is distributed under the University of Illinois Open Source
6293010Sadrian// License. See LICENSE.TXT for details.
7293010Sadrian//
8293010Sadrian//===----------------------------------------------------------------------===//
9293010Sadrian
10293010Sadrian#include "clang/Frontend/CompilerInstance.h"
11293010Sadrian#include "clang/AST/ASTConsumer.h"
12293010Sadrian#include "clang/AST/ASTContext.h"
13293010Sadrian#include "clang/Basic/Diagnostic.h"
14293010Sadrian#include "clang/Basic/FileManager.h"
15293010Sadrian#include "clang/Basic/SourceManager.h"
16293010Sadrian#include "clang/Basic/TargetInfo.h"
17293010Sadrian#include "clang/Basic/Version.h"
18293010Sadrian#include "clang/Lex/HeaderSearch.h"
19293010Sadrian#include "clang/Lex/Preprocessor.h"
20293010Sadrian#include "clang/Lex/PTHManager.h"
21293010Sadrian#include "clang/Frontend/ChainedDiagnosticClient.h"
22293010Sadrian#include "clang/Frontend/FrontendAction.h"
23293010Sadrian#include "clang/Frontend/PCHReader.h"
24293010Sadrian#include "clang/Frontend/FrontendDiagnostic.h"
25293010Sadrian#include "clang/Frontend/TextDiagnosticPrinter.h"
26293010Sadrian#include "clang/Frontend/VerifyDiagnosticsClient.h"
27293010Sadrian#include "clang/Frontend/Utils.h"
28293010Sadrian#include "clang/Sema/CodeCompleteConsumer.h"
29293010Sadrian#include "llvm/LLVMContext.h"
30293010Sadrian#include "llvm/Support/MemoryBuffer.h"
31293010Sadrian#include "llvm/Support/raw_ostream.h"
32293010Sadrian#include "llvm/ADT/Statistic.h"
33293010Sadrian#include "llvm/Support/Timer.h"
34293010Sadrian#include "llvm/System/Host.h"
35293010Sadrian#include "llvm/System/Path.h"
36293010Sadrian#include "llvm/System/Program.h"
37293010Sadrianusing namespace clang;
38293010Sadrian
39293010SadrianCompilerInstance::CompilerInstance()
40293010Sadrian  : Invocation(new CompilerInvocation()), Reader(0) {
41293010Sadrian}
42293010Sadrian
43293010SadrianCompilerInstance::~CompilerInstance() {
44293010Sadrian}
45293010Sadrian
46293010Sadrianvoid CompilerInstance::setLLVMContext(llvm::LLVMContext *Value) {
47293010Sadrian  LLVMContext.reset(Value);
48293010Sadrian}
49293010Sadrian
50293010Sadrianvoid CompilerInstance::setInvocation(CompilerInvocation *Value) {
51293010Sadrian  Invocation.reset(Value);
52293010Sadrian}
53293010Sadrian
54293010Sadrianvoid CompilerInstance::setDiagnostics(Diagnostic *Value) {
55293010Sadrian  Diagnostics = Value;
56293010Sadrian}
57293010Sadrian
58293010Sadrianvoid CompilerInstance::setDiagnosticClient(DiagnosticClient *Value) {
59293010Sadrian  DiagClient.reset(Value);
60293010Sadrian}
61293010Sadrian
62293010Sadrianvoid CompilerInstance::setTarget(TargetInfo *Value) {
63293010Sadrian  Target.reset(Value);
64293010Sadrian}
65293010Sadrian
66293010Sadrianvoid CompilerInstance::setFileManager(FileManager *Value) {
67293010Sadrian  FileMgr.reset(Value);
68293010Sadrian}
69293010Sadrian
70293010Sadrianvoid CompilerInstance::setSourceManager(SourceManager *Value) {
71293010Sadrian  SourceMgr.reset(Value);
72293010Sadrian}
73293010Sadrian
74293010Sadrianvoid CompilerInstance::setPreprocessor(Preprocessor *Value) {
75293010Sadrian  PP.reset(Value);
76293010Sadrian}
77293010Sadrian
78293010Sadrianvoid CompilerInstance::setASTContext(ASTContext *Value) {
79293010Sadrian  Context.reset(Value);
80293010Sadrian}
81293010Sadrian
82293010Sadrianvoid CompilerInstance::setASTConsumer(ASTConsumer *Value) {
83293010Sadrian  Consumer.reset(Value);
84293010Sadrian}
85293010Sadrian
86293010Sadrianvoid CompilerInstance::setCodeCompletionConsumer(CodeCompleteConsumer *Value) {
87293010Sadrian  CompletionConsumer.reset(Value);
88293010Sadrian}
89293010Sadrian
90293010Sadrian// Diagnostics
91293010Sadriannamespace {
92293010Sadrian  class BinaryDiagnosticSerializer : public DiagnosticClient {
93293010Sadrian    llvm::raw_ostream &OS;
94293010Sadrian    SourceManager *SourceMgr;
95293010Sadrian  public:
96293010Sadrian    explicit BinaryDiagnosticSerializer(llvm::raw_ostream &OS)
97293010Sadrian      : OS(OS), SourceMgr(0) { }
98293010Sadrian
99293010Sadrian    virtual void HandleDiagnostic(Diagnostic::Level DiagLevel,
100293010Sadrian                                  const DiagnosticInfo &Info);
101293010Sadrian  };
102293010Sadrian}
103293010Sadrian
104293010Sadrianvoid BinaryDiagnosticSerializer::HandleDiagnostic(Diagnostic::Level DiagLevel,
105293010Sadrian                                                  const DiagnosticInfo &Info) {
106293010Sadrian  StoredDiagnostic(DiagLevel, Info).Serialize(OS);
107293010Sadrian}
108293010Sadrian
109293010Sadrianstatic void SetUpBuildDumpLog(const DiagnosticOptions &DiagOpts,
110293010Sadrian                              unsigned argc, char **argv,
111293010Sadrian                              Diagnostic &Diags) {
112293010Sadrian  std::string ErrorInfo;
113293010Sadrian  llvm::OwningPtr<llvm::raw_ostream> OS(
114293010Sadrian    new llvm::raw_fd_ostream(DiagOpts.DumpBuildInformation.c_str(), ErrorInfo));
115293010Sadrian  if (!ErrorInfo.empty()) {
116293010Sadrian    Diags.Report(diag::err_fe_unable_to_open_logfile)
117293010Sadrian                 << DiagOpts.DumpBuildInformation << ErrorInfo;
118293010Sadrian    return;
119293010Sadrian  }
120293010Sadrian
121293010Sadrian  (*OS) << "clang -cc1 command line arguments: ";
122293010Sadrian  for (unsigned i = 0; i != argc; ++i)
123293010Sadrian    (*OS) << argv[i] << ' ';
124293010Sadrian  (*OS) << '\n';
125293010Sadrian
126293010Sadrian  // Chain in a diagnostic client which will log the diagnostics.
127293010Sadrian  DiagnosticClient *Logger =
128293010Sadrian    new TextDiagnosticPrinter(*OS.take(), DiagOpts, /*OwnsOutputStream=*/true);
129293010Sadrian  Diags.setClient(new ChainedDiagnosticClient(Diags.getClient(), Logger));
130293010Sadrian}
131293010Sadrian
132293010Sadrianvoid CompilerInstance::createDiagnostics(int Argc, char **Argv) {
133293010Sadrian  Diagnostics = createDiagnostics(getDiagnosticOpts(), Argc, Argv);
134293010Sadrian
135293010Sadrian  if (Diagnostics)
136293010Sadrian    DiagClient.reset(Diagnostics->getClient());
137293010Sadrian}
138293010Sadrian
139293010Sadrianllvm::IntrusiveRefCntPtr<Diagnostic>
140293010SadrianCompilerInstance::createDiagnostics(const DiagnosticOptions &Opts,
141293010Sadrian                                    int Argc, char **Argv) {
142293010Sadrian  llvm::IntrusiveRefCntPtr<Diagnostic> Diags(new Diagnostic());
143293010Sadrian
144293010Sadrian  // Create the diagnostic client for reporting errors or for
145293010Sadrian  // implementing -verify.
146293010Sadrian  llvm::OwningPtr<DiagnosticClient> DiagClient;
147293010Sadrian  if (Opts.BinaryOutput) {
148293010Sadrian    if (llvm::sys::Program::ChangeStderrToBinary()) {
149293010Sadrian      // We weren't able to set standard error to binary, which is a
150293010Sadrian      // bit of a problem. So, just create a text diagnostic printer
151293010Sadrian      // to complain about this problem, and pretend that the user
152293010Sadrian      // didn't try to use binary output.
153293010Sadrian      DiagClient.reset(new TextDiagnosticPrinter(llvm::errs(), Opts));
154293010Sadrian      Diags->setClient(DiagClient.take());
155293010Sadrian      Diags->Report(diag::err_fe_stderr_binary);
156293010Sadrian      return Diags;
157293010Sadrian    } else {
158293010Sadrian      DiagClient.reset(new BinaryDiagnosticSerializer(llvm::errs()));
159293010Sadrian    }
160293010Sadrian  } else {
161293010Sadrian    DiagClient.reset(new TextDiagnosticPrinter(llvm::errs(), Opts));
162293010Sadrian  }
163293010Sadrian
164293010Sadrian  // Chain in -verify checker, if requested.
165293010Sadrian  if (Opts.VerifyDiagnostics)
166293010Sadrian    DiagClient.reset(new VerifyDiagnosticsClient(*Diags, DiagClient.take()));
167293010Sadrian
168293010Sadrian  Diags->setClient(DiagClient.take());
169293010Sadrian  if (!Opts.DumpBuildInformation.empty())
170293010Sadrian    SetUpBuildDumpLog(Opts, Argc, Argv, *Diags);
171293010Sadrian
172293010Sadrian  // Configure our handling of diagnostics.
173293010Sadrian  ProcessWarningOptions(*Diags, Opts);
174293010Sadrian
175293010Sadrian  return Diags;
176293010Sadrian}
177293010Sadrian
178293010Sadrian// File Manager
179293010Sadrian
180293010Sadrianvoid CompilerInstance::createFileManager() {
181293010Sadrian  FileMgr.reset(new FileManager());
182293010Sadrian}
183293010Sadrian
184293010Sadrian// Source Manager
185293010Sadrian
186293010Sadrianvoid CompilerInstance::createSourceManager() {
187293010Sadrian  SourceMgr.reset(new SourceManager(getDiagnostics()));
188293010Sadrian}
189293010Sadrian
190293010Sadrian// Preprocessor
191293010Sadrian
192293010Sadrianvoid CompilerInstance::createPreprocessor() {
193293010Sadrian  PP.reset(createPreprocessor(getDiagnostics(), getLangOpts(),
194293010Sadrian                              getPreprocessorOpts(), getHeaderSearchOpts(),
195293010Sadrian                              getDependencyOutputOpts(), getTarget(),
196293010Sadrian                              getFrontendOpts(), getSourceManager(),
197293010Sadrian                              getFileManager()));
198293010Sadrian}
199293010Sadrian
200293010SadrianPreprocessor *
201293010SadrianCompilerInstance::createPreprocessor(Diagnostic &Diags,
202293010Sadrian                                     const LangOptions &LangInfo,
203293010Sadrian                                     const PreprocessorOptions &PPOpts,
204293010Sadrian                                     const HeaderSearchOptions &HSOpts,
205293010Sadrian                                     const DependencyOutputOptions &DepOpts,
206293010Sadrian                                     const TargetInfo &Target,
207293010Sadrian                                     const FrontendOptions &FEOpts,
208293010Sadrian                                     SourceManager &SourceMgr,
209293010Sadrian                                     FileManager &FileMgr) {
210293010Sadrian  // Create a PTH manager if we are using some form of a token cache.
211293010Sadrian  PTHManager *PTHMgr = 0;
212293010Sadrian  if (!PPOpts.TokenCache.empty())
213293010Sadrian    PTHMgr = PTHManager::Create(PPOpts.TokenCache, Diags);
214293010Sadrian
215293010Sadrian  // Create the Preprocessor.
216293010Sadrian  HeaderSearch *HeaderInfo = new HeaderSearch(FileMgr);
217293010Sadrian  Preprocessor *PP = new Preprocessor(Diags, LangInfo, Target,
218293010Sadrian                                      SourceMgr, *HeaderInfo, PTHMgr,
219293010Sadrian                                      /*OwnsHeaderSearch=*/true);
220293010Sadrian
221293010Sadrian  // Note that this is different then passing PTHMgr to Preprocessor's ctor.
222293010Sadrian  // That argument is used as the IdentifierInfoLookup argument to
223293010Sadrian  // IdentifierTable's ctor.
224293010Sadrian  if (PTHMgr) {
225293010Sadrian    PTHMgr->setPreprocessor(PP);
226293010Sadrian    PP->setPTHManager(PTHMgr);
227293010Sadrian  }
228293010Sadrian
229293010Sadrian  if (PPOpts.DetailedRecord)
230293010Sadrian    PP->createPreprocessingRecord();
231293010Sadrian
232293010Sadrian  InitializePreprocessor(*PP, PPOpts, HSOpts, FEOpts);
233293010Sadrian
234293010Sadrian  // Handle generating dependencies, if requested.
235293010Sadrian  if (!DepOpts.OutputFile.empty())
236293010Sadrian    AttachDependencyFileGen(*PP, DepOpts);
237293010Sadrian
238293010Sadrian  return PP;
239293010Sadrian}
240293010Sadrian
241293010Sadrian// ASTContext
242293010Sadrian
243293010Sadrianvoid CompilerInstance::createASTContext() {
244293010Sadrian  Preprocessor &PP = getPreprocessor();
245293010Sadrian  Context.reset(new ASTContext(getLangOpts(), PP.getSourceManager(),
246293010Sadrian                               getTarget(), PP.getIdentifierTable(),
247293010Sadrian                               PP.getSelectorTable(), PP.getBuiltinInfo(),
248293010Sadrian                               /*FreeMemory=*/ !getFrontendOpts().DisableFree,
249293010Sadrian                               /*size_reserve=*/ 0));
250293010Sadrian}
251293010Sadrian
252293010Sadrian// ExternalASTSource
253293010Sadrian
254293010Sadrianvoid CompilerInstance::createPCHExternalASTSource(llvm::StringRef Path) {
255293010Sadrian  llvm::OwningPtr<ExternalASTSource> Source;
256293010Sadrian  Source.reset(createPCHExternalASTSource(Path, getHeaderSearchOpts().Sysroot,
257293010Sadrian                                          getPreprocessor(), getASTContext()));
258293010Sadrian  // Remember the PCHReader, but in a non-owning way.
259293010Sadrian  Reader = static_cast<PCHReader*>(Source.get());
260293010Sadrian  getASTContext().setExternalSource(Source);
261293010Sadrian}
262293010Sadrian
263293010SadrianExternalASTSource *
264293010SadrianCompilerInstance::createPCHExternalASTSource(llvm::StringRef Path,
265293010Sadrian                                             const std::string &Sysroot,
266293010Sadrian                                             Preprocessor &PP,
267293010Sadrian                                             ASTContext &Context) {
268293010Sadrian  llvm::OwningPtr<PCHReader> Reader;
269293010Sadrian  Reader.reset(new PCHReader(PP, &Context,
270293010Sadrian                             Sysroot.empty() ? 0 : Sysroot.c_str()));
271293010Sadrian
272293010Sadrian  switch (Reader->ReadPCH(Path)) {
273293010Sadrian  case PCHReader::Success:
274293010Sadrian    // Set the predefines buffer as suggested by the PCH reader. Typically, the
275293010Sadrian    // predefines buffer will be empty.
276293010Sadrian    PP.setPredefines(Reader->getSuggestedPredefines());
277293010Sadrian    return Reader.take();
278293010Sadrian
279293010Sadrian  case PCHReader::Failure:
280293010Sadrian    // Unrecoverable failure: don't even try to process the input file.
281293010Sadrian    break;
282293010Sadrian
283293010Sadrian  case PCHReader::IgnorePCH:
284293010Sadrian    // No suitable PCH file could be found. Return an error.
285293010Sadrian    break;
286293010Sadrian  }
287293010Sadrian
288293010Sadrian  return 0;
289293010Sadrian}
290293010Sadrian
291293010Sadrian// Code Completion
292293010Sadrian
293293010Sadrianvoid CompilerInstance::createCodeCompletionConsumer() {
294293010Sadrian  const ParsedSourceLocation &Loc = getFrontendOpts().CodeCompletionAt;
295293010Sadrian  CompletionConsumer.reset(
296293010Sadrian    createCodeCompletionConsumer(getPreprocessor(),
297293010Sadrian                                 Loc.FileName, Loc.Line, Loc.Column,
298293010Sadrian                                 getFrontendOpts().DebugCodeCompletionPrinter,
299293010Sadrian                                 getFrontendOpts().ShowMacrosInCodeCompletion,
300293010Sadrian                             getFrontendOpts().ShowCodePatternsInCodeCompletion,
301293010Sadrian                                 llvm::outs()));
302293010Sadrian  if (!CompletionConsumer)
303293010Sadrian    return;
304293010Sadrian
305293010Sadrian  if (CompletionConsumer->isOutputBinary() &&
306293010Sadrian      llvm::sys::Program::ChangeStdoutToBinary()) {
307293010Sadrian    getPreprocessor().getDiagnostics().Report(diag::err_fe_stdout_binary);
308293010Sadrian    CompletionConsumer.reset();
309293010Sadrian  }
310293010Sadrian}
311293010Sadrian
312293010Sadrianvoid CompilerInstance::createFrontendTimer() {
313293010Sadrian  FrontendTimer.reset(new llvm::Timer("Clang front-end timer"));
314293010Sadrian}
315293010Sadrian
316293010SadrianCodeCompleteConsumer *
317293010SadrianCompilerInstance::createCodeCompletionConsumer(Preprocessor &PP,
318293010Sadrian                                               const std::string &Filename,
319293010Sadrian                                               unsigned Line,
320293010Sadrian                                               unsigned Column,
321293010Sadrian                                               bool UseDebugPrinter,
322293010Sadrian                                               bool ShowMacros,
323293010Sadrian                                               bool ShowCodePatterns,
324293010Sadrian                                               llvm::raw_ostream &OS) {
325293010Sadrian  // Tell the source manager to chop off the given file at a specific
326293010Sadrian  // line and column.
327293010Sadrian  const FileEntry *Entry = PP.getFileManager().getFile(Filename);
328293010Sadrian  if (!Entry) {
329293010Sadrian    PP.getDiagnostics().Report(diag::err_fe_invalid_code_complete_file)
330293010Sadrian      << Filename;
331293010Sadrian    return 0;
332293010Sadrian  }
333293010Sadrian
334293010Sadrian  // Truncate the named file at the given line/column.
335293010Sadrian  PP.SetCodeCompletionPoint(Entry, Line, Column);
336293010Sadrian
337293010Sadrian  // Set up the creation routine for code-completion.
338293010Sadrian  if (UseDebugPrinter)
339293010Sadrian    return new PrintingCodeCompleteConsumer(ShowMacros, ShowCodePatterns, OS);
340293010Sadrian  else
341293010Sadrian    return new CIndexCodeCompleteConsumer(ShowMacros, ShowCodePatterns, OS);
342293010Sadrian}
343293010Sadrian
344293010Sadrian// Output Files
345293010Sadrian
346293010Sadrianvoid CompilerInstance::addOutputFile(llvm::StringRef Path,
347293010Sadrian                                     llvm::raw_ostream *OS) {
348293010Sadrian  assert(OS && "Attempt to add empty stream to output list!");
349293010Sadrian  OutputFiles.push_back(std::make_pair(Path, OS));
350293010Sadrian}
351293010Sadrian
352293010Sadrianvoid CompilerInstance::clearOutputFiles(bool EraseFiles) {
353293010Sadrian  for (std::list< std::pair<std::string, llvm::raw_ostream*> >::iterator
354293010Sadrian         it = OutputFiles.begin(), ie = OutputFiles.end(); it != ie; ++it) {
355293010Sadrian    delete it->second;
356293010Sadrian    if (EraseFiles && !it->first.empty())
357293010Sadrian      llvm::sys::Path(it->first).eraseFromDisk();
358293010Sadrian  }
359293010Sadrian  OutputFiles.clear();
360293010Sadrian}
361293010Sadrian
362293010Sadrianllvm::raw_fd_ostream *
363293010SadrianCompilerInstance::createDefaultOutputFile(bool Binary,
364293010Sadrian                                          llvm::StringRef InFile,
365293010Sadrian                                          llvm::StringRef Extension) {
366293010Sadrian  return createOutputFile(getFrontendOpts().OutputFile, Binary,
367293010Sadrian                          InFile, Extension);
368293010Sadrian}
369293010Sadrian
370293010Sadrianllvm::raw_fd_ostream *
371293010SadrianCompilerInstance::createOutputFile(llvm::StringRef OutputPath,
372293010Sadrian                                   bool Binary,
373293010Sadrian                                   llvm::StringRef InFile,
374293010Sadrian                                   llvm::StringRef Extension) {
375293010Sadrian  std::string Error, OutputPathName;
376293010Sadrian  llvm::raw_fd_ostream *OS = createOutputFile(OutputPath, Error, Binary,
377293010Sadrian                                              InFile, Extension,
378293010Sadrian                                              &OutputPathName);
379293010Sadrian  if (!OS) {
380293010Sadrian    getDiagnostics().Report(diag::err_fe_unable_to_open_output)
381293010Sadrian      << OutputPath << Error;
382293010Sadrian    return 0;
383293010Sadrian  }
384293010Sadrian
385293010Sadrian  // Add the output file -- but don't try to remove "-", since this means we are
386293010Sadrian  // using stdin.
387293010Sadrian  addOutputFile((OutputPathName != "-") ? OutputPathName : "", OS);
388293010Sadrian
389293010Sadrian  return OS;
390293010Sadrian}
391293010Sadrian
392293010Sadrianllvm::raw_fd_ostream *
393293010SadrianCompilerInstance::createOutputFile(llvm::StringRef OutputPath,
394293010Sadrian                                   std::string &Error,
395293010Sadrian                                   bool Binary,
396293010Sadrian                                   llvm::StringRef InFile,
397293010Sadrian                                   llvm::StringRef Extension,
398293010Sadrian                                   std::string *ResultPathName) {
399293010Sadrian  std::string OutFile;
400293010Sadrian  if (!OutputPath.empty()) {
401293010Sadrian    OutFile = OutputPath;
402293010Sadrian  } else if (InFile == "-") {
403293010Sadrian    OutFile = "-";
404293010Sadrian  } else if (!Extension.empty()) {
405293010Sadrian    llvm::sys::Path Path(InFile);
406293010Sadrian    Path.eraseSuffix();
407293010Sadrian    Path.appendSuffix(Extension);
408293010Sadrian    OutFile = Path.str();
409293010Sadrian  } else {
410293010Sadrian    OutFile = "-";
411293010Sadrian  }
412293010Sadrian
413293010Sadrian  llvm::OwningPtr<llvm::raw_fd_ostream> OS(
414293010Sadrian    new llvm::raw_fd_ostream(OutFile.c_str(), Error,
415293010Sadrian                             (Binary ? llvm::raw_fd_ostream::F_Binary : 0)));
416293010Sadrian  if (!Error.empty())
417293010Sadrian    return 0;
418293010Sadrian
419293010Sadrian  if (ResultPathName)
420293010Sadrian    *ResultPathName = OutFile;
421293010Sadrian
422293010Sadrian  return OS.take();
423293010Sadrian}
424293010Sadrian
425293010Sadrian// Initialization Utilities
426293010Sadrian
427293010Sadrianbool CompilerInstance::InitializeSourceManager(llvm::StringRef InputFile) {
428293010Sadrian  return InitializeSourceManager(InputFile, getDiagnostics(), getFileManager(),
429293010Sadrian                                 getSourceManager(), getFrontendOpts());
430293010Sadrian}
431293010Sadrian
432293010Sadrianbool CompilerInstance::InitializeSourceManager(llvm::StringRef InputFile,
433293010Sadrian                                               Diagnostic &Diags,
434293010Sadrian                                               FileManager &FileMgr,
435293010Sadrian                                               SourceManager &SourceMgr,
436293010Sadrian                                               const FrontendOptions &Opts) {
437293010Sadrian  // Figure out where to get and map in the main file.
438293010Sadrian  if (InputFile != "-") {
439293010Sadrian    const FileEntry *File = FileMgr.getFile(InputFile);
440293010Sadrian    if (File) SourceMgr.createMainFileID(File, SourceLocation());
441293010Sadrian    if (SourceMgr.getMainFileID().isInvalid()) {
442293010Sadrian      Diags.Report(diag::err_fe_error_reading) << InputFile;
443293010Sadrian      return false;
444293010Sadrian    }
445293010Sadrian  } else {
446293010Sadrian    llvm::MemoryBuffer *SB = llvm::MemoryBuffer::getSTDIN();
447293010Sadrian    if (SB) SourceMgr.createMainFileIDForMemBuffer(SB);
448293010Sadrian    if (SourceMgr.getMainFileID().isInvalid()) {
449293010Sadrian      Diags.Report(diag::err_fe_error_reading_stdin);
450293010Sadrian      return false;
451293010Sadrian    }
452293010Sadrian  }
453293010Sadrian
454293010Sadrian  return true;
455293010Sadrian}
456293010Sadrian
457293010Sadrian// High-Level Operations
458293010Sadrian
459293010Sadrianbool CompilerInstance::ExecuteAction(FrontendAction &Act) {
460293010Sadrian  assert(hasDiagnostics() && "Diagnostics engine is not initialized!");
461293010Sadrian  assert(!getFrontendOpts().ShowHelp && "Client must handle '-help'!");
462293010Sadrian  assert(!getFrontendOpts().ShowVersion && "Client must handle '-version'!");
463293010Sadrian
464293010Sadrian  // FIXME: Take this as an argument, once all the APIs we used have moved to
465293010Sadrian  // taking it as an input instead of hard-coding llvm::errs.
466293010Sadrian  llvm::raw_ostream &OS = llvm::errs();
467293010Sadrian
468293010Sadrian  // Create the target instance.
469293010Sadrian  setTarget(TargetInfo::CreateTargetInfo(getDiagnostics(), getTargetOpts()));
470293010Sadrian  if (!hasTarget())
471293010Sadrian    return false;
472293010Sadrian
473293010Sadrian  // Inform the target of the language options.
474293010Sadrian  //
475293010Sadrian  // FIXME: We shouldn't need to do this, the target should be immutable once
476293010Sadrian  // created. This complexity should be lifted elsewhere.
477293010Sadrian  getTarget().setForcedLangOptions(getLangOpts());
478293010Sadrian
479293010Sadrian  // Validate/process some options.
480293010Sadrian  if (getHeaderSearchOpts().Verbose)
481293010Sadrian    OS << "clang -cc1 version " CLANG_VERSION_STRING
482293010Sadrian       << " based upon " << PACKAGE_STRING
483293010Sadrian       << " hosted on " << llvm::sys::getHostTriple() << "\n";
484293010Sadrian
485293010Sadrian  if (getFrontendOpts().ShowTimers)
486293010Sadrian    createFrontendTimer();
487293010Sadrian
488293010Sadrian  if (getFrontendOpts().ShowStats)
489293010Sadrian    llvm::EnableStatistics();
490293010Sadrian
491293010Sadrian  for (unsigned i = 0, e = getFrontendOpts().Inputs.size(); i != e; ++i) {
492293010Sadrian    const std::string &InFile = getFrontendOpts().Inputs[i].second;
493293010Sadrian
494293010Sadrian    // Reset the ID tables if we are reusing the SourceManager.
495293010Sadrian    if (hasSourceManager())
496293010Sadrian      getSourceManager().clearIDTables();
497293010Sadrian
498293010Sadrian    if (Act.BeginSourceFile(*this, InFile, getFrontendOpts().Inputs[i].first)) {
499293010Sadrian      Act.Execute();
500293010Sadrian      Act.EndSourceFile();
501293010Sadrian    }
502293010Sadrian  }
503293010Sadrian
504293010Sadrian  if (getDiagnosticOpts().ShowCarets) {
505293010Sadrian    unsigned NumWarnings = getDiagnostics().getNumWarnings();
506293010Sadrian    unsigned NumErrors = getDiagnostics().getNumErrors() -
507293010Sadrian                               getDiagnostics().getNumErrorsSuppressed();
508293010Sadrian
509293010Sadrian    if (NumWarnings)
510293010Sadrian      OS << NumWarnings << " warning" << (NumWarnings == 1 ? "" : "s");
511293010Sadrian    if (NumWarnings && NumErrors)
512293010Sadrian      OS << " and ";
513293010Sadrian    if (NumErrors)
514293010Sadrian      OS << NumErrors << " error" << (NumErrors == 1 ? "" : "s");
515293010Sadrian    if (NumWarnings || NumErrors)
516293010Sadrian      OS << " generated.\n";
517293010Sadrian  }
518293010Sadrian
519293010Sadrian  if (getFrontendOpts().ShowStats && hasFileManager()) {
520293010Sadrian    getFileManager().PrintStats();
521293010Sadrian    OS << "\n";
522293010Sadrian  }
523293010Sadrian
524293010Sadrian  // Return the appropriate status when verifying diagnostics.
525293010Sadrian  //
526293010Sadrian  // FIXME: If we could make getNumErrors() do the right thing, we wouldn't need
527293010Sadrian  // this.
528293010Sadrian  if (getDiagnosticOpts().VerifyDiagnostics)
529293010Sadrian    return !static_cast<VerifyDiagnosticsClient&>(
530293010Sadrian      getDiagnosticClient()).HadErrors();
531293010Sadrian
532293010Sadrian  return !getDiagnostics().getNumErrors();
533293010Sadrian}
534293010Sadrian
535293010Sadrian
536293010Sadrian