zcov: / lib/Frontend/DependencyFile.cpp


Files: 1 Branches Taken: 56.5% 26 / 46
Generated: 2010-02-10 01:31 Branches Executed: 78.3% 36 / 46
Line Coverage: 75.0% 51 / 68


Programs: 2 Runs 3018


       1                 : //===--- DependencyFile.cpp - Generate dependency file --------------------===//
       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                 : // This code generates dependency files.
      11                 : //
      12                 : //===----------------------------------------------------------------------===//
      13                 : 
      14                 : #include "clang/Frontend/Utils.h"
      15                 : #include "clang/Basic/FileManager.h"
      16                 : #include "clang/Basic/SourceLocation.h"
      17                 : #include "clang/Basic/SourceManager.h"
      18                 : #include "clang/Frontend/DependencyOutputOptions.h"
      19                 : #include "clang/Frontend/FrontendDiagnostic.h"
      20                 : #include "clang/Lex/DirectoryLookup.h"
      21                 : #include "clang/Lex/PPCallbacks.h"
      22                 : #include "clang/Lex/Preprocessor.h"
      23                 : #include "llvm/ADT/StringSet.h"
      24                 : #include "llvm/Support/raw_ostream.h"
      25                 : #include <string>
      26                 : 
      27                 : using namespace clang;
      28                 : 
      29                 : namespace {
      30                 : class DependencyFileCallback : public PPCallbacks {
      31                 :   std::vector<std::string> Files;
      32                 :   llvm::StringSet<> FilesSet;
      33                 :   const Preprocessor *PP;
      34                 :   std::vector<std::string> Targets;
      35                 :   llvm::raw_ostream *OS;
      36                 :   bool IncludeSystemHeaders;
      37                 :   bool PhonyTarget;
      38                 : private:
      39                 :   bool FileMatchesDepCriteria(const char *Filename,
      40                 :                               SrcMgr::CharacteristicKind FileType);
      41                 :   void OutputDependencyFile();
      42                 : 
      43                 : public:
      44                 :   DependencyFileCallback(const Preprocessor *_PP,
      45                 :                          llvm::raw_ostream *_OS,
      46                3:                          const DependencyOutputOptions &Opts)
      47                 :     : PP(_PP), Targets(Opts.Targets), OS(_OS),
      48                 :       IncludeSystemHeaders(Opts.IncludeSystemHeaders),
      49                3:       PhonyTarget(Opts.UsePhonyTargets) {}
      50                 : 
      51                3:   ~DependencyFileCallback() {
      52                3:     OutputDependencyFile();
      53                3:     OS->flush();
                        3: branch 0 taken
                        0: branch 1 not taken
                        3: branch 3 taken
                        3: branch 4 taken
      54                3:     delete OS;
                        3: branch 4 taken
                        0: branch 5 not taken
                        0: branch 11 not taken
                        0: branch 12 not taken
      55                3:   }
      56                 : 
      57                 :   virtual void FileChanged(SourceLocation Loc, FileChangeReason Reason,
      58                 :                            SrcMgr::CharacteristicKind FileType);
      59                 : };
      60                 : }
      61                 : 
      62                 : void clang::AttachDependencyFileGen(Preprocessor &PP,
      63                3:                                     const DependencyOutputOptions &Opts) {
                        0: branch 1 not taken
                        3: branch 2 taken
      64                3:   if (Opts.Targets.empty()) {
      65                0:     PP.getDiagnostics().Report(diag::err_fe_dependency_file_requires_MT);
      66                0:     return;
      67                 :   }
      68                 : 
      69                3:   std::string Err;
      70                3:   llvm::raw_ostream *OS(new llvm::raw_fd_ostream(Opts.OutputFile.c_str(), Err));
                        0: branch 1 not taken
                        3: branch 2 taken
      71                3:   if (!Err.empty()) {
      72                 :     PP.getDiagnostics().Report(diag::err_fe_error_opening)
      73                0:       << Opts.OutputFile << Err;
      74                0:     return;
      75                 :   }
      76                 : 
                        3: branch 1 taken
                        0: branch 2 not taken
      77                3:   assert(!PP.getPPCallbacks() && "Preprocessor callbacks already registered!");
                        3: branch 4 taken
                        0: branch 5 not taken
      78                6:   PP.setPPCallbacks(new DependencyFileCallback(&PP, OS, Opts));
      79                 : }
      80                 : 
      81                 : /// FileMatchesDepCriteria - Determine whether the given Filename should be
      82                 : /// considered as a dependency.
      83                 : bool DependencyFileCallback::FileMatchesDepCriteria(const char *Filename,
      84                3:                                           SrcMgr::CharacteristicKind FileType) {
                        0: branch 1 not taken
                        3: branch 2 taken
      85                3:   if (strcmp("<built-in>", Filename) == 0)
      86                0:     return false;
      87                 : 
                        3: branch 0 taken
                        0: branch 1 not taken
      88                3:   if (IncludeSystemHeaders)
      89                3:     return true;
      90                 : 
      91                0:   return FileType == SrcMgr::C_User;
      92                 : }
      93                 : 
      94                 : void DependencyFileCallback::FileChanged(SourceLocation Loc,
      95                 :                                          FileChangeReason Reason,
      96               18:                                          SrcMgr::CharacteristicKind FileType) {
                        9: branch 0 taken
                        9: branch 1 taken
      97               18:   if (Reason != PPCallbacks::EnterFile)
      98                9:     return;
      99                 : 
     100                 :   // Dependency generation really does want to go all the way to the
     101                 :   // file entry for a source location to find out what is depended on.
     102                 :   // We do not want #line markers to affect dependency generation!
     103                9:   SourceManager &SM = PP->getSourceManager();
     104                 : 
     105                 :   const FileEntry *FE =
     106                9:     SM.getFileEntryForID(SM.getFileID(SM.getInstantiationLoc(Loc)));
                        3: branch 0 taken
                        6: branch 1 taken
     107                9:   if (FE == 0) return;
     108                 : 
     109                3:   const char *Filename = FE->getName();
                        0: branch 1 not taken
                        3: branch 2 taken
     110                3:   if (!FileMatchesDepCriteria(Filename, FileType))
     111                0:     return;
     112                 : 
     113                 :   // Remove leading "./"
                        0: branch 0 not taken
                        3: branch 1 taken
                        3: branch 2 taken
                        3: branch 3 taken
     114                3:   if (Filename[0] == '.' && Filename[1] == '/')
     115                0:     Filename = &Filename[2];
     116                 : 
                        3: branch 5 taken
                        0: branch 6 not taken
     117                3:   if (FilesSet.insert(Filename))
     118                3:     Files.push_back(Filename);
     119                 : }
     120                 : 
     121                3: void DependencyFileCallback::OutputDependencyFile() {
     122                 :   // Write out the dependency targets, trying to avoid overly long
     123                 :   // lines when possible. We try our best to emit exactly the same
     124                 :   // dependency file as GCC (4.2), assuming the included files are the
     125                 :   // same.
     126                3:   const unsigned MaxColumns = 75;
     127                3:   unsigned Columns = 0;
     128                 : 
                        3: branch 2 taken
                        3: branch 3 taken
     129                6:   for (std::vector<std::string>::iterator
     130                3:          I = Targets.begin(), E = Targets.end(); I != E; ++I) {
     131                3:     unsigned N = I->length();
                        3: branch 0 taken
                        0: branch 1 not taken
     132                3:     if (Columns == 0) {
     133                3:       Columns += N;
     134                3:       *OS << *I;
                        0: branch 0 not taken
                        0: branch 1 not taken
     135                0:     } else if (Columns + N + 2 > MaxColumns) {
     136                0:       Columns = N + 2;
     137                0:       *OS << " \\\n  " << *I;
     138                 :     } else {
     139                0:       Columns += N + 1;
     140                0:       *OS << ' ' << *I;
     141                 :     }
     142                 :   }
     143                 : 
     144                3:   *OS << ':';
     145                3:   Columns += 1;
     146                 : 
     147                 :   // Now add each dependency in the order it was seen, but avoiding
     148                 :   // duplicates.
                        3: branch 3 taken
                        3: branch 4 taken
     149                9:   for (std::vector<std::string>::iterator I = Files.begin(),
     150                3:          E = Files.end(); I != E; ++I) {
     151                 :     // Start a new line if this would exceed the column limit. Make
     152                 :     // sure to leave space for a trailing " \" in case we need to
     153                 :     // break the line on the next iteration.
     154                3:     unsigned N = I->length();
                        3: branch 0 taken
                        0: branch 1 not taken
     155                3:     if (Columns + (N + 1) + 2 > MaxColumns) {
     156                3:       *OS << " \\\n ";
     157                3:       Columns = 2;
     158                 :     }
     159                3:     *OS << ' ' << *I;
     160                3:     Columns += N + 1;
     161                 :   }
     162                3:   *OS << '\n';
     163                 : 
     164                 :   // Create phony targets if requested.
                        0: branch 0 not taken
                        3: branch 1 taken
     165                3:   if (PhonyTarget) {
     166                 :     // Skip the first entry, this is always the input file itself.
                        0: branch 4 not taken
                        0: branch 5 not taken
     167                0:     for (std::vector<std::string>::iterator I = Files.begin() + 1,
     168                0:            E = Files.end(); I != E; ++I) {
     169                0:       *OS << '\n';
     170                0:       *OS << *I << ":\n";
     171                 :     }
     172                 :   }
     173                3: }
     174                 : 

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