zcov: / lib/Frontend/FixItRewriter.cpp


Files: 1 Branches Taken: 54.2% 39 / 72
Generated: 2010-02-10 01:31 Branches Executed: 75.0% 54 / 72
Line Coverage: 64.2% 61 / 95


Programs: 1 Runs 2897


       1                 : //===--- FixItRewriter.cpp - Fix-It Rewriter Diagnostic Client --*- C++ -*-===//
       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 is a diagnostic client adaptor that performs rewrites as
      11                 : // suggested by code modification hints attached to diagnostics. It
      12                 : // then forwards any diagnostics to the adapted diagnostic client.
      13                 : //
      14                 : //===----------------------------------------------------------------------===//
      15                 : 
      16                 : #include "clang/Frontend/FixItRewriter.h"
      17                 : #include "clang/Basic/SourceManager.h"
      18                 : #include "clang/Frontend/FrontendDiagnostic.h"
      19                 : #include "llvm/Support/raw_ostream.h"
      20                 : #include "llvm/System/Path.h"
      21                 : #include "llvm/ADT/OwningPtr.h"
      22                 : #include <cstdio>
      23                 : 
      24                 : using namespace clang;
      25                 : 
      26                 : FixItRewriter::FixItRewriter(Diagnostic &Diags, SourceManager &SourceMgr,
      27               12:                              const LangOptions &LangOpts)
      28               12:   : Diags(Diags), Rewrite(SourceMgr, LangOpts), NumFailures(0) {
      29               12:   Client = Diags.getClient();
      30               12:   Diags.setClient(this);
      31               12: }
      32                 : 
      33               12: FixItRewriter::~FixItRewriter() {
      34               12:   Diags.setClient(Client);
                       12: branch 3 taken
                        0: branch 4 not taken
                        0: branch 9 not taken
                        0: branch 10 not taken
                        0: branch 15 not taken
                        0: branch 16 not taken
      35               12: }
      36                 : 
      37                 : bool FixItRewriter::WriteFixedFile(const std::string &InFileName,
      38               12:                                    const std::string &OutFileName) {
                        3: branch 0 taken
                        9: branch 1 taken
      39               12:   if (NumFailures > 0) {
      40                3:     Diag(FullSourceLoc(), diag::warn_fixit_no_changes);
      41                3:     return true;
      42                 :   }
      43                 : 
      44                9:   llvm::OwningPtr<llvm::raw_ostream> OwnedStream;
      45                 :   llvm::raw_ostream *OutFile;
                        9: branch 1 taken
                        0: branch 2 not taken
      46                9:   if (!OutFileName.empty()) {
      47                9:     std::string Err;
      48                 :     OutFile = new llvm::raw_fd_ostream(OutFileName.c_str(), Err,
      49                9:                                        llvm::raw_fd_ostream::F_Binary);
      50                9:     OwnedStream.reset(OutFile);
                        0: branch 1 not taken
                        0: branch 2 not taken
      51                0:   } else if (InFileName == "-") {
      52                0:     OutFile = &llvm::outs();
      53                 :   } else {
      54                0:     llvm::sys::Path Path(InFileName);
      55                0:     std::string Suffix = Path.getSuffix();
      56                0:     Path.eraseSuffix();
      57                0:     Path.appendSuffix("fixit." + Suffix);
      58                0:     std::string Err;
      59                 :     OutFile = new llvm::raw_fd_ostream(Path.c_str(), Err,
      60                0:                                        llvm::raw_fd_ostream::F_Binary);
      61                0:     OwnedStream.reset(OutFile);
      62                 :   }
      63                 : 
      64                9:   FileID MainFileID = Rewrite.getSourceMgr().getMainFileID();
                        8: branch 0 taken
                        1: branch 1 taken
      65                9:   if (const RewriteBuffer *RewriteBuf =
      66                9:         Rewrite.getRewriteBufferFor(MainFileID)) {
      67                8:     *OutFile << std::string(RewriteBuf->begin(), RewriteBuf->end());
      68                 :   } else {
      69                1:     Diag(FullSourceLoc(), diag::note_fixit_main_file_unchanged);
      70                 :   }
      71                9:   OutFile->flush();
      72                 : 
      73                9:   return false;
      74                 : }
      75                 : 
      76               98: bool FixItRewriter::IncludeInDiagnosticCounts() const {
                       98: branch 0 taken
                        0: branch 1 not taken
      77               98:   return Client? Client->IncludeInDiagnosticCounts() : true;
      78                 : }
      79                 : 
      80                 : void FixItRewriter::HandleDiagnostic(Diagnostic::Level DiagLevel,
      81               98:                                      const DiagnosticInfo &Info) {
      82               98:   Client->HandleDiagnostic(DiagLevel, Info);
      83                 : 
      84                 :   // Skip over any diagnostics that are ignored.
                        0: branch 0 not taken
                       98: branch 1 taken
      85               98:   if (DiagLevel == Diagnostic::Ignored)
      86                0:     return;
      87                 : 
                        0: branch 1 not taken
                       98: branch 2 taken
      88               98:   if (!FixItLocations.empty()) {
      89                 :     // The user has specified the locations where we should perform
      90                 :     // the various fix-it modifications.
      91                 : 
      92                 :     // If this diagnostic does not have any code modifications,
      93                 :     // completely ignore it, even if it's an error: fix-it locations
      94                 :     // are meant to perform specific fix-ups even in the presence of
      95                 :     // other errors.
                        0: branch 1 not taken
                        0: branch 2 not taken
      96                0:     if (Info.getNumCodeModificationHints() == 0)
      97                0:       return;
      98                 : 
      99                 :     // See if the location of the error is one that matches what the
     100                 :     // user requested.
     101                0:     bool AcceptableLocation = false;
     102                 :     const FileEntry *File
     103                 :       = Rewrite.getSourceMgr().getFileEntryForID(
     104                0:                                             Info.getLocation().getFileID());
     105                0:     unsigned Line = Info.getLocation().getSpellingLineNumber();
     106                0:     unsigned Column = Info.getLocation().getSpellingColumnNumber();
                        0: branch 0 not taken
                        0: branch 1 not taken
     107                0:     for (llvm::SmallVector<RequestedSourceLocation, 4>::iterator
     108                0:            Loc = FixItLocations.begin(), LocEnd = FixItLocations.end();
     109                 :          Loc != LocEnd; ++Loc) {
                        0: branch 0 not taken
                        0: branch 1 not taken
                        0: branch 2 not taken
                        0: branch 3 not taken
                        0: branch 4 not taken
                        0: branch 5 not taken
     110                0:       if (Loc->File == File && Loc->Line == Line && Loc->Column == Column) {
     111                0:         AcceptableLocation = true;
     112                0:         break;
     113                 :       }
     114                 :     }
     115                 : 
                        0: branch 0 not taken
                        0: branch 1 not taken
     116                0:     if (!AcceptableLocation)
     117                0:       return;
                       33: branch 0 taken
                       65: branch 1 taken
     118               98:   } else if (DiagLevel == Diagnostic::Note) {
     119                 :     // Don't apply fix-it modifications in notes.
     120               33:     return;
     121                 :   }
     122                 : 
     123                 :   // Make sure that we can perform all of the modifications we
     124                 :   // in this diagnostic.
     125               65:   bool CanRewrite = Info.getNumCodeModificationHints() > 0;
                       65: branch 1 taken
                       65: branch 2 taken
     126              130:   for (unsigned Idx = 0, Last = Info.getNumCodeModificationHints();
     127                 :        Idx < Last; ++Idx) {
     128               65:     const CodeModificationHint &Hint = Info.getCodeModificationHint(Idx);
                       36: branch 1 taken
                       29: branch 2 taken
                        0: branch 4 not taken
                       36: branch 5 taken
                        0: branch 6 not taken
                       65: branch 7 taken
     129               65:     if (Hint.RemoveRange.isValid() &&
     130                 :         Rewrite.getRangeSize(Hint.RemoveRange) == -1) {
     131                0:       CanRewrite = false;
     132                0:       break;
     133                 :     }
     134                 : 
                       59: branch 1 taken
                        6: branch 2 taken
                        0: branch 4 not taken
                       59: branch 5 taken
                        0: branch 6 not taken
                       65: branch 7 taken
     135               65:     if (Hint.InsertionLoc.isValid() &&
     136                 :         !Rewrite.isRewritable(Hint.InsertionLoc)) {
     137                0:       CanRewrite = false;
     138                0:       break;
     139                 :     }
     140                 :   }
     141                 : 
                        8: branch 0 taken
                       57: branch 1 taken
     142               65:   if (!CanRewrite) {
                        0: branch 1 not taken
                        8: branch 2 taken
     143                8:     if (Info.getNumCodeModificationHints() > 0)
     144                0:       Diag(Info.getLocation(), diag::note_fixit_in_macro);
     145                 : 
     146                 :     // If this was an error, refuse to perform any rewriting.
                        1: branch 0 taken
                        7: branch 1 taken
                        0: branch 2 not taken
                        1: branch 3 taken
     147                8:     if (DiagLevel == Diagnostic::Error || DiagLevel == Diagnostic::Fatal) {
                        3: branch 0 taken
                        4: branch 1 taken
     148                7:       if (++NumFailures == 1)
     149                3:         Diag(Info.getLocation(), diag::note_fixit_unfixed_error);
     150                 :     }
     151                8:     return;
     152                 :   }
     153                 : 
     154               57:   bool Failed = false;
                       65: branch 1 taken
                       57: branch 2 taken
     155              122:   for (unsigned Idx = 0, Last = Info.getNumCodeModificationHints();
     156                 :        Idx < Last; ++Idx) {
     157               65:     const CodeModificationHint &Hint = Info.getCodeModificationHint(Idx);
                       29: branch 1 taken
                       36: branch 2 taken
     158               65:     if (!Hint.RemoveRange.isValid()) {
     159                 :       // We're adding code.
                        0: branch 2 not taken
                       29: branch 3 taken
     160               29:       if (Rewrite.InsertTextBefore(Hint.InsertionLoc, Hint.CodeToInsert))
     161                0:         Failed = true;
     162               29:       continue;
     163                 :     }
     164                 : 
                        6: branch 1 taken
                       30: branch 2 taken
     165               36:     if (Hint.CodeToInsert.empty()) {
     166                 :       // We're removing code.
                        0: branch 3 not taken
                        6: branch 4 taken
     167                6:       if (Rewrite.RemoveText(Hint.RemoveRange.getBegin(),
     168                 :                              Rewrite.getRangeSize(Hint.RemoveRange)))
     169                0:         Failed = true;
     170                6:       continue;
     171                 :     }
     172                 : 
     173                 :     // We're replacing code.
                        0: branch 4 not taken
                       30: branch 5 taken
     174               30:     if (Rewrite.ReplaceText(Hint.RemoveRange.getBegin(),
     175                 :                             Rewrite.getRangeSize(Hint.RemoveRange),
     176                 :                             Hint.CodeToInsert))
     177                0:       Failed = true;
     178                 :   }
     179                 : 
                        0: branch 0 not taken
                       57: branch 1 taken
     180               57:   if (Failed) {
     181                0:     ++NumFailures;
     182                0:     Diag(Info.getLocation(), diag::note_fixit_failed);
     183                0:     return;
     184                 :   }
     185                 : 
     186               57:   Diag(Info.getLocation(), diag::note_fixit_applied);
     187                 : }
     188                 : 
     189                 : /// \brief Emit a diagnostic via the adapted diagnostic client.
     190               64: void FixItRewriter::Diag(FullSourceLoc Loc, unsigned DiagID) {
     191                 :   // When producing this diagnostic, we temporarily bypass ourselves,
     192                 :   // clear out any current diagnostic, and let the downstream client
     193                 :   // format the diagnostic.
     194               64:   Diags.setClient(Client);
     195               64:   Diags.Clear();
     196               64:   Diags.Report(Loc, DiagID);
     197               64:   Diags.setClient(this);
     198               64: }

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