Home | History | Annotate | Download | only in Frontend
      1 //===--- 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"
     11 #include "clang/Sema/Sema.h"
     12 #include "clang/AST/ASTConsumer.h"
     13 #include "clang/AST/ASTContext.h"
     14 #include "clang/Basic/Diagnostic.h"
     15 #include "clang/Basic/FileManager.h"
     16 #include "clang/Basic/SourceManager.h"
     17 #include "clang/Basic/TargetInfo.h"
     18 #include "clang/Basic/Version.h"
     19 #include "clang/Lex/HeaderSearch.h"
     20 #include "clang/Lex/Preprocessor.h"
     21 #include "clang/Lex/PTHManager.h"
     22 #include "clang/Frontend/ChainedDiagnosticClient.h"
     23 #include "clang/Frontend/FrontendAction.h"
     24 #include "clang/Frontend/FrontendDiagnostic.h"
     25 #include "clang/Frontend/LogDiagnosticPrinter.h"
     26 #include "clang/Frontend/TextDiagnosticPrinter.h"
     27 #include "clang/Frontend/VerifyDiagnosticsClient.h"
     28 #include "clang/Frontend/Utils.h"
     29 #include "clang/Serialization/ASTReader.h"
     30 #include "clang/Sema/CodeCompleteConsumer.h"
     31 #include "llvm/Support/FileSystem.h"
     32 #include "llvm/Support/MemoryBuffer.h"
     33 #include "llvm/Support/raw_ostream.h"
     34 #include "llvm/ADT/Statistic.h"
     35 #include "llvm/Support/Timer.h"
     36 #include "llvm/Support/Host.h"
     37 #include "llvm/Support/Path.h"
     38 #include "llvm/Support/Program.h"
     39 #include "llvm/Support/Signals.h"
     40 #include "llvm/Support/system_error.h"
     41 #include "llvm/Config/config.h"
     42 using namespace clang;
     43 
     44 CompilerInstance::CompilerInstance()
     45   : Invocation(new CompilerInvocation()), ModuleManager(0) {
     46 }
     47 
     48 CompilerInstance::~CompilerInstance() {
     49 }
     50 
     51 void CompilerInstance::setInvocation(CompilerInvocation *Value) {
     52   Invocation = Value;
     53 }
     54 
     55 void CompilerInstance::setDiagnostics(Diagnostic *Value) {
     56   Diagnostics = Value;
     57 }
     58 
     59 void CompilerInstance::setTarget(TargetInfo *Value) {
     60   Target = Value;
     61 }
     62 
     63 void CompilerInstance::setFileManager(FileManager *Value) {
     64   FileMgr = Value;
     65 }
     66 
     67 void CompilerInstance::setSourceManager(SourceManager *Value) {
     68   SourceMgr = Value;
     69 }
     70 
     71 void CompilerInstance::setPreprocessor(Preprocessor *Value) { PP = Value; }
     72 
     73 void CompilerInstance::setASTContext(ASTContext *Value) { Context = Value; }
     74 
     75 void CompilerInstance::setSema(Sema *S) {
     76   TheSema.reset(S);
     77 }
     78 
     79 void CompilerInstance::setASTConsumer(ASTConsumer *Value) {
     80   Consumer.reset(Value);
     81 }
     82 
     83 void CompilerInstance::setCodeCompletionConsumer(CodeCompleteConsumer *Value) {
     84   CompletionConsumer.reset(Value);
     85 }
     86 
     87 // Diagnostics
     88 static void SetUpBuildDumpLog(const DiagnosticOptions &DiagOpts,
     89                               unsigned argc, const char* const *argv,
     90                               Diagnostic &Diags) {
     91   std::string ErrorInfo;
     92   llvm::OwningPtr<llvm::raw_ostream> OS(
     93     new llvm::raw_fd_ostream(DiagOpts.DumpBuildInformation.c_str(), ErrorInfo));
     94   if (!ErrorInfo.empty()) {
     95     Diags.Report(diag::err_fe_unable_to_open_logfile)
     96                  << DiagOpts.DumpBuildInformation << ErrorInfo;
     97     return;
     98   }
     99 
    100   (*OS) << "clang -cc1 command line arguments: ";
    101   for (unsigned i = 0; i != argc; ++i)
    102     (*OS) << argv[i] << ' ';
    103   (*OS) << '\n';
    104 
    105   // Chain in a diagnostic client which will log the diagnostics.
    106   DiagnosticClient *Logger =
    107     new TextDiagnosticPrinter(*OS.take(), DiagOpts, /*OwnsOutputStream=*/true);
    108   Diags.setClient(new ChainedDiagnosticClient(Diags.takeClient(), Logger));
    109 }
    110 
    111 static void SetUpDiagnosticLog(const DiagnosticOptions &DiagOpts,
    112                                const CodeGenOptions *CodeGenOpts,
    113                                Diagnostic &Diags) {
    114   std::string ErrorInfo;
    115   bool OwnsStream = false;
    116   llvm::raw_ostream *OS = &llvm::errs();
    117   if (DiagOpts.DiagnosticLogFile != "-") {
    118     // Create the output stream.
    119     llvm::raw_fd_ostream *FileOS(
    120       new llvm::raw_fd_ostream(DiagOpts.DiagnosticLogFile.c_str(),
    121                                ErrorInfo, llvm::raw_fd_ostream::F_Append));
    122     if (!ErrorInfo.empty()) {
    123       Diags.Report(diag::warn_fe_cc_log_diagnostics_failure)
    124         << DiagOpts.DumpBuildInformation << ErrorInfo;
    125     } else {
    126       FileOS->SetUnbuffered();
    127       FileOS->SetUseAtomicWrites(true);
    128       OS = FileOS;
    129       OwnsStream = true;
    130     }
    131   }
    132 
    133   // Chain in the diagnostic client which will log the diagnostics.
    134   LogDiagnosticPrinter *Logger = new LogDiagnosticPrinter(*OS, DiagOpts,
    135                                                           OwnsStream);
    136   if (CodeGenOpts)
    137     Logger->setDwarfDebugFlags(CodeGenOpts->DwarfDebugFlags);
    138   Diags.setClient(new ChainedDiagnosticClient(Diags.takeClient(), Logger));
    139 }
    140 
    141 void CompilerInstance::createDiagnostics(int Argc, const char* const *Argv,
    142                                          DiagnosticClient *Client) {
    143   Diagnostics = createDiagnostics(getDiagnosticOpts(), Argc, Argv, Client,
    144                                   &getCodeGenOpts());
    145 }
    146 
    147 llvm::IntrusiveRefCntPtr<Diagnostic>
    148 CompilerInstance::createDiagnostics(const DiagnosticOptions &Opts,
    149                                     int Argc, const char* const *Argv,
    150                                     DiagnosticClient *Client,
    151                                     const CodeGenOptions *CodeGenOpts) {
    152   llvm::IntrusiveRefCntPtr<DiagnosticIDs> DiagID(new DiagnosticIDs());
    153   llvm::IntrusiveRefCntPtr<Diagnostic> Diags(new Diagnostic(DiagID));
    154 
    155   // Create the diagnostic client for reporting errors or for
    156   // implementing -verify.
    157   if (Client)
    158     Diags->setClient(Client);
    159   else
    160     Diags->setClient(new TextDiagnosticPrinter(llvm::errs(), Opts));
    161 
    162   // Chain in -verify checker, if requested.
    163   if (Opts.VerifyDiagnostics)
    164     Diags->setClient(new VerifyDiagnosticsClient(*Diags, Diags->takeClient()));
    165 
    166   // Chain in -diagnostic-log-file dumper, if requested.
    167   if (!Opts.DiagnosticLogFile.empty())
    168     SetUpDiagnosticLog(Opts, CodeGenOpts, *Diags);
    169 
    170   if (!Opts.DumpBuildInformation.empty())
    171     SetUpBuildDumpLog(Opts, Argc, Argv, *Diags);
    172 
    173   // Configure our handling of diagnostics.
    174   ProcessWarningOptions(*Diags, Opts);
    175 
    176   return Diags;
    177 }
    178 
    179 // File Manager
    180 
    181 void CompilerInstance::createFileManager() {
    182   FileMgr = new FileManager(getFileSystemOpts());
    183 }
    184 
    185 // Source Manager
    186 
    187 void CompilerInstance::createSourceManager(FileManager &FileMgr) {
    188   SourceMgr = new SourceManager(getDiagnostics(), FileMgr);
    189 }
    190 
    191 // Preprocessor
    192 
    193 void CompilerInstance::createPreprocessor() {
    194   PP = createPreprocessor(getDiagnostics(), getLangOpts(),
    195                           getPreprocessorOpts(), getHeaderSearchOpts(),
    196                           getDependencyOutputOpts(), getTarget(),
    197                           getFrontendOpts(), getSourceManager(),
    198                           getFileManager());
    199 }
    200 
    201 Preprocessor *
    202 CompilerInstance::createPreprocessor(Diagnostic &Diags,
    203                                      const LangOptions &LangInfo,
    204                                      const PreprocessorOptions &PPOpts,
    205                                      const HeaderSearchOptions &HSOpts,
    206                                      const DependencyOutputOptions &DepOpts,
    207                                      const TargetInfo &Target,
    208                                      const FrontendOptions &FEOpts,
    209                                      SourceManager &SourceMgr,
    210                                      FileManager &FileMgr) {
    211   // Create a PTH manager if we are using some form of a token cache.
    212   PTHManager *PTHMgr = 0;
    213   if (!PPOpts.TokenCache.empty())
    214     PTHMgr = PTHManager::Create(PPOpts.TokenCache, Diags);
    215 
    216   // Create the Preprocessor.
    217   HeaderSearch *HeaderInfo = new HeaderSearch(FileMgr);
    218   Preprocessor *PP = new Preprocessor(Diags, LangInfo, Target,
    219                                       SourceMgr, *HeaderInfo, PTHMgr,
    220                                       /*OwnsHeaderSearch=*/true);
    221 
    222   // Note that this is different then passing PTHMgr to Preprocessor's ctor.
    223   // That argument is used as the IdentifierInfoLookup argument to
    224   // IdentifierTable's ctor.
    225   if (PTHMgr) {
    226     PTHMgr->setPreprocessor(PP);
    227     PP->setPTHManager(PTHMgr);
    228   }
    229 
    230   if (PPOpts.DetailedRecord)
    231     PP->createPreprocessingRecord(
    232                        PPOpts.DetailedRecordIncludesNestedMacroExpansions);
    233 
    234   InitializePreprocessor(*PP, PPOpts, HSOpts, FEOpts);
    235 
    236   // Handle generating dependencies, if requested.
    237   if (!DepOpts.OutputFile.empty())
    238     AttachDependencyFileGen(*PP, DepOpts);
    239 
    240   // Handle generating header include information, if requested.
    241   if (DepOpts.ShowHeaderIncludes)
    242     AttachHeaderIncludeGen(*PP);
    243   if (!DepOpts.HeaderIncludeOutputFile.empty()) {
    244     llvm::StringRef OutputPath = DepOpts.HeaderIncludeOutputFile;
    245     if (OutputPath == "-")
    246       OutputPath = "";
    247     AttachHeaderIncludeGen(*PP, /*ShowAllHeaders=*/true, OutputPath,
    248                            /*ShowDepth=*/false);
    249   }
    250 
    251   return PP;
    252 }
    253 
    254 // ASTContext
    255 
    256 void CompilerInstance::createASTContext() {
    257   Preprocessor &PP = getPreprocessor();
    258   Context = new ASTContext(getLangOpts(), PP.getSourceManager(),
    259                            getTarget(), PP.getIdentifierTable(),
    260                            PP.getSelectorTable(), PP.getBuiltinInfo(),
    261                            /*size_reserve=*/ 0);
    262 }
    263 
    264 // ExternalASTSource
    265 
    266 void CompilerInstance::createPCHExternalASTSource(llvm::StringRef Path,
    267                                                   bool DisablePCHValidation,
    268                                                   bool DisableStatCache,
    269                                                  void *DeserializationListener){
    270   llvm::OwningPtr<ExternalASTSource> Source;
    271   bool Preamble = getPreprocessorOpts().PrecompiledPreambleBytes.first != 0;
    272   Source.reset(createPCHExternalASTSource(Path, getHeaderSearchOpts().Sysroot,
    273                                           DisablePCHValidation,
    274                                           DisableStatCache,
    275                                           getPreprocessor(), getASTContext(),
    276                                           DeserializationListener,
    277                                           Preamble));
    278   ModuleManager = static_cast<ASTReader*>(Source.get());
    279   getASTContext().setExternalSource(Source);
    280 }
    281 
    282 ExternalASTSource *
    283 CompilerInstance::createPCHExternalASTSource(llvm::StringRef Path,
    284                                              const std::string &Sysroot,
    285                                              bool DisablePCHValidation,
    286                                              bool DisableStatCache,
    287                                              Preprocessor &PP,
    288                                              ASTContext &Context,
    289                                              void *DeserializationListener,
    290                                              bool Preamble) {
    291   llvm::OwningPtr<ASTReader> Reader;
    292   Reader.reset(new ASTReader(PP, &Context,
    293                              Sysroot.empty() ? 0 : Sysroot.c_str(),
    294                              DisablePCHValidation, DisableStatCache));
    295 
    296   Reader->setDeserializationListener(
    297             static_cast<ASTDeserializationListener *>(DeserializationListener));
    298   switch (Reader->ReadAST(Path,
    299                           Preamble ? ASTReader::Preamble : ASTReader::PCH)) {
    300   case ASTReader::Success:
    301     // Set the predefines buffer as suggested by the PCH reader. Typically, the
    302     // predefines buffer will be empty.
    303     PP.setPredefines(Reader->getSuggestedPredefines());
    304     return Reader.take();
    305 
    306   case ASTReader::Failure:
    307     // Unrecoverable failure: don't even try to process the input file.
    308     break;
    309 
    310   case ASTReader::IgnorePCH:
    311     // No suitable PCH file could be found. Return an error.
    312     break;
    313   }
    314 
    315   return 0;
    316 }
    317 
    318 // Code Completion
    319 
    320 static bool EnableCodeCompletion(Preprocessor &PP,
    321                                  const std::string &Filename,
    322                                  unsigned Line,
    323                                  unsigned Column) {
    324   // Tell the source manager to chop off the given file at a specific
    325   // line and column.
    326   const FileEntry *Entry = PP.getFileManager().getFile(Filename);
    327   if (!Entry) {
    328     PP.getDiagnostics().Report(diag::err_fe_invalid_code_complete_file)
    329       << Filename;
    330     return true;
    331   }
    332 
    333   // Truncate the named file at the given line/column.
    334   PP.SetCodeCompletionPoint(Entry, Line, Column);
    335   return false;
    336 }
    337 
    338 void CompilerInstance::createCodeCompletionConsumer() {
    339   const ParsedSourceLocation &Loc = getFrontendOpts().CodeCompletionAt;
    340   if (!CompletionConsumer) {
    341     CompletionConsumer.reset(
    342       createCodeCompletionConsumer(getPreprocessor(),
    343                                    Loc.FileName, Loc.Line, Loc.Column,
    344                                    getFrontendOpts().ShowMacrosInCodeCompletion,
    345                              getFrontendOpts().ShowCodePatternsInCodeCompletion,
    346                            getFrontendOpts().ShowGlobalSymbolsInCodeCompletion,
    347                                    llvm::outs()));
    348     if (!CompletionConsumer)
    349       return;
    350   } else if (EnableCodeCompletion(getPreprocessor(), Loc.FileName,
    351                                   Loc.Line, Loc.Column)) {
    352     CompletionConsumer.reset();
    353     return;
    354   }
    355 
    356   if (CompletionConsumer->isOutputBinary() &&
    357       llvm::sys::Program::ChangeStdoutToBinary()) {
    358     getPreprocessor().getDiagnostics().Report(diag::err_fe_stdout_binary);
    359     CompletionConsumer.reset();
    360   }
    361 }
    362 
    363 void CompilerInstance::createFrontendTimer() {
    364   FrontendTimer.reset(new llvm::Timer("Clang front-end timer"));
    365 }
    366 
    367 CodeCompleteConsumer *
    368 CompilerInstance::createCodeCompletionConsumer(Preprocessor &PP,
    369                                                const std::string &Filename,
    370                                                unsigned Line,
    371                                                unsigned Column,
    372                                                bool ShowMacros,
    373                                                bool ShowCodePatterns,
    374                                                bool ShowGlobals,
    375                                                llvm::raw_ostream &OS) {
    376   if (EnableCodeCompletion(PP, Filename, Line, Column))
    377     return 0;
    378 
    379   // Set up the creation routine for code-completion.
    380   return new PrintingCodeCompleteConsumer(ShowMacros, ShowCodePatterns,
    381                                           ShowGlobals, OS);
    382 }
    383 
    384 void CompilerInstance::createSema(bool CompleteTranslationUnit,
    385                                   CodeCompleteConsumer *CompletionConsumer) {
    386   TheSema.reset(new Sema(getPreprocessor(), getASTContext(), getASTConsumer(),
    387                          CompleteTranslationUnit, CompletionConsumer));
    388 }
    389 
    390 // Output Files
    391 
    392 void CompilerInstance::addOutputFile(const OutputFile &OutFile) {
    393   assert(OutFile.OS && "Attempt to add empty stream to output list!");
    394   OutputFiles.push_back(OutFile);
    395 }
    396 
    397 void CompilerInstance::clearOutputFiles(bool EraseFiles) {
    398   for (std::list<OutputFile>::iterator
    399          it = OutputFiles.begin(), ie = OutputFiles.end(); it != ie; ++it) {
    400     delete it->OS;
    401     if (!it->TempFilename.empty()) {
    402       if (EraseFiles) {
    403         bool existed;
    404         llvm::sys::fs::remove(it->TempFilename, existed);
    405       } else {
    406         llvm::SmallString<128> NewOutFile(it->Filename);
    407 
    408         // If '-working-directory' was passed, the output filename should be
    409         // relative to that.
    410         FileMgr->FixupRelativePath(NewOutFile);
    411         if (llvm::error_code ec = llvm::sys::fs::rename(it->TempFilename,
    412                                                         NewOutFile.str())) {
    413           getDiagnostics().Report(diag::err_fe_unable_to_rename_temp)
    414             << it->TempFilename << it->Filename << ec.message();
    415 
    416           bool existed;
    417           llvm::sys::fs::remove(it->TempFilename, existed);
    418         }
    419       }
    420     } else if (!it->Filename.empty() && EraseFiles)
    421       llvm::sys::Path(it->Filename).eraseFromDisk();
    422 
    423   }
    424   OutputFiles.clear();
    425 }
    426 
    427 llvm::raw_fd_ostream *
    428 CompilerInstance::createDefaultOutputFile(bool Binary,
    429                                           llvm::StringRef InFile,
    430                                           llvm::StringRef Extension) {
    431   return createOutputFile(getFrontendOpts().OutputFile, Binary,
    432                           /*RemoveFileOnSignal=*/true, InFile, Extension);
    433 }
    434 
    435 llvm::raw_fd_ostream *
    436 CompilerInstance::createOutputFile(llvm::StringRef OutputPath,
    437                                    bool Binary, bool RemoveFileOnSignal,
    438                                    llvm::StringRef InFile,
    439                                    llvm::StringRef Extension) {
    440   std::string Error, OutputPathName, TempPathName;
    441   llvm::raw_fd_ostream *OS = createOutputFile(OutputPath, Error, Binary,
    442                                               RemoveFileOnSignal,
    443                                               InFile, Extension,
    444                                               &OutputPathName,
    445                                               &TempPathName);
    446   if (!OS) {
    447     getDiagnostics().Report(diag::err_fe_unable_to_open_output)
    448       << OutputPath << Error;
    449     return 0;
    450   }
    451 
    452   // Add the output file -- but don't try to remove "-", since this means we are
    453   // using stdin.
    454   addOutputFile(OutputFile((OutputPathName != "-") ? OutputPathName : "",
    455                 TempPathName, OS));
    456 
    457   return OS;
    458 }
    459 
    460 llvm::raw_fd_ostream *
    461 CompilerInstance::createOutputFile(llvm::StringRef OutputPath,
    462                                    std::string &Error,
    463                                    bool Binary,
    464                                    bool RemoveFileOnSignal,
    465                                    llvm::StringRef InFile,
    466                                    llvm::StringRef Extension,
    467                                    std::string *ResultPathName,
    468                                    std::string *TempPathName) {
    469   std::string OutFile, TempFile;
    470   if (!OutputPath.empty()) {
    471     OutFile = OutputPath;
    472   } else if (InFile == "-") {
    473     OutFile = "-";
    474   } else if (!Extension.empty()) {
    475     llvm::sys::Path Path(InFile);
    476     Path.eraseSuffix();
    477     Path.appendSuffix(Extension);
    478     OutFile = Path.str();
    479   } else {
    480     OutFile = "-";
    481   }
    482 
    483   if (OutFile != "-") {
    484     llvm::sys::Path OutPath(OutFile);
    485     // Only create the temporary if we can actually write to OutPath, otherwise
    486     // we want to fail early.
    487     bool Exists;
    488     if ((llvm::sys::fs::exists(OutPath.str(), Exists) || !Exists) ||
    489         (OutPath.isRegularFile() && OutPath.canWrite())) {
    490       // Create a temporary file.
    491       llvm::sys::Path TempPath(OutFile);
    492       if (!TempPath.createTemporaryFileOnDisk())
    493         TempFile = TempPath.str();
    494     }
    495   }
    496 
    497   std::string OSFile = OutFile;
    498   if (!TempFile.empty())
    499     OSFile = TempFile;
    500 
    501   llvm::OwningPtr<llvm::raw_fd_ostream> OS(
    502     new llvm::raw_fd_ostream(OSFile.c_str(), Error,
    503                              (Binary ? llvm::raw_fd_ostream::F_Binary : 0)));
    504   if (!Error.empty())
    505     return 0;
    506 
    507   // Make sure the out stream file gets removed if we crash.
    508   if (RemoveFileOnSignal)
    509     llvm::sys::RemoveFileOnSignal(llvm::sys::Path(OSFile));
    510 
    511   if (ResultPathName)
    512     *ResultPathName = OutFile;
    513   if (TempPathName)
    514     *TempPathName = TempFile;
    515 
    516   return OS.take();
    517 }
    518 
    519 // Initialization Utilities
    520 
    521 bool CompilerInstance::InitializeSourceManager(llvm::StringRef InputFile) {
    522   return InitializeSourceManager(InputFile, getDiagnostics(), getFileManager(),
    523                                  getSourceManager(), getFrontendOpts());
    524 }
    525 
    526 bool CompilerInstance::InitializeSourceManager(llvm::StringRef InputFile,
    527                                                Diagnostic &Diags,
    528                                                FileManager &FileMgr,
    529                                                SourceManager &SourceMgr,
    530                                                const FrontendOptions &Opts) {
    531   // Figure out where to get and map in the main file, unless it's already
    532   // been created (e.g., by a precompiled preamble).
    533   if (!SourceMgr.getMainFileID().isInvalid()) {
    534     // Do nothing: the main file has already been set.
    535   } else if (InputFile != "-") {
    536     const FileEntry *File = FileMgr.getFile(InputFile);
    537     if (!File) {
    538       Diags.Report(diag::err_fe_error_reading) << InputFile;
    539       return false;
    540     }
    541     SourceMgr.createMainFileID(File);
    542   } else {
    543     llvm::OwningPtr<llvm::MemoryBuffer> SB;
    544     if (llvm::MemoryBuffer::getSTDIN(SB)) {
    545       // FIXME: Give ec.message() in this diag.
    546       Diags.Report(diag::err_fe_error_reading_stdin);
    547       return false;
    548     }
    549     const FileEntry *File = FileMgr.getVirtualFile(SB->getBufferIdentifier(),
    550                                                    SB->getBufferSize(), 0);
    551     SourceMgr.createMainFileID(File);
    552     SourceMgr.overrideFileContents(File, SB.take());
    553   }
    554 
    555   assert(!SourceMgr.getMainFileID().isInvalid() &&
    556          "Couldn't establish MainFileID!");
    557   return true;
    558 }
    559 
    560 // High-Level Operations
    561 
    562 bool CompilerInstance::ExecuteAction(FrontendAction &Act) {
    563   assert(hasDiagnostics() && "Diagnostics engine is not initialized!");
    564   assert(!getFrontendOpts().ShowHelp && "Client must handle '-help'!");
    565   assert(!getFrontendOpts().ShowVersion && "Client must handle '-version'!");
    566 
    567   // FIXME: Take this as an argument, once all the APIs we used have moved to
    568   // taking it as an input instead of hard-coding llvm::errs.
    569   llvm::raw_ostream &OS = llvm::errs();
    570 
    571   // Create the target instance.
    572   setTarget(TargetInfo::CreateTargetInfo(getDiagnostics(), getTargetOpts()));
    573   if (!hasTarget())
    574     return false;
    575 
    576   // Inform the target of the language options.
    577   //
    578   // FIXME: We shouldn't need to do this, the target should be immutable once
    579   // created. This complexity should be lifted elsewhere.
    580   getTarget().setForcedLangOptions(getLangOpts());
    581 
    582   // Validate/process some options.
    583   if (getHeaderSearchOpts().Verbose)
    584     OS << "clang -cc1 version " CLANG_VERSION_STRING
    585        << " based upon " << PACKAGE_STRING
    586        << " hosted on " << llvm::sys::getHostTriple() << "\n";
    587 
    588   if (getFrontendOpts().ShowTimers)
    589     createFrontendTimer();
    590 
    591   if (getFrontendOpts().ShowStats)
    592     llvm::EnableStatistics();
    593 
    594   for (unsigned i = 0, e = getFrontendOpts().Inputs.size(); i != e; ++i) {
    595     const std::string &InFile = getFrontendOpts().Inputs[i].second;
    596 
    597     // Reset the ID tables if we are reusing the SourceManager.
    598     if (hasSourceManager())
    599       getSourceManager().clearIDTables();
    600 
    601     if (Act.BeginSourceFile(*this, InFile, getFrontendOpts().Inputs[i].first)) {
    602       Act.Execute();
    603       Act.EndSourceFile();
    604     }
    605   }
    606 
    607   if (getDiagnosticOpts().ShowCarets) {
    608     // We can have multiple diagnostics sharing one diagnostic client.
    609     // Get the total number of warnings/errors from the client.
    610     unsigned NumWarnings = getDiagnostics().getClient()->getNumWarnings();
    611     unsigned NumErrors = getDiagnostics().getClient()->getNumErrors();
    612 
    613     if (NumWarnings)
    614       OS << NumWarnings << " warning" << (NumWarnings == 1 ? "" : "s");
    615     if (NumWarnings && NumErrors)
    616       OS << " and ";
    617     if (NumErrors)
    618       OS << NumErrors << " error" << (NumErrors == 1 ? "" : "s");
    619     if (NumWarnings || NumErrors)
    620       OS << " generated.\n";
    621   }
    622 
    623   if (getFrontendOpts().ShowStats && hasFileManager()) {
    624     getFileManager().PrintStats();
    625     OS << "\n";
    626   }
    627 
    628   return !getDiagnostics().getClient()->getNumErrors();
    629 }
    630 
    631 
    632