zcov: / lib/Frontend/CompilerInstance.cpp


Files: 1 Branches Taken: 70.2% 87 / 124
Generated: 2010-02-10 01:31 Branches Executed: 88.7% 110 / 124
Line Coverage: 81.3% 187 / 230


Programs: 2 Runs 3018


       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/AST/ASTConsumer.h"
      12                 : #include "clang/AST/ASTContext.h"
      13                 : #include "clang/Basic/Diagnostic.h"
      14                 : #include "clang/Basic/FileManager.h"
      15                 : #include "clang/Basic/SourceManager.h"
      16                 : #include "clang/Basic/TargetInfo.h"
      17                 : #include "clang/Basic/Version.h"
      18                 : #include "clang/Lex/HeaderSearch.h"
      19                 : #include "clang/Lex/Preprocessor.h"
      20                 : #include "clang/Lex/PTHManager.h"
      21                 : #include "clang/Frontend/ChainedDiagnosticClient.h"
      22                 : #include "clang/Frontend/FrontendAction.h"
      23                 : #include "clang/Frontend/PCHReader.h"
      24                 : #include "clang/Frontend/FrontendDiagnostic.h"
      25                 : #include "clang/Frontend/TextDiagnosticPrinter.h"
      26                 : #include "clang/Frontend/VerifyDiagnosticsClient.h"
      27                 : #include "clang/Frontend/Utils.h"
      28                 : #include "clang/Sema/CodeCompleteConsumer.h"
      29                 : #include "llvm/LLVMContext.h"
      30                 : #include "llvm/Support/MemoryBuffer.h"
      31                 : #include "llvm/Support/raw_ostream.h"
      32                 : #include "llvm/Support/Timer.h"
      33                 : #include "llvm/System/Host.h"
      34                 : #include "llvm/System/Path.h"
      35                 : #include "llvm/System/Program.h"
      36                 : using namespace clang;
      37                 : 
      38                 : CompilerInstance::CompilerInstance(llvm::LLVMContext *_LLVMContext,
      39             2523:                                    bool _OwnsLLVMContext)
      40                 :   : LLVMContext(_LLVMContext),
      41                 :     OwnsLLVMContext(_OwnsLLVMContext),
      42             2523:     Invocation(new CompilerInvocation) {
      43             2523: }
      44                 : 
      45             2523: CompilerInstance::~CompilerInstance() {
                        9: branch 0 taken
                     2514: branch 1 taken
                     2514: branch 2 taken
                     2514: branch 3 taken
      46             2523:   if (OwnsLLVMContext)
                        0: branch 0 not taken
                        9: branch 1 taken
                        0: branch 4 not taken
                        0: branch 5 not taken
      47                9:     delete LLVMContext;
      48             2523: }
      49                 : 
      50                9: void CompilerInstance::setInvocation(CompilerInvocation *Value) {
      51                9:   Invocation.reset(Value);
      52                9: }
      53                 : 
      54                9: void CompilerInstance::setDiagnostics(Diagnostic *Value) {
      55                9:   Diagnostics.reset(Value);
      56                9: }
      57                 : 
      58                9: void CompilerInstance::setDiagnosticClient(DiagnosticClient *Value) {
      59                9:   DiagClient.reset(Value);
      60                9: }
      61                 : 
      62             2522: void CompilerInstance::setTarget(TargetInfo *Value) {
      63             2522:   Target.reset(Value);
      64             2522: }
      65                 : 
      66               11: void CompilerInstance::setFileManager(FileManager *Value) {
      67               11:   FileMgr.reset(Value);
      68               11: }
      69                 : 
      70               11: void CompilerInstance::setSourceManager(SourceManager *Value) {
      71               11:   SourceMgr.reset(Value);
      72               11: }
      73                 : 
      74                2: void CompilerInstance::setPreprocessor(Preprocessor *Value) {
      75                2:   PP.reset(Value);
      76                2: }
      77                 : 
      78             2369: void CompilerInstance::setASTContext(ASTContext *Value) {
      79             2369:   Context.reset(Value);
      80             2369: }
      81                 : 
      82             4606: void CompilerInstance::setASTConsumer(ASTConsumer *Value) {
      83             4606:   Consumer.reset(Value);
      84             4606: }
      85                 : 
      86                0: void CompilerInstance::setCodeCompletionConsumer(CodeCompleteConsumer *Value) {
      87                0:   CompletionConsumer.reset(Value);
      88                0: }
      89                 : 
      90                 : // Diagnostics
      91                 : namespace {
                       52: branch 1 taken
                        0: branch 2 not taken
                        0: branch 5 not taken
                        0: branch 6 not taken
      92               52:   class BinaryDiagnosticSerializer : public DiagnosticClient {
      93                 :     llvm::raw_ostream &OS;
      94                 :     SourceManager *SourceMgr;
      95                 :   public:
      96               52:     explicit BinaryDiagnosticSerializer(llvm::raw_ostream &OS)
      97               52:       : OS(OS), SourceMgr(0) { }
      98                 :     
      99                 :     virtual void HandleDiagnostic(Diagnostic::Level DiagLevel,
     100                 :                                   const DiagnosticInfo &Info);
     101                 :   };
     102                 : }
     103                 : 
     104                 : void BinaryDiagnosticSerializer::HandleDiagnostic(Diagnostic::Level DiagLevel,
     105               54:                                                   const DiagnosticInfo &Info) {
     106               54:   Info.Serialize(DiagLevel, OS);
     107               54: }
     108                 : 
     109                 : static void SetUpBuildDumpLog(const DiagnosticOptions &DiagOpts,
     110                 :                               unsigned argc, char **argv,
     111                0:                               llvm::OwningPtr<DiagnosticClient> &DiagClient) {
     112                0:   std::string ErrorInfo;
     113                 :   llvm::raw_ostream *OS =
     114                0:     new llvm::raw_fd_ostream(DiagOpts.DumpBuildInformation.c_str(), ErrorInfo);
                        0: branch 1 not taken
                        0: branch 2 not taken
     115                0:   if (!ErrorInfo.empty()) {
     116                 :     // FIXME: Do not fail like this.
     117                 :     llvm::errs() << "error opening -dump-build-information file '"
     118                0:                  << DiagOpts.DumpBuildInformation << "', option ignored!\n";
                        0: branch 0 not taken
                        0: branch 1 not taken
     119                0:     delete OS;
     120                0:     return;
     121                 :   }
     122                 : 
     123                0:   (*OS) << "clang -cc1 command line arguments: ";
                        0: branch 0 not taken
                        0: branch 1 not taken
     124                0:   for (unsigned i = 0; i != argc; ++i)
     125                0:     (*OS) << argv[i] << ' ';
     126                0:   (*OS) << '\n';
     127                 : 
     128                 :   // Chain in a diagnostic client which will log the diagnostics.
     129                 :   DiagnosticClient *Logger =
     130                0:     new TextDiagnosticPrinter(*OS, DiagOpts, /*OwnsOutputStream=*/true);
                        0: branch 5 not taken
                        0: branch 6 not taken
     131                0:   DiagClient.reset(new ChainedDiagnosticClient(DiagClient.take(), Logger));
     132                 : }
     133                 : 
     134             2514: void CompilerInstance::createDiagnostics(int Argc, char **Argv) {
     135             2514:   Diagnostics.reset(createDiagnostics(getDiagnosticOpts(), Argc, Argv));
     136                 : 
                     2514: branch 1 taken
                        0: branch 2 not taken
     137             2514:   if (Diagnostics)
     138             2514:     DiagClient.reset(Diagnostics->getClient());
     139             2514: }
     140                 : 
     141                 : Diagnostic *CompilerInstance::createDiagnostics(const DiagnosticOptions &Opts,
     142             2583:                                                 int Argc, char **Argv) {
     143             2583:   llvm::OwningPtr<Diagnostic> Diags(new Diagnostic());
     144                 : 
     145                 :   // Create the diagnostic client for reporting errors or for
     146                 :   // implementing -verify.
     147             2583:   llvm::OwningPtr<DiagnosticClient> DiagClient;
                       52: branch 0 taken
                     2531: branch 1 taken
     148             2583:   if (Opts.BinaryOutput) {
                        0: branch 1 not taken
                       52: branch 2 taken
     149               52:     if (llvm::sys::Program::ChangeStderrToBinary()) {
     150                 :       // We weren't able to set standard error to binary, which is a
     151                 :       // bit of a problem. So, just create a text diagnostic printer
     152                 :       // to complain about this problem, and pretend that the user
     153                 :       // didn't try to use binary output.
     154                0:       DiagClient.reset(new TextDiagnosticPrinter(llvm::errs(), Opts));
     155                0:       Diags->setClient(DiagClient.take());
     156                0:       Diags->Report(diag::err_fe_stderr_binary);
     157                0:       return Diags.take();
     158                 :     } else {
     159               52:       DiagClient.reset(new BinaryDiagnosticSerializer(llvm::errs()));
     160                 :     }
     161                 :   } else {
     162             2531:     DiagClient.reset(new TextDiagnosticPrinter(llvm::errs(), Opts));
     163                 :   }
     164                 : 
     165                 :   // Chain in -verify checker, if requested.
                     1312: branch 0 taken
                     1271: branch 1 taken
     166             2583:   if (Opts.VerifyDiagnostics)
     167             1312:     DiagClient.reset(new VerifyDiagnosticsClient(*Diags, DiagClient.take()));
     168                 : 
                        0: branch 1 not taken
                     2583: branch 2 taken
     169             2583:   if (!Opts.DumpBuildInformation.empty())
     170                0:     SetUpBuildDumpLog(Opts, Argc, Argv, DiagClient);
     171                 : 
     172                 :   // Configure our handling of diagnostics.
     173             2583:   Diags->setClient(DiagClient.take());
                        0: branch 2 not taken
                     2583: branch 3 taken
     174             2583:   if (ProcessWarningOptions(*Diags, Opts))
     175                0:     return 0;
     176                 : 
     177             2583:   return Diags.take();
     178                 : }
     179                 : 
     180                 : // File Manager
     181                 : 
     182             2511: void CompilerInstance::createFileManager() {
     183             2511:   FileMgr.reset(new FileManager());
     184             2511: }
     185                 : 
     186                 : // Source Manager
     187                 : 
     188             2511: void CompilerInstance::createSourceManager() {
     189             2511:   SourceMgr.reset(new SourceManager());
     190             2511: }
     191                 : 
     192                 : // Preprocessor
     193                 : 
     194             2520: void CompilerInstance::createPreprocessor() {
     195                 :   PP.reset(createPreprocessor(getDiagnostics(), getLangOpts(),
     196                 :                               getPreprocessorOpts(), getHeaderSearchOpts(),
     197                 :                               getDependencyOutputOpts(), getTarget(),
     198                 :                               getFrontendOpts(), getSourceManager(),
     199             2520:                               getFileManager()));
     200             2520: }
     201                 : 
     202                 : Preprocessor *
     203                 : CompilerInstance::createPreprocessor(Diagnostic &Diags,
     204                 :                                      const LangOptions &LangInfo,
     205                 :                                      const PreprocessorOptions &PPOpts,
     206                 :                                      const HeaderSearchOptions &HSOpts,
     207                 :                                      const DependencyOutputOptions &DepOpts,
     208                 :                                      const TargetInfo &Target,
     209                 :                                      const FrontendOptions &FEOpts,
     210                 :                                      SourceManager &SourceMgr,
     211             2520:                                      FileManager &FileMgr) {
     212                 :   // Create a PTH manager if we are using some form of a token cache.
     213             2520:   PTHManager *PTHMgr = 0;
                        1: branch 1 taken
                     2519: branch 2 taken
     214             2520:   if (!PPOpts.TokenCache.empty())
     215                1:     PTHMgr = PTHManager::Create(PPOpts.TokenCache, Diags);
     216                 : 
     217                 :   // Create the Preprocessor.
     218             2520:   HeaderSearch *HeaderInfo = new HeaderSearch(FileMgr);
     219                 :   Preprocessor *PP = new Preprocessor(Diags, LangInfo, Target,
     220                 :                                       SourceMgr, *HeaderInfo, PTHMgr,
     221             2520:                                       /*OwnsHeaderSearch=*/true);
     222                 : 
     223                 :   // Note that this is different then passing PTHMgr to Preprocessor's ctor.
     224                 :   // That argument is used as the IdentifierInfoLookup argument to
     225                 :   // IdentifierTable's ctor.
                        1: branch 0 taken
                     2519: branch 1 taken
     226             2520:   if (PTHMgr) {
     227                1:     PTHMgr->setPreprocessor(PP);
     228                1:     PP->setPTHManager(PTHMgr);
     229                 :   }
     230                 : 
     231             2520:   InitializePreprocessor(*PP, PPOpts, HSOpts, FEOpts);
     232                 : 
     233                 :   // Handle generating dependencies, if requested.
                        3: branch 1 taken
                     2517: branch 2 taken
     234             2520:   if (!DepOpts.OutputFile.empty())
     235                3:     AttachDependencyFileGen(*PP, DepOpts);
     236                 : 
     237             2520:   return PP;
     238                 : }
     239                 : 
     240                 : // ASTContext
     241                 : 
     242             2237: void CompilerInstance::createASTContext() {
     243             2237:   Preprocessor &PP = getPreprocessor();
     244                 :   Context.reset(new ASTContext(getLangOpts(), PP.getSourceManager(),
     245                 :                                getTarget(), PP.getIdentifierTable(),
     246                 :                                PP.getSelectorTable(), PP.getBuiltinInfo(),
     247                 :                                /*FreeMemory=*/ !getFrontendOpts().DisableFree,
     248             2237:                                /*size_reserve=*/ 0));
     249             2237: }
     250                 : 
     251                 : // ExternalASTSource
     252                 : 
     253               35: void CompilerInstance::createPCHExternalASTSource(llvm::StringRef Path) {
     254               35:   llvm::OwningPtr<ExternalASTSource> Source;
     255                 :   Source.reset(createPCHExternalASTSource(Path, getHeaderSearchOpts().Sysroot,
     256               35:                                           getPreprocessor(), getASTContext()));
     257               35:   getASTContext().setExternalSource(Source);
     258               35: }
     259                 : 
     260                 : ExternalASTSource *
     261                 : CompilerInstance::createPCHExternalASTSource(llvm::StringRef Path,
     262                 :                                              const std::string &Sysroot,
     263                 :                                              Preprocessor &PP,
     264               35:                                              ASTContext &Context) {
     265               35:   llvm::OwningPtr<PCHReader> Reader;
     266                 :   Reader.reset(new PCHReader(PP, &Context,
                        0: branch 1 not taken
                       35: branch 2 taken
     267               35:                              Sysroot.empty() ? 0 : Sysroot.c_str()));
     268                 : 
                       33: branch 4 taken
                        2: branch 5 taken
     269               35:   switch (Reader->ReadPCH(Path)) {
     270                 :   case PCHReader::Success:
     271                 :     // Set the predefines buffer as suggested by the PCH reader. Typically, the
     272                 :     // predefines buffer will be empty.
     273               33:     PP.setPredefines(Reader->getSuggestedPredefines());
                       33: branch 1 taken
                        0: branch 2 not taken
     274               33:     return Reader.take();
     275                 : 
     276                 :   case PCHReader::Failure:
     277                 :     // Unrecoverable failure: don't even try to process the input file.
     278                 :     break;
     279                 : 
     280                 :   case PCHReader::IgnorePCH:
     281                 :     // No suitable PCH file could be found. Return an error.
     282                 :     break;
     283                 :   }
     284                 : 
     285                2:   return 0;
     286                 : }
     287                 : 
     288                 : // Code Completion
     289                 : 
     290               87: void CompilerInstance::createCodeCompletionConsumer() {
     291               87:   const ParsedSourceLocation &Loc = getFrontendOpts().CodeCompletionAt;
     292                 :   CompletionConsumer.reset(
     293                 :     createCodeCompletionConsumer(getPreprocessor(),
     294                 :                                  Loc.FileName, Loc.Line, Loc.Column,
     295                 :                                  getFrontendOpts().DebugCodeCompletionPrinter,
     296                 :                                  getFrontendOpts().ShowMacrosInCodeCompletion,
     297               87:                                  llvm::outs()));
     298                 : 
                       51: branch 2 taken
                       36: branch 3 taken
                        0: branch 5 not taken
                       51: branch 6 taken
                        0: branch 7 not taken
                       87: branch 8 taken
     299               87:   if (CompletionConsumer->isOutputBinary() &&
     300                 :       llvm::sys::Program::ChangeStdoutToBinary()) {
     301                0:     getPreprocessor().getDiagnostics().Report(diag::err_fe_stdout_binary);
     302                0:     CompletionConsumer.reset();
     303                 :   }
     304               87: }
     305                 : 
     306                0: void CompilerInstance::createFrontendTimer() {
     307                0:   FrontendTimer.reset(new llvm::Timer("Clang front-end timer"));
     308                0: }
     309                 : 
     310                 : CodeCompleteConsumer *
     311                 : CompilerInstance::createCodeCompletionConsumer(Preprocessor &PP,
     312                 :                                                const std::string &Filename,
     313                 :                                                unsigned Line,
     314                 :                                                unsigned Column,
     315                 :                                                bool UseDebugPrinter,
     316                 :                                                bool ShowMacros,
     317               87:                                                llvm::raw_ostream &OS) {
     318                 :   // Tell the source manager to chop off the given file at a specific
     319                 :   // line and column.
     320               87:   const FileEntry *Entry = PP.getFileManager().getFile(Filename);
                        0: branch 0 not taken
                       87: branch 1 taken
     321               87:   if (!Entry) {
     322                 :     PP.getDiagnostics().Report(diag::err_fe_invalid_code_complete_file)
     323                0:       << Filename;
     324                0:     return 0;
     325                 :   }
     326                 : 
     327                 :   // Truncate the named file at the given line/column.
     328               87:   PP.SetCodeCompletionPoint(Entry, Line, Column);
     329                 : 
     330                 :   // Set up the creation routine for code-completion.
                       36: branch 0 taken
                       51: branch 1 taken
     331               87:   if (UseDebugPrinter)
     332               36:     return new PrintingCodeCompleteConsumer(ShowMacros, OS);
     333                 :   else
     334               51:     return new CIndexCodeCompleteConsumer(ShowMacros, OS);
     335                 : }
     336                 : 
     337                 : // Output Files
     338                 : 
     339                 : void CompilerInstance::addOutputFile(llvm::StringRef Path,
     340              955:                                      llvm::raw_ostream *OS) {
                        0: branch 0 not taken
                      955: branch 1 taken
     341              955:   assert(OS && "Attempt to add empty stream to output list!");
     342              955:   OutputFiles.push_back(std::make_pair(Path, OS));
     343              955: }
     344                 : 
     345             2519: void CompilerInstance::ClearOutputFiles(bool EraseFiles) {
                      955: branch 2 taken
                     2519: branch 3 taken
     346             3474:   for (std::list< std::pair<std::string, llvm::raw_ostream*> >::iterator
     347             2519:          it = OutputFiles.begin(), ie = OutputFiles.end(); it != ie; ++it) {
                      955: branch 1 taken
                        0: branch 2 not taken
     348              955:     delete it->second;
                       17: branch 0 taken
                      938: branch 1 taken
                        1: branch 4 taken
                       16: branch 5 taken
                        1: branch 6 taken
                      954: branch 7 taken
     349              955:     if (EraseFiles && !it->first.empty())
     350                1:       llvm::sys::Path(it->first).eraseFromDisk();
     351                 :   }
     352             2519:   OutputFiles.clear();
     353             2519: }
     354                 : 
     355                 : llvm::raw_fd_ostream *
     356                 : CompilerInstance::createDefaultOutputFile(bool Binary,
     357                 :                                           llvm::StringRef InFile,
     358              956:                                           llvm::StringRef Extension) {
     359                 :   return createOutputFile(getFrontendOpts().OutputFile, Binary,
     360              956:                           InFile, Extension);
     361                 : }
     362                 : 
     363                 : llvm::raw_fd_ostream *
     364                 : CompilerInstance::createOutputFile(llvm::StringRef OutputPath,
     365                 :                                    bool Binary,
     366                 :                                    llvm::StringRef InFile,
     367              956:                                    llvm::StringRef Extension) {
     368              956:   std::string Error, OutputPathName;
     369                 :   llvm::raw_fd_ostream *OS = createOutputFile(OutputPath, Error, Binary,
     370                 :                                               InFile, Extension,
     371              956:                                               &OutputPathName);
                        1: branch 0 taken
                      955: branch 1 taken
     372              956:   if (!OS) {
     373                 :     getDiagnostics().Report(diag::err_fe_unable_to_open_output)
     374                1:       << OutputPath << Error;
     375                1:     return 0;
     376                 :   }
     377                 : 
     378                 :   // Add the output file -- but don't try to remove "-", since this means we are
     379                 :   // using stdin.
                      381: branch 1 taken
                      574: branch 2 taken
                      574: branch 9 taken
                      381: branch 10 taken
     380              955:   addOutputFile((OutputPathName != "-") ? OutputPathName : "", OS);
     381                 : 
     382              955:   return OS;
     383                 : }
     384                 : 
     385                 : llvm::raw_fd_ostream *
     386                 : CompilerInstance::createOutputFile(llvm::StringRef OutputPath,
     387                 :                                    std::string &Error,
     388                 :                                    bool Binary,
     389                 :                                    llvm::StringRef InFile,
     390                 :                                    llvm::StringRef Extension,
     391              956:                                    std::string *ResultPathName) {
     392              956:   std::string OutFile;
                      708: branch 1 taken
                      248: branch 2 taken
     393              956:   if (!OutputPath.empty()) {
     394              708:     OutFile = OutputPath;
                       64: branch 2 taken
                      184: branch 3 taken
     395              248:   } else if (InFile == "-") {
     396               64:     OutFile = "-";
                        0: branch 1 not taken
                      184: branch 2 taken
     397              184:   } else if (!Extension.empty()) {
     398                0:     llvm::sys::Path Path(InFile);
     399                0:     Path.eraseSuffix();
     400                0:     Path.appendSuffix(Extension);
     401                0:     OutFile = Path.str();
     402                 :   } else {
     403              184:     OutFile = "-";
     404                 :   }
     405                 : 
     406                 :   llvm::OwningPtr<llvm::raw_fd_ostream> OS(
     407                 :     new llvm::raw_fd_ostream(OutFile.c_str(), Error,
                      309: branch 2 taken
                      647: branch 3 taken
     408              956:                              (Binary ? llvm::raw_fd_ostream::F_Binary : 0)));
                        1: branch 1 taken
                      955: branch 2 taken
     409              956:   if (!Error.empty())
     410                1:     return 0;
     411                 : 
                      955: branch 0 taken
                        0: branch 1 not taken
     412              955:   if (ResultPathName)
     413              955:     *ResultPathName = OutFile;
     414                 : 
     415              955:   return OS.take();
     416                 : }
     417                 : 
     418                 : // Initialization Utilities
     419                 : 
     420             2517: bool CompilerInstance::InitializeSourceManager(llvm::StringRef InputFile) {
     421                 :   return InitializeSourceManager(InputFile, getDiagnostics(), getFileManager(),
     422             2517:                                  getSourceManager(), getFrontendOpts());
     423                 : }
     424                 : 
     425                 : bool CompilerInstance::InitializeSourceManager(llvm::StringRef InputFile,
     426                 :                                                Diagnostic &Diags,
     427                 :                                                FileManager &FileMgr,
     428                 :                                                SourceManager &SourceMgr,
     429             2517:                                                const FrontendOptions &Opts) {
     430                 :   // Figure out where to get and map in the main file.
                        0: branch 0 not taken
                     2517: branch 1 taken
     431             2517:   if (Opts.EmptyInputOnly) {
     432                0:     const char *EmptyStr = "";
     433                 :     llvm::MemoryBuffer *SB =
     434                0:       llvm::MemoryBuffer::getMemBuffer(EmptyStr, EmptyStr, "<empty input>");
     435                0:     SourceMgr.createMainFileIDForMemBuffer(SB);
                     2422: branch 2 taken
                       95: branch 3 taken
     436             2517:   } else if (InputFile != "-") {
     437             2422:     const FileEntry *File = FileMgr.getFile(InputFile);
                     2422: branch 0 taken
                        0: branch 1 not taken
     438             2422:     if (File) SourceMgr.createMainFileID(File, SourceLocation());
                        0: branch 2 not taken
                     2422: branch 3 taken
     439             2422:     if (SourceMgr.getMainFileID().isInvalid()) {
     440                0:       Diags.Report(diag::err_fe_error_reading) << InputFile;
     441                0:       return false;
     442                 :     }
     443                 :   } else {
     444               95:     llvm::MemoryBuffer *SB = llvm::MemoryBuffer::getSTDIN();
     445               95:     SourceMgr.createMainFileIDForMemBuffer(SB);
                        0: branch 2 not taken
                       95: branch 3 taken
     446               95:     if (SourceMgr.getMainFileID().isInvalid()) {
     447                0:       Diags.Report(diag::err_fe_error_reading_stdin);
     448                0:       return false;
     449                 :     }
     450                 :   }
     451                 : 
     452             2517:   return true;
     453                 : }
     454                 : 
     455                 : // High-Level Operations
     456                 : 
     457             2513: bool CompilerInstance::ExecuteAction(FrontendAction &Act) {
                     2513: branch 1 taken
                        0: branch 2 not taken
     458             2513:   assert(hasDiagnostics() && "Diagnostics engine is not initialized!");
                     2513: branch 1 taken
                        0: branch 2 not taken
     459             2513:   assert(!getFrontendOpts().ShowHelp && "Client must handle '-help'!");
                     2513: branch 1 taken
                        0: branch 2 not taken
     460             2513:   assert(!getFrontendOpts().ShowVersion && "Client must handle '-version'!");
     461                 : 
     462                 :   // FIXME: Take this as an argument, once all the APIs we used have moved to
     463                 :   // taking it as an input instead of hard-coding llvm::errs.
     464             2513:   llvm::raw_ostream &OS = llvm::errs();
     465                 : 
     466                 :   // Create the target instance.
     467             2513:   setTarget(TargetInfo::CreateTargetInfo(getDiagnostics(), getTargetOpts()));
                        0: branch 1 not taken
                     2513: branch 2 taken
     468             2513:   if (!hasTarget())
     469                0:     return false;
     470                 : 
     471                 :   // Inform the target of the language options.
     472                 :   //
     473                 :   // FIXME: We shouldn't need to do this, the target should be immutable once
     474                 :   // created. This complexity should be lifted elsewhere.
     475             2513:   getTarget().setForcedLangOptions(getLangOpts());
     476                 : 
     477                 :   // Validate/process some options.
                        1: branch 1 taken
                     2512: branch 2 taken
     478             2513:   if (getHeaderSearchOpts().Verbose)
     479                 :     OS << "clang -cc1 version " CLANG_VERSION_STRING
     480                 :        << " based upon " << PACKAGE_STRING
     481                1:        << " hosted on " << llvm::sys::getHostTriple() << "\n";
     482                 : 
                        0: branch 1 not taken
                     2513: branch 2 taken
     483             2513:   if (getFrontendOpts().ShowTimers)
     484                0:     createFrontendTimer();
     485                 : 
                     2513: branch 2 taken
                     2513: branch 3 taken
     486             5026:   for (unsigned i = 0, e = getFrontendOpts().Inputs.size(); i != e; ++i) {
     487             2513:     const std::string &InFile = getFrontendOpts().Inputs[i].second;
     488                 : 
     489                 :     // If we aren't using an AST file, setup the file and source managers and
     490                 :     // the preprocessor.
     491             2513:     bool IsAST = getFrontendOpts().Inputs[i].first == FrontendOptions::IK_AST;
                     2511: branch 0 taken
                        2: branch 1 taken
     492             2513:     if (!IsAST) {
                     2511: branch 0 taken
                        0: branch 1 not taken
     493             2511:       if (!i) {
     494                 :         // Create a file manager object to provide access to and cache the
     495                 :         // filesystem.
     496             2511:         createFileManager();
     497                 : 
     498                 :         // Create the source manager.
     499             2511:         createSourceManager();
     500                 :       } else {
     501                 :         // Reset the ID tables if we are reusing the SourceManager.
     502                0:         getSourceManager().clearIDTables();
     503                 :       }
     504                 : 
     505                 :       // Create the preprocessor.
     506             2511:       createPreprocessor();
     507                 :     }
     508                 : 
                     2510: branch 2 taken
                        3: branch 3 taken
     509             2513:     if (Act.BeginSourceFile(*this, InFile, IsAST)) {
     510             2510:       Act.Execute();
     511             2510:       Act.EndSourceFile();
     512                 :     }
     513                 :   }
     514                 : 
                     2511: branch 1 taken
                        2: branch 2 taken
     515             2513:   if (getDiagnosticOpts().ShowCarets)
                     1142: branch 2 taken
                     1369: branch 3 taken
     516             2511:     if (unsigned NumDiagnostics = getDiagnostics().getNumDiagnostics())
     517                 :       OS << NumDiagnostics << " diagnostic"
     518                 :          << (NumDiagnostics == 1 ? "" : "s")
                      248: branch 0 taken
                      894: branch 1 taken
     519             1142:          << " generated.\n";
     520                 : 
                        2: branch 1 taken
                     2511: branch 2 taken
     521             2513:   if (getFrontendOpts().ShowStats) {
     522                2:     getFileManager().PrintStats();
     523                2:     OS << "\n";
     524                 :   }
     525                 : 
     526                 :   // Return the appropriate status when verifying diagnostics.
     527                 :   //
     528                 :   // FIXME: If we could make getNumErrors() do the right thing, we wouldn't need
     529                 :   // this.
                     1312: branch 1 taken
                     1201: branch 2 taken
     530             2513:   if (getDiagnosticOpts().VerifyDiagnostics)
     531                 :     return !static_cast<VerifyDiagnosticsClient&>(
     532             1312:       getDiagnosticClient()).HadErrors();
     533                 : 
     534             1201:   return !getDiagnostics().getNumErrors();
     535                 : }
     536                 : 
     537                 : 

Generated: 2010-02-10 01:31 by zcov