head	1.1;
branch	1.1.1;
access;
symbols
	netbsd-11-0-RC4:1.1.1.5
	netbsd-11-0-RC3:1.1.1.5
	netbsd-11-0-RC2:1.1.1.5
	netbsd-11-0-RC1:1.1.1.5
	perseant-exfatfs-base-20250801:1.1.1.5
	netbsd-11:1.1.1.5.0.10
	netbsd-11-base:1.1.1.5
	netbsd-10-1-RELEASE:1.1.1.5
	perseant-exfatfs-base-20240630:1.1.1.5
	perseant-exfatfs:1.1.1.5.0.8
	perseant-exfatfs-base:1.1.1.5
	netbsd-8-3-RELEASE:1.1.1.3
	netbsd-9-4-RELEASE:1.1.1.4
	netbsd-10-0-RELEASE:1.1.1.5
	netbsd-10-0-RC6:1.1.1.5
	netbsd-10-0-RC5:1.1.1.5
	netbsd-10-0-RC4:1.1.1.5
	netbsd-10-0-RC3:1.1.1.5
	netbsd-10-0-RC2:1.1.1.5
	netbsd-10-0-RC1:1.1.1.5
	netbsd-10:1.1.1.5.0.6
	netbsd-10-base:1.1.1.5
	netbsd-9-3-RELEASE:1.1.1.4
	cjep_sun2x:1.1.1.5.0.4
	cjep_sun2x-base:1.1.1.5
	cjep_staticlib_x-base1:1.1.1.5
	netbsd-9-2-RELEASE:1.1.1.4
	cjep_staticlib_x:1.1.1.5.0.2
	cjep_staticlib_x-base:1.1.1.5
	netbsd-9-1-RELEASE:1.1.1.4
	phil-wifi-20200421:1.1.1.5
	phil-wifi-20200411:1.1.1.5
	phil-wifi-20200406:1.1.1.5
	netbsd-8-2-RELEASE:1.1.1.3
	netbsd-9-0-RELEASE:1.1.1.4
	netbsd-9-0-RC2:1.1.1.4
	netbsd-9-0-RC1:1.1.1.4
	netbsd-9:1.1.1.4.0.2
	netbsd-9-base:1.1.1.4
	phil-wifi-20190609:1.1.1.4
	netbsd-8-1-RELEASE:1.1.1.3
	netbsd-8-1-RC1:1.1.1.3
	pgoyette-compat-merge-20190127:1.1.1.3.14.1
	pgoyette-compat-20190127:1.1.1.4
	pgoyette-compat-20190118:1.1.1.4
	pgoyette-compat-1226:1.1.1.4
	pgoyette-compat-1126:1.1.1.4
	pgoyette-compat-1020:1.1.1.4
	pgoyette-compat-0930:1.1.1.4
	pgoyette-compat-0906:1.1.1.4
	netbsd-7-2-RELEASE:1.1.1.1.2.1
	pgoyette-compat-0728:1.1.1.4
	clang-337282:1.1.1.4
	netbsd-8-0-RELEASE:1.1.1.3
	phil-wifi:1.1.1.3.0.16
	phil-wifi-base:1.1.1.3
	pgoyette-compat-0625:1.1.1.3
	netbsd-8-0-RC2:1.1.1.3
	pgoyette-compat-0521:1.1.1.3
	pgoyette-compat-0502:1.1.1.3
	pgoyette-compat-0422:1.1.1.3
	netbsd-8-0-RC1:1.1.1.3
	pgoyette-compat-0415:1.1.1.3
	pgoyette-compat-0407:1.1.1.3
	pgoyette-compat-0330:1.1.1.3
	pgoyette-compat-0322:1.1.1.3
	pgoyette-compat-0315:1.1.1.3
	netbsd-7-1-2-RELEASE:1.1.1.1.2.1
	pgoyette-compat:1.1.1.3.0.14
	pgoyette-compat-base:1.1.1.3
	netbsd-7-1-1-RELEASE:1.1.1.1.2.1
	clang-319952:1.1.1.3
	matt-nb8-mediatek:1.1.1.3.0.12
	matt-nb8-mediatek-base:1.1.1.3
	clang-309604:1.1.1.3
	perseant-stdc-iso10646:1.1.1.3.0.10
	perseant-stdc-iso10646-base:1.1.1.3
	netbsd-8:1.1.1.3.0.8
	netbsd-8-base:1.1.1.3
	prg-localcount2-base3:1.1.1.3
	prg-localcount2-base2:1.1.1.3
	prg-localcount2-base1:1.1.1.3
	prg-localcount2:1.1.1.3.0.6
	prg-localcount2-base:1.1.1.3
	pgoyette-localcount-20170426:1.1.1.3
	bouyer-socketcan-base1:1.1.1.3
	pgoyette-localcount-20170320:1.1.1.3
	netbsd-7-1:1.1.1.1.2.1.0.6
	netbsd-7-1-RELEASE:1.1.1.1.2.1
	netbsd-7-1-RC2:1.1.1.1.2.1
	clang-294123:1.1.1.3
	netbsd-7-nhusb-base-20170116:1.1.1.1.2.1
	bouyer-socketcan:1.1.1.3.0.4
	bouyer-socketcan-base:1.1.1.3
	clang-291444:1.1.1.3
	pgoyette-localcount-20170107:1.1.1.3
	netbsd-7-1-RC1:1.1.1.1.2.1
	pgoyette-localcount-20161104:1.1.1.3
	netbsd-7-0-2-RELEASE:1.1.1.1.2.1
	localcount-20160914:1.1.1.3
	netbsd-7-nhusb:1.1.1.1.2.1.0.4
	netbsd-7-nhusb-base:1.1.1.1.2.1
	clang-280599:1.1.1.3
	pgoyette-localcount-20160806:1.1.1.3
	pgoyette-localcount-20160726:1.1.1.3
	pgoyette-localcount:1.1.1.3.0.2
	pgoyette-localcount-base:1.1.1.3
	netbsd-7-0-1-RELEASE:1.1.1.1.2.1
	clang-261930:1.1.1.3
	netbsd-7-0:1.1.1.1.2.1.0.2
	netbsd-7-0-RELEASE:1.1.1.1.2.1
	netbsd-7-0-RC3:1.1.1.1.2.1
	netbsd-7-0-RC2:1.1.1.1.2.1
	netbsd-7-0-RC1:1.1.1.1.2.1
	clang-237755:1.1.1.2
	clang-232565:1.1.1.2
	clang-227398:1.1.1.2
	tls-maxphys-base:1.1.1.1
	tls-maxphys:1.1.1.1.0.4
	netbsd-7:1.1.1.1.0.2
	netbsd-7-base:1.1.1.1
	clang-215315:1.1.1.1
	LLVM:1.1.1;
locks; strict;
comment	@// @;


1.1
date	2014.08.10.17.08.27;	author joerg;	state Exp;
branches
	1.1.1.1;
next	;
commitid	N85tXAN6Ex9VZPLx;

1.1.1.1
date	2014.08.10.17.08.27;	author joerg;	state Exp;
branches
	1.1.1.1.2.1
	1.1.1.1.4.1;
next	1.1.1.2;
commitid	N85tXAN6Ex9VZPLx;

1.1.1.2
date	2015.01.29.19.57.32;	author joerg;	state Exp;
branches;
next	1.1.1.3;
commitid	mlISSizlPKvepX7y;

1.1.1.3
date	2016.02.27.22.11.53;	author joerg;	state Exp;
branches
	1.1.1.3.14.1
	1.1.1.3.16.1;
next	1.1.1.4;
commitid	tIimz3oDlh1NpBWy;

1.1.1.4
date	2018.07.17.18.31.09;	author joerg;	state Exp;
branches;
next	1.1.1.5;
commitid	wDzL46ALjrCZgwKA;

1.1.1.5
date	2019.11.13.22.19.23;	author joerg;	state dead;
branches;
next	;
commitid	QD8YATxuNG34YJKB;

1.1.1.1.2.1
date	2015.06.04.20.04.28;	author snj;	state Exp;
branches;
next	;
commitid	yRnjq9fueSo6n9oy;

1.1.1.1.4.1
date	2014.08.10.17.08.27;	author tls;	state dead;
branches;
next	1.1.1.1.4.2;
commitid	jTnpym9Qu0o4R1Nx;

1.1.1.1.4.2
date	2014.08.19.23.47.28;	author tls;	state Exp;
branches;
next	;
commitid	jTnpym9Qu0o4R1Nx;

1.1.1.3.14.1
date	2018.07.28.04.33.19;	author pgoyette;	state Exp;
branches;
next	;
commitid	1UP1xAIUxv1ZgRLA;

1.1.1.3.16.1
date	2019.06.10.21.45.24;	author christos;	state Exp;
branches;
next	1.1.1.3.16.2;
commitid	jtc8rnCzWiEEHGqB;

1.1.1.3.16.2
date	2020.04.13.07.46.34;	author martin;	state dead;
branches;
next	;
commitid	X01YhRUPVUDaec4C;


desc
@@


1.1
log
@Initial revision
@
text
@//===--- FixItRewriter.cpp - Fix-It Rewriter Diagnostic Client --*- C++ -*-===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This is a diagnostic client adaptor that performs rewrites as
// suggested by code modification hints attached to diagnostics. It
// then forwards any diagnostics to the adapted diagnostic client.
//
//===----------------------------------------------------------------------===//

#include "clang/Rewrite/Frontend/FixItRewriter.h"
#include "clang/Basic/FileManager.h"
#include "clang/Basic/SourceLocation.h"
#include "clang/Basic/SourceManager.h"
#include "clang/Edit/Commit.h"
#include "clang/Edit/EditsReceiver.h"
#include "clang/Frontend/FrontendDiagnostic.h"
#include "llvm/Support/Path.h"
#include "llvm/Support/raw_ostream.h"
#include <cstdio>
#include <memory>

using namespace clang;

FixItRewriter::FixItRewriter(DiagnosticsEngine &Diags, SourceManager &SourceMgr,
                             const LangOptions &LangOpts,
                             FixItOptions *FixItOpts)
  : Diags(Diags),
    Editor(SourceMgr, LangOpts),
    Rewrite(SourceMgr, LangOpts),
    FixItOpts(FixItOpts),
    NumFailures(0),
    PrevDiagSilenced(false) {
  OwnsClient = Diags.ownsClient();
  Client = Diags.takeClient();
  Diags.setClient(this);
}

FixItRewriter::~FixItRewriter() {
  Diags.takeClient();
  Diags.setClient(Client, OwnsClient);
}

bool FixItRewriter::WriteFixedFile(FileID ID, raw_ostream &OS) {
  const RewriteBuffer *RewriteBuf = Rewrite.getRewriteBufferFor(ID);
  if (!RewriteBuf) return true;
  RewriteBuf->write(OS);
  OS.flush();
  return false;
}

namespace {

class RewritesReceiver : public edit::EditsReceiver {
  Rewriter &Rewrite;

public:
  RewritesReceiver(Rewriter &Rewrite) : Rewrite(Rewrite) { }

  void insert(SourceLocation loc, StringRef text) override {
    Rewrite.InsertText(loc, text);
  }
  void replace(CharSourceRange range, StringRef text) override {
    Rewrite.ReplaceText(range.getBegin(), Rewrite.getRangeSize(range), text);
  }
};

}

bool FixItRewriter::WriteFixedFiles(
            std::vector<std::pair<std::string, std::string> > *RewrittenFiles) {
  if (NumFailures > 0 && !FixItOpts->FixWhatYouCan) {
    Diag(FullSourceLoc(), diag::warn_fixit_no_changes);
    return true;
  }

  RewritesReceiver Rec(Rewrite);
  Editor.applyRewrites(Rec);

  for (iterator I = buffer_begin(), E = buffer_end(); I != E; ++I) {
    const FileEntry *Entry = Rewrite.getSourceMgr().getFileEntryForID(I->first);
    int fd;
    std::string Filename = FixItOpts->RewriteFilename(Entry->getName(), fd);
    std::string Err;
    std::unique_ptr<llvm::raw_fd_ostream> OS;
    if (fd != -1) {
      OS.reset(new llvm::raw_fd_ostream(fd, /*shouldClose=*/true));
    } else {
      OS.reset(new llvm::raw_fd_ostream(Filename.c_str(), Err,
                                        llvm::sys::fs::F_None));
    }
    if (!Err.empty()) {
      Diags.Report(clang::diag::err_fe_unable_to_open_output)
          << Filename << Err;
      continue;
    }
    RewriteBuffer &RewriteBuf = I->second;
    RewriteBuf.write(*OS);
    OS->flush();

    if (RewrittenFiles)
      RewrittenFiles->push_back(std::make_pair(Entry->getName(), Filename));
  }

  return false;
}

bool FixItRewriter::IncludeInDiagnosticCounts() const {
  return Client ? Client->IncludeInDiagnosticCounts() : true;
}

void FixItRewriter::HandleDiagnostic(DiagnosticsEngine::Level DiagLevel,
                                     const Diagnostic &Info) {
  // Default implementation (Warnings/errors count).
  DiagnosticConsumer::HandleDiagnostic(DiagLevel, Info);

  if (!FixItOpts->Silent ||
      DiagLevel >= DiagnosticsEngine::Error ||
      (DiagLevel == DiagnosticsEngine::Note && !PrevDiagSilenced) ||
      (DiagLevel > DiagnosticsEngine::Note && Info.getNumFixItHints())) {
    Client->HandleDiagnostic(DiagLevel, Info);
    PrevDiagSilenced = false;
  } else {
    PrevDiagSilenced = true;
  }

  // Skip over any diagnostics that are ignored or notes.
  if (DiagLevel <= DiagnosticsEngine::Note)
    return;
  // Skip over errors if we are only fixing warnings.
  if (DiagLevel >= DiagnosticsEngine::Error && FixItOpts->FixOnlyWarnings) {
    ++NumFailures;
    return;
  }

  // Make sure that we can perform all of the modifications we
  // in this diagnostic.
  edit::Commit commit(Editor);
  for (unsigned Idx = 0, Last = Info.getNumFixItHints();
       Idx < Last; ++Idx) {
    const FixItHint &Hint = Info.getFixItHint(Idx);

    if (Hint.CodeToInsert.empty()) {
      if (Hint.InsertFromRange.isValid())
        commit.insertFromRange(Hint.RemoveRange.getBegin(),
                           Hint.InsertFromRange, /*afterToken=*/false,
                           Hint.BeforePreviousInsertions);
      else
        commit.remove(Hint.RemoveRange);
    } else {
      if (Hint.RemoveRange.isTokenRange() ||
          Hint.RemoveRange.getBegin() != Hint.RemoveRange.getEnd())
        commit.replace(Hint.RemoveRange, Hint.CodeToInsert);
      else
        commit.insert(Hint.RemoveRange.getBegin(), Hint.CodeToInsert,
                    /*afterToken=*/false, Hint.BeforePreviousInsertions);
    }
  }
  bool CanRewrite = Info.getNumFixItHints() > 0 && commit.isCommitable();

  if (!CanRewrite) {
    if (Info.getNumFixItHints() > 0)
      Diag(Info.getLocation(), diag::note_fixit_in_macro);

    // If this was an error, refuse to perform any rewriting.
    if (DiagLevel >= DiagnosticsEngine::Error) {
      if (++NumFailures == 1)
        Diag(Info.getLocation(), diag::note_fixit_unfixed_error);
    }
    return;
  }
  
  if (!Editor.commit(commit)) {
    ++NumFailures;
    Diag(Info.getLocation(), diag::note_fixit_failed);
    return;
  }

  Diag(Info.getLocation(), diag::note_fixit_applied);
}

/// \brief Emit a diagnostic via the adapted diagnostic client.
void FixItRewriter::Diag(SourceLocation Loc, unsigned DiagID) {
  // When producing this diagnostic, we temporarily bypass ourselves,
  // clear out any current diagnostic, and let the downstream client
  // format the diagnostic.
  Diags.takeClient();
  Diags.setClient(Client);
  Diags.Clear();
  Diags.Report(Loc, DiagID);
  Diags.takeClient();
  Diags.setClient(this);
}

FixItOptions::~FixItOptions() {}
@


1.1.1.1
log
@Import clang 3.6svn r215315.
@
text
@@


1.1.1.1.2.1
log
@Update LLVM to 3.6.1, requested by joerg in ticket 824.
@
text
@d39 3
a41 3
  Owner = Diags.takeClient();
  Client = Diags.getClient();
  Diags.setClient(this, false);
d45 2
a46 1
  Diags.setClient(Client, Owner.release() != nullptr);
d89 1
a89 1
    std::error_code EC;
d94 2
a95 1
      OS.reset(new llvm::raw_fd_ostream(Filename, EC, llvm::sys::fs::F_None));
d97 3
a99 3
    if (EC) {
      Diags.Report(clang::diag::err_fe_unable_to_open_output) << Filename
                                                              << EC.message();
d192 2
a193 1
  Diags.setClient(Client, false);
d196 2
a197 1
  Diags.setClient(this, false);
@


1.1.1.2
log
@Import Clang 3.6RC1 r227398.
@
text
@d39 3
a41 3
  Owner = Diags.takeClient();
  Client = Diags.getClient();
  Diags.setClient(this, false);
d45 2
a46 1
  Diags.setClient(Client, Owner.release() != nullptr);
d89 1
a89 1
    std::error_code EC;
d94 2
a95 1
      OS.reset(new llvm::raw_fd_ostream(Filename, EC, llvm::sys::fs::F_None));
d97 3
a99 3
    if (EC) {
      Diags.Report(clang::diag::err_fe_unable_to_open_output) << Filename
                                                              << EC.message();
d192 2
a193 1
  Diags.setClient(Client, false);
d196 2
a197 1
  Diags.setClient(this, false);
@


1.1.1.3
log
@Import Clang 3.8.0rc3 r261930.
@
text
@a83 7
  if (FixItOpts->InPlace) {
    // Overwriting open files on Windows is tricky, but the rewriter can do it
    // for us.
    Rewrite.overwriteChangedFiles();
    return false;
  }

@


1.1.1.3.16.1
log
@Sync with HEAD
@
text
@d1 1
a1 1
//===- FixItRewriter.cpp - Fix-It Rewriter Diagnostic Client --------------===//
a16 1
#include "clang/Basic/Diagnostic.h"
a17 1
#include "clang/Basic/LLVM.h"
d23 1
a23 4
#include "clang/Rewrite/Core/RewriteBuffer.h"
#include "clang/Rewrite/Core/Rewriter.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/Support/FileSystem.h"
a26 3
#include <string>
#include <system_error>
#include <utility>
d33 6
a38 2
    : Diags(Diags), Editor(SourceMgr, LangOpts), Rewrite(SourceMgr, LangOpts),
      FixItOpts(FixItOpts) {
d62 1
a62 1
  RewritesReceiver(Rewriter &Rewrite) : Rewrite(Rewrite) {}
a66 1

d72 1
a72 1
} // namespace
d75 1
a75 1
             std::vector<std::pair<std::string, std::string>> *RewrittenFiles) {
d192 1
a192 1
/// Emit a diagnostic via the adapted diagnostic client.
d203 1
a203 1
FixItOptions::~FixItOptions() = default;
@


1.1.1.3.16.2
log
@Mostly merge changes from HEAD upto 20200411
@
text
@@


1.1.1.3.14.1
log
@Sync with HEAD
@
text
@d1 1
a1 1
//===- FixItRewriter.cpp - Fix-It Rewriter Diagnostic Client --------------===//
a16 1
#include "clang/Basic/Diagnostic.h"
a17 1
#include "clang/Basic/LLVM.h"
d23 1
a23 4
#include "clang/Rewrite/Core/RewriteBuffer.h"
#include "clang/Rewrite/Core/Rewriter.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/Support/FileSystem.h"
a26 3
#include <string>
#include <system_error>
#include <utility>
d33 6
a38 2
    : Diags(Diags), Editor(SourceMgr, LangOpts), Rewrite(SourceMgr, LangOpts),
      FixItOpts(FixItOpts) {
d62 1
a62 1
  RewritesReceiver(Rewriter &Rewrite) : Rewrite(Rewrite) {}
a66 1

d72 1
a72 1
} // namespace
d75 1
a75 1
             std::vector<std::pair<std::string, std::string>> *RewrittenFiles) {
d192 1
a192 1
/// Emit a diagnostic via the adapted diagnostic client.
d203 1
a203 1
FixItOptions::~FixItOptions() = default;
@


1.1.1.4
log
@Import clang r337282 from trunk
@
text
@d1 1
a1 1
//===- FixItRewriter.cpp - Fix-It Rewriter Diagnostic Client --------------===//
a16 1
#include "clang/Basic/Diagnostic.h"
a17 1
#include "clang/Basic/LLVM.h"
d23 1
a23 4
#include "clang/Rewrite/Core/RewriteBuffer.h"
#include "clang/Rewrite/Core/Rewriter.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/Support/FileSystem.h"
a26 3
#include <string>
#include <system_error>
#include <utility>
d33 6
a38 2
    : Diags(Diags), Editor(SourceMgr, LangOpts), Rewrite(SourceMgr, LangOpts),
      FixItOpts(FixItOpts) {
d62 1
a62 1
  RewritesReceiver(Rewriter &Rewrite) : Rewrite(Rewrite) {}
a66 1

d72 1
a72 1
} // namespace
d75 1
a75 1
             std::vector<std::pair<std::string, std::string>> *RewrittenFiles) {
d192 1
a192 1
/// Emit a diagnostic via the adapted diagnostic client.
d203 1
a203 1
FixItOptions::~FixItOptions() = default;
@


1.1.1.5
log
@Mark old LLVM instance as dead.
@
text
@@


1.1.1.1.4.1
log
@file FixItRewriter.cpp was added on branch tls-maxphys on 2014-08-19 23:47:28 +0000
@
text
@d1 200
@


1.1.1.1.4.2
log
@Rebase to HEAD as of a few days ago.
@
text
@a0 200
//===--- FixItRewriter.cpp - Fix-It Rewriter Diagnostic Client --*- C++ -*-===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This is a diagnostic client adaptor that performs rewrites as
// suggested by code modification hints attached to diagnostics. It
// then forwards any diagnostics to the adapted diagnostic client.
//
//===----------------------------------------------------------------------===//

#include "clang/Rewrite/Frontend/FixItRewriter.h"
#include "clang/Basic/FileManager.h"
#include "clang/Basic/SourceLocation.h"
#include "clang/Basic/SourceManager.h"
#include "clang/Edit/Commit.h"
#include "clang/Edit/EditsReceiver.h"
#include "clang/Frontend/FrontendDiagnostic.h"
#include "llvm/Support/Path.h"
#include "llvm/Support/raw_ostream.h"
#include <cstdio>
#include <memory>

using namespace clang;

FixItRewriter::FixItRewriter(DiagnosticsEngine &Diags, SourceManager &SourceMgr,
                             const LangOptions &LangOpts,
                             FixItOptions *FixItOpts)
  : Diags(Diags),
    Editor(SourceMgr, LangOpts),
    Rewrite(SourceMgr, LangOpts),
    FixItOpts(FixItOpts),
    NumFailures(0),
    PrevDiagSilenced(false) {
  OwnsClient = Diags.ownsClient();
  Client = Diags.takeClient();
  Diags.setClient(this);
}

FixItRewriter::~FixItRewriter() {
  Diags.takeClient();
  Diags.setClient(Client, OwnsClient);
}

bool FixItRewriter::WriteFixedFile(FileID ID, raw_ostream &OS) {
  const RewriteBuffer *RewriteBuf = Rewrite.getRewriteBufferFor(ID);
  if (!RewriteBuf) return true;
  RewriteBuf->write(OS);
  OS.flush();
  return false;
}

namespace {

class RewritesReceiver : public edit::EditsReceiver {
  Rewriter &Rewrite;

public:
  RewritesReceiver(Rewriter &Rewrite) : Rewrite(Rewrite) { }

  void insert(SourceLocation loc, StringRef text) override {
    Rewrite.InsertText(loc, text);
  }
  void replace(CharSourceRange range, StringRef text) override {
    Rewrite.ReplaceText(range.getBegin(), Rewrite.getRangeSize(range), text);
  }
};

}

bool FixItRewriter::WriteFixedFiles(
            std::vector<std::pair<std::string, std::string> > *RewrittenFiles) {
  if (NumFailures > 0 && !FixItOpts->FixWhatYouCan) {
    Diag(FullSourceLoc(), diag::warn_fixit_no_changes);
    return true;
  }

  RewritesReceiver Rec(Rewrite);
  Editor.applyRewrites(Rec);

  for (iterator I = buffer_begin(), E = buffer_end(); I != E; ++I) {
    const FileEntry *Entry = Rewrite.getSourceMgr().getFileEntryForID(I->first);
    int fd;
    std::string Filename = FixItOpts->RewriteFilename(Entry->getName(), fd);
    std::string Err;
    std::unique_ptr<llvm::raw_fd_ostream> OS;
    if (fd != -1) {
      OS.reset(new llvm::raw_fd_ostream(fd, /*shouldClose=*/true));
    } else {
      OS.reset(new llvm::raw_fd_ostream(Filename.c_str(), Err,
                                        llvm::sys::fs::F_None));
    }
    if (!Err.empty()) {
      Diags.Report(clang::diag::err_fe_unable_to_open_output)
          << Filename << Err;
      continue;
    }
    RewriteBuffer &RewriteBuf = I->second;
    RewriteBuf.write(*OS);
    OS->flush();

    if (RewrittenFiles)
      RewrittenFiles->push_back(std::make_pair(Entry->getName(), Filename));
  }

  return false;
}

bool FixItRewriter::IncludeInDiagnosticCounts() const {
  return Client ? Client->IncludeInDiagnosticCounts() : true;
}

void FixItRewriter::HandleDiagnostic(DiagnosticsEngine::Level DiagLevel,
                                     const Diagnostic &Info) {
  // Default implementation (Warnings/errors count).
  DiagnosticConsumer::HandleDiagnostic(DiagLevel, Info);

  if (!FixItOpts->Silent ||
      DiagLevel >= DiagnosticsEngine::Error ||
      (DiagLevel == DiagnosticsEngine::Note && !PrevDiagSilenced) ||
      (DiagLevel > DiagnosticsEngine::Note && Info.getNumFixItHints())) {
    Client->HandleDiagnostic(DiagLevel, Info);
    PrevDiagSilenced = false;
  } else {
    PrevDiagSilenced = true;
  }

  // Skip over any diagnostics that are ignored or notes.
  if (DiagLevel <= DiagnosticsEngine::Note)
    return;
  // Skip over errors if we are only fixing warnings.
  if (DiagLevel >= DiagnosticsEngine::Error && FixItOpts->FixOnlyWarnings) {
    ++NumFailures;
    return;
  }

  // Make sure that we can perform all of the modifications we
  // in this diagnostic.
  edit::Commit commit(Editor);
  for (unsigned Idx = 0, Last = Info.getNumFixItHints();
       Idx < Last; ++Idx) {
    const FixItHint &Hint = Info.getFixItHint(Idx);

    if (Hint.CodeToInsert.empty()) {
      if (Hint.InsertFromRange.isValid())
        commit.insertFromRange(Hint.RemoveRange.getBegin(),
                           Hint.InsertFromRange, /*afterToken=*/false,
                           Hint.BeforePreviousInsertions);
      else
        commit.remove(Hint.RemoveRange);
    } else {
      if (Hint.RemoveRange.isTokenRange() ||
          Hint.RemoveRange.getBegin() != Hint.RemoveRange.getEnd())
        commit.replace(Hint.RemoveRange, Hint.CodeToInsert);
      else
        commit.insert(Hint.RemoveRange.getBegin(), Hint.CodeToInsert,
                    /*afterToken=*/false, Hint.BeforePreviousInsertions);
    }
  }
  bool CanRewrite = Info.getNumFixItHints() > 0 && commit.isCommitable();

  if (!CanRewrite) {
    if (Info.getNumFixItHints() > 0)
      Diag(Info.getLocation(), diag::note_fixit_in_macro);

    // If this was an error, refuse to perform any rewriting.
    if (DiagLevel >= DiagnosticsEngine::Error) {
      if (++NumFailures == 1)
        Diag(Info.getLocation(), diag::note_fixit_unfixed_error);
    }
    return;
  }
  
  if (!Editor.commit(commit)) {
    ++NumFailures;
    Diag(Info.getLocation(), diag::note_fixit_failed);
    return;
  }

  Diag(Info.getLocation(), diag::note_fixit_applied);
}

/// \brief Emit a diagnostic via the adapted diagnostic client.
void FixItRewriter::Diag(SourceLocation Loc, unsigned DiagID) {
  // When producing this diagnostic, we temporarily bypass ourselves,
  // clear out any current diagnostic, and let the downstream client
  // format the diagnostic.
  Diags.takeClient();
  Diags.setClient(Client);
  Diags.Clear();
  Diags.Report(Loc, DiagID);
  Diags.takeClient();
  Diags.setClient(this);
}

FixItOptions::~FixItOptions() {}
@


