[cfe-commits] r68324 - in /cfe/trunk: include/clang/Basic/Diagnostic.h include/clang/Basic/DiagnosticFrontendKinds.td include/clang/Frontend/FixItRewriter.h lib/Frontend/FixItRewriter.cpp tools/clang-cc/clang-cc.cpp
Douglas Gregor
dgregor at apple.com
Thu Apr 2 10:13:00 PDT 2009
Author: dgregor
Date: Thu Apr 2 12:13:00 2009
New Revision: 68324
URL: http://llvm.org/viewvc/llvm-project?rev=68324&view=rev
Log:
Provide FIX-IT notes to describe what fix-it is doing behind the
scenes, using the underlying diagnostic client to format the
messages.
Modified:
cfe/trunk/include/clang/Basic/Diagnostic.h
cfe/trunk/include/clang/Basic/DiagnosticFrontendKinds.td
cfe/trunk/include/clang/Frontend/FixItRewriter.h
cfe/trunk/lib/Frontend/FixItRewriter.cpp
cfe/trunk/tools/clang-cc/clang-cc.cpp
Modified: cfe/trunk/include/clang/Basic/Diagnostic.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/Diagnostic.h?rev=68324&r1=68323&r2=68324&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/Diagnostic.h (original)
+++ cfe/trunk/include/clang/Basic/Diagnostic.h Thu Apr 2 12:13:00 2009
@@ -299,6 +299,9 @@
/// @c Pos represents the source location associated with the diagnostic,
/// which can be an invalid location if no position information is available.
inline DiagnosticBuilder Report(FullSourceLoc Pos, unsigned DiagID);
+
+ /// \brief Clear out the current diagnostic.
+ void Clear() { CurDiagID = ~0U; }
private:
/// getDiagnosticLevel - This is an internal implementation helper used when
@@ -423,8 +426,8 @@
// DiagnosticClient.
DiagObj->ProcessDiag();
- // This diagnostic is no longer in flight.
- DiagObj->CurDiagID = ~0U;
+ // Clear out the current diagnostic object.
+ DiagObj->Clear();
// This diagnostic is dead.
DiagObj = 0;
Modified: cfe/trunk/include/clang/Basic/DiagnosticFrontendKinds.td
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticFrontendKinds.td?rev=68324&r1=68323&r2=68324&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/DiagnosticFrontendKinds.td (original)
+++ cfe/trunk/include/clang/Basic/DiagnosticFrontendKinds.td Thu Apr 2 12:13:00 2009
@@ -14,4 +14,12 @@
def err_fe_error_reading : Error<"error reading '%0'">;
def err_fe_error_reading_stdin : Error<"error reading stdin">;
+def note_fixit_applied : Note<"FIX-IT applied suggested code changes">;
+def note_fixit_in_macro : Note<
+ "FIX-IT unable to apply suggested code changes in a macro">;
+def note_fixit_failed : Note<
+ "FIX-IT unable to apply suggested code changes">;
+def note_fixit_unfixed_error : Note<"FIX-IT detected an error it cannot fix">;
+def warn_fixit_no_changes : Note<
+ "FIX-IT detected errors it could not fix; no output will be generated">;
}
Modified: cfe/trunk/include/clang/Frontend/FixItRewriter.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Frontend/FixItRewriter.h?rev=68324&r1=68323&r2=68324&view=diff
==============================================================================
--- cfe/trunk/include/clang/Frontend/FixItRewriter.h (original)
+++ cfe/trunk/include/clang/Frontend/FixItRewriter.h Thu Apr 2 12:13:00 2009
@@ -16,27 +16,30 @@
#define LLVM_CLANG_FRONTEND_FIX_IT_REWRITER_H
#include "clang/Basic/Diagnostic.h"
+#include "clang/Rewrite/Rewriter.h"
namespace clang {
-class Rewriter;
class SourceManager;
class FixItRewriter : public DiagnosticClient {
- /// \brief The adapted diagnostic client, to which we will forward
- /// any diagnostics.
- DiagnosticClient *Client;
+ /// \brief The diagnostics machinery.
+ Diagnostic &Diags;
/// \brief The rewriter used to perform the various code
/// modifications.
- Rewriter *Rewrite;
+ Rewriter Rewrite;
+
+ /// \brief The diagnostic client that performs the actual formatting
+ /// of error messages.
+ DiagnosticClient *Client;
/// \brief The number of rewriter failures.
unsigned NumFailures;
public:
/// \brief Initialize a new fix-it rewriter.
- FixItRewriter(DiagnosticClient *Client, SourceManager &SourceMgr);
+ FixItRewriter(Diagnostic &Diags, SourceManager &SourceMgr);
/// \brief Destroy the fix-it rewriter.
~FixItRewriter();
@@ -58,6 +61,8 @@
virtual void HandleDiagnostic(Diagnostic::Level DiagLevel,
const DiagnosticInfo &Info);
+ /// \brief Emit a diagnostic via the adapted diagnostic client.
+ void Diag(FullSourceLoc Loc, unsigned DiagID);
};
}
Modified: cfe/trunk/lib/Frontend/FixItRewriter.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Frontend/FixItRewriter.cpp?rev=68324&r1=68323&r2=68324&view=diff
==============================================================================
--- cfe/trunk/lib/Frontend/FixItRewriter.cpp (original)
+++ cfe/trunk/lib/Frontend/FixItRewriter.cpp Thu Apr 2 12:13:00 2009
@@ -15,31 +15,27 @@
#include "clang/Frontend/FixItRewriter.h"
#include "clang/Basic/SourceManager.h"
-#include "clang/Rewrite/Rewriter.h"
+#include "clang/Frontend/FrontendDiagnostic.h"
#include "llvm/ADT/OwningPtr.h"
#include "llvm/Support/Streams.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/System/Path.h"
-#include <cstdio>
using namespace clang;
-FixItRewriter::FixItRewriter(DiagnosticClient *Client,
- SourceManager &SourceMgr)
- : Client(Client), NumFailures(0) {
- Rewrite = new Rewriter(SourceMgr);
+FixItRewriter::FixItRewriter(Diagnostic &Diags, SourceManager &SourceMgr)
+ : Diags(Diags), Rewrite(SourceMgr), NumFailures(0) {
+ Client = Diags.getClient();
+ Diags.setClient(this);
}
FixItRewriter::~FixItRewriter() {
- delete Rewrite;
+ Diags.setClient(Client);
}
bool FixItRewriter::WriteFixedFile(const std::string &InFileName,
const std::string &OutFileName) {
if (NumFailures > 0) {
- // FIXME: Use diagnostic machinery!
- std::fprintf(stderr,
- "%d fix-it failures detected; code will not be modified\n",
- NumFailures);
+ Diag(FullSourceLoc(), diag::warn_fixit_no_changes);
return true;
}
@@ -67,9 +63,9 @@
OwnedStream.reset(OutFile);
}
- FileID MainFileID = Rewrite->getSourceMgr().getMainFileID();
+ FileID MainFileID = Rewrite.getSourceMgr().getMainFileID();
if (const RewriteBuffer *RewriteBuf =
- Rewrite->getRewriteBufferFor(MainFileID)) {
+ Rewrite.getRewriteBufferFor(MainFileID)) {
*OutFile << std::string(RewriteBuf->begin(), RewriteBuf->end());
} else {
std::fprintf(stderr, "Main file is unchanged\n");
@@ -95,30 +91,26 @@
Idx < Last; ++Idx) {
const CodeModificationHint &Hint = Info.getCodeModificationHint(Idx);
if (Hint.RemoveRange.isValid() &&
- Rewrite->getRangeSize(Hint.RemoveRange) == -1) {
+ Rewrite.getRangeSize(Hint.RemoveRange) == -1) {
CanRewrite = false;
break;
}
if (Hint.InsertionLoc.isValid() &&
- !Rewrite->isRewritable(Hint.InsertionLoc)) {
+ !Rewrite.isRewritable(Hint.InsertionLoc)) {
CanRewrite = false;
break;
}
}
if (!CanRewrite) {
- if (Info.getNumCodeModificationHints() > 0) {
- // FIXME: warn the user that this rewrite couldn't be done
- }
+ if (Info.getNumCodeModificationHints() > 0)
+ Diag(Info.getLocation(), diag::note_fixit_in_macro);
// If this was an error, refuse to perform any rewriting.
if (DiagLevel == Diagnostic::Error || DiagLevel == Diagnostic::Fatal) {
- if (++NumFailures == 1) {
- // FIXME: use diagnostic machinery to print this.
- std::fprintf(stderr, "error without fix-it advice detected; "
- "fix-it will produce no output\n");
- }
+ if (++NumFailures == 1)
+ Diag(Info.getLocation(), diag::note_fixit_unfixed_error);
}
return;
}
@@ -129,27 +121,43 @@
const CodeModificationHint &Hint = Info.getCodeModificationHint(Idx);
if (!Hint.RemoveRange.isValid()) {
// We're adding code.
- if (Rewrite->InsertStrBefore(Hint.InsertionLoc, Hint.CodeToInsert))
+ if (Rewrite.InsertStrBefore(Hint.InsertionLoc, Hint.CodeToInsert))
Failed = true;
continue;
}
if (Hint.CodeToInsert.empty()) {
// We're removing code.
- if (Rewrite->RemoveText(Hint.RemoveRange.getBegin(),
- Rewrite->getRangeSize(Hint.RemoveRange)))
+ if (Rewrite.RemoveText(Hint.RemoveRange.getBegin(),
+ Rewrite.getRangeSize(Hint.RemoveRange)))
Failed = true;
continue;
}
// We're replacing code.
- if (Rewrite->ReplaceText(Hint.RemoveRange.getBegin(),
- Rewrite->getRangeSize(Hint.RemoveRange),
- Hint.CodeToInsert.c_str(),
- Hint.CodeToInsert.size()))
+ if (Rewrite.ReplaceText(Hint.RemoveRange.getBegin(),
+ Rewrite.getRangeSize(Hint.RemoveRange),
+ Hint.CodeToInsert.c_str(),
+ Hint.CodeToInsert.size()))
Failed = true;
}
- if (Failed) // FIXME: notify the user that the rewrite failed.
+ if (Failed) {
++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(FullSourceLoc 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.setClient(Client);
+ Diags.Clear();
+ Diags.Report(Loc, DiagID);
+ Diags.setClient(this);
}
Modified: cfe/trunk/tools/clang-cc/clang-cc.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/tools/clang-cc/clang-cc.cpp?rev=68324&r1=68323&r2=68324&view=diff
==============================================================================
--- cfe/trunk/tools/clang-cc/clang-cc.cpp (original)
+++ cfe/trunk/tools/clang-cc/clang-cc.cpp Thu Apr 2 12:13:00 2009
@@ -1452,9 +1452,8 @@
case FixIt:
llvm::TimeRegion Timer(ClangFrontendTimer);
Consumer.reset(new ASTConsumer());
- FixItRewrite = new FixItRewriter(PP.getDiagnostics().getClient(),
+ FixItRewrite = new FixItRewriter(PP.getDiagnostics(),
PP.getSourceManager());
- PP.getDiagnostics().setClient(FixItRewrite);
break;
}
More information about the cfe-commits
mailing list