summaryrefslogtreecommitdiffstats
path: root/clang
diff options
context:
space:
mode:
authorArgyrios Kyrtzidis <akyrtzi@gmail.com>2012-01-26 02:40:48 +0000
committerArgyrios Kyrtzidis <akyrtzi@gmail.com>2012-01-26 02:40:48 +0000
commit24e9afff4345b331c8eab721741c3d6cf6600bbf (patch)
tree448a5967ebb13639c601d69768120328419d6702 /clang
parent7b878febf1bb8bec97f0ed55d5c09298b329ad12 (diff)
downloadbcm5719-llvm-24e9afff4345b331c8eab721741c3d6cf6600bbf.tar.gz
bcm5719-llvm-24e9afff4345b331c8eab721741c3d6cf6600bbf.zip
Introduce 3 new fixit options:
-fixit-recompile applies fixits and recompiles the result -fixit-to-temporary applies fixits to temporary files -fix-only-warnings">, applies fixits for warnings only, not errors Combining "-fixit-recompile -fixit-to-temporary" allows testing the result of fixits without touching the original sources. llvm-svn: 149027
Diffstat (limited to 'clang')
-rw-r--r--clang/include/clang/Basic/Diagnostic.h1
-rw-r--r--clang/include/clang/Driver/CC1Options.td6
-rw-r--r--clang/include/clang/Frontend/FrontendOptions.h3
-rw-r--r--clang/include/clang/Rewrite/FixItRewriter.h18
-rw-r--r--clang/include/clang/Rewrite/FrontendActions.h12
-rw-r--r--clang/lib/Frontend/CompilerInvocation.cpp9
-rw-r--r--clang/lib/FrontendTool/ExecuteCompilerInvocation.cpp4
-rw-r--r--clang/lib/Rewrite/FixItRewriter.cpp30
-rw-r--r--clang/lib/Rewrite/FrontendActions.cpp57
-rw-r--r--clang/test/FixIt/fixit-recompile.c6
10 files changed, 139 insertions, 7 deletions
diff --git a/clang/include/clang/Basic/Diagnostic.h b/clang/include/clang/Basic/Diagnostic.h
index 0a785fd0a71..4f5fe6501ef 100644
--- a/clang/include/clang/Basic/Diagnostic.h
+++ b/clang/include/clang/Basic/Diagnostic.h
@@ -1070,6 +1070,7 @@ public:
unsigned getNumErrors() const { return NumErrors; }
unsigned getNumWarnings() const { return NumWarnings; }
+ virtual void clear() { NumWarnings = NumErrors = 0; }
virtual ~DiagnosticConsumer();
diff --git a/clang/include/clang/Driver/CC1Options.td b/clang/include/clang/Driver/CC1Options.td
index 1125ddd6033..bf7b915e3d9 100644
--- a/clang/include/clang/Driver/CC1Options.td
+++ b/clang/include/clang/Driver/CC1Options.td
@@ -453,6 +453,12 @@ def fdump_record_layouts : Flag<"-fdump-record-layouts">,
HelpText<"Dump record layout information">;
def fix_what_you_can : Flag<"-fix-what-you-can">,
HelpText<"Apply fix-it advice even in the presence of unfixable errors">;
+def fix_only_warnings : Flag<"-fix-only-warnings">,
+ HelpText<"Apply fix-it advice only for warnings, not errors">;
+def fixit_recompile : Flag<"-fixit-recompile">,
+ HelpText<"Apply fix-it changes and recompile">;
+def fixit_to_temp : Flag<"-fixit-to-temporary">,
+ HelpText<"Apply fix-it changes to temporary files">;
// Generic forwarding to LLVM options. This should only be used for debugging
// and experimental features.
diff --git a/clang/include/clang/Frontend/FrontendOptions.h b/clang/include/clang/Frontend/FrontendOptions.h
index 637ceff5783..080e1435033 100644
--- a/clang/include/clang/Frontend/FrontendOptions.h
+++ b/clang/include/clang/Frontend/FrontendOptions.h
@@ -102,6 +102,9 @@ public:
unsigned ShowVersion : 1; ///< Show the -version text.
unsigned FixWhatYouCan : 1; ///< Apply fixes even if there are
/// unfixable errors.
+ unsigned FixOnlyWarnings : 1; ///< Apply fixes only for warnings.
+ unsigned FixAndRecompile : 1; ///< Apply fixes and recompile.
+ unsigned FixToTemporaries : 1; ///< Apply fixes to temporary files.
unsigned ARCMTMigrateEmitARCErrors : 1; /// Emit ARC errors even if the
/// migrator can fix them
diff --git a/clang/include/clang/Rewrite/FixItRewriter.h b/clang/include/clang/Rewrite/FixItRewriter.h
index bf7e7911c97..aeda25b24e2 100644
--- a/clang/include/clang/Rewrite/FixItRewriter.h
+++ b/clang/include/clang/Rewrite/FixItRewriter.h
@@ -26,6 +26,9 @@ class FileEntry;
class FixItOptions {
public:
+ FixItOptions() : FixWhatYouCan(false),
+ FixOnlyWarnings(false), Silent(false) { }
+
virtual ~FixItOptions();
/// \brief This file is about to be rewritten. Return the name of the file
@@ -34,6 +37,14 @@ public:
/// \brief Whether to abort fixing a file when not all errors could be fixed.
bool FixWhatYouCan;
+
+ /// \brief Whether to only fix warnings and not errors.
+ bool FixOnlyWarnings;
+
+ /// \brief If true, only pass the diagnostic to the actual diagnostic consumer
+ /// if it is an error or a fixit was applied as part of the diagnostic.
+ /// It basically silences warnings without accompanying fixits.
+ bool Silent;
};
class FixItRewriter : public DiagnosticConsumer {
@@ -47,6 +58,7 @@ class FixItRewriter : public DiagnosticConsumer {
/// \brief The diagnostic client that performs the actual formatting
/// of error messages.
DiagnosticConsumer *Client;
+ bool OwnsClient;
/// \brief Turn an input path into an output path. NULL implies overwriting
/// the original.
@@ -55,6 +67,9 @@ class FixItRewriter : public DiagnosticConsumer {
/// \brief The number of rewriter failures.
unsigned NumFailures;
+ /// \brief Whether the previous diagnostic was not passed to the consumer.
+ bool PrevDiagSilenced;
+
public:
typedef Rewriter::buffer_iterator iterator;
@@ -82,7 +97,8 @@ public:
/// \brief Write the modified source files.
///
/// \returns true if there was an error, false otherwise.
- bool WriteFixedFiles();
+ bool WriteFixedFiles(
+ std::vector<std::pair<std::string, std::string> > *RewrittenFiles = 0);
/// IncludeInDiagnosticCounts - This method (whose default implementation
/// returns true) indicates whether the diagnostics handled by this
diff --git a/clang/include/clang/Rewrite/FrontendActions.h b/clang/include/clang/Rewrite/FrontendActions.h
index f7aeefae7e5..35a37ee6509 100644
--- a/clang/include/clang/Rewrite/FrontendActions.h
+++ b/clang/include/clang/Rewrite/FrontendActions.h
@@ -46,6 +46,18 @@ public:
~FixItAction();
};
+/// \brief Emits changes to temporary files and uses them for the original
+/// frontend action.
+class FixItRecompile : public WrapperFrontendAction {
+ FrontendAction *WrappedAction;
+public:
+ FixItRecompile(FrontendAction *WrappedAction)
+ : WrapperFrontendAction(WrappedAction), WrappedAction(WrappedAction) {}
+
+protected:
+ virtual bool BeginInvocation(CompilerInstance &CI);
+};
+
class RewriteObjCAction : public ASTFrontendAction {
protected:
virtual ASTConsumer *CreateASTConsumer(CompilerInstance &CI,
diff --git a/clang/lib/Frontend/CompilerInvocation.cpp b/clang/lib/Frontend/CompilerInvocation.cpp
index aa367b0a74a..7e5af12d517 100644
--- a/clang/lib/Frontend/CompilerInvocation.cpp
+++ b/clang/lib/Frontend/CompilerInvocation.cpp
@@ -466,6 +466,12 @@ static void FrontendOptsToArgs(const FrontendOptions &Opts,
Res.push_back("-version");
if (Opts.FixWhatYouCan)
Res.push_back("-fix-what-you-can");
+ if (Opts.FixOnlyWarnings)
+ Res.push_back("-fix-only-warnings");
+ if (Opts.FixAndRecompile)
+ Res.push_back("-fixit-recompile");
+ if (Opts.FixToTemporaries)
+ Res.push_back("-fixit-to-temporary");
switch (Opts.ARCMTAction) {
case FrontendOptions::ARCMT_None:
break;
@@ -1401,6 +1407,9 @@ static InputKind ParseFrontendArgs(FrontendOptions &Opts, ArgList &Args,
Opts.ASTMergeFiles = Args.getAllArgValues(OPT_ast_merge);
Opts.LLVMArgs = Args.getAllArgValues(OPT_mllvm);
Opts.FixWhatYouCan = Args.hasArg(OPT_fix_what_you_can);
+ Opts.FixOnlyWarnings = Args.hasArg(OPT_fix_only_warnings);
+ Opts.FixAndRecompile = Args.hasArg(OPT_fixit_recompile);
+ Opts.FixToTemporaries = Args.hasArg(OPT_fixit_to_temp);
Opts.ARCMTAction = FrontendOptions::ARCMT_None;
if (const Arg *A = Args.getLastArg(OPT_arcmt_check,
diff --git a/clang/lib/FrontendTool/ExecuteCompilerInvocation.cpp b/clang/lib/FrontendTool/ExecuteCompilerInvocation.cpp
index 2782a85beb6..9f2bdf25be5 100644
--- a/clang/lib/FrontendTool/ExecuteCompilerInvocation.cpp
+++ b/clang/lib/FrontendTool/ExecuteCompilerInvocation.cpp
@@ -87,6 +87,10 @@ static FrontendAction *CreateFrontendAction(CompilerInstance &CI) {
if (!Act)
return 0;
+ if (CI.getFrontendOpts().FixAndRecompile) {
+ Act = new FixItRecompile(Act);
+ }
+
// Potentially wrap the base FE action in an ARC Migrate Tool action.
switch (CI.getFrontendOpts().ARCMTAction) {
case FrontendOptions::ARCMT_None:
diff --git a/clang/lib/Rewrite/FixItRewriter.cpp b/clang/lib/Rewrite/FixItRewriter.cpp
index 632c0de0742..51029665e47 100644
--- a/clang/lib/Rewrite/FixItRewriter.cpp
+++ b/clang/lib/Rewrite/FixItRewriter.cpp
@@ -31,14 +31,16 @@ FixItRewriter::FixItRewriter(DiagnosticsEngine &Diags, SourceManager &SourceMgr,
: Diags(Diags),
Rewrite(SourceMgr, LangOpts),
FixItOpts(FixItOpts),
- NumFailures(0) {
+ NumFailures(0),
+ PrevDiagSilenced(false) {
+ OwnsClient = Diags.ownsClient();
Client = Diags.takeClient();
Diags.setClient(this);
}
FixItRewriter::~FixItRewriter() {
Diags.takeClient();
- Diags.setClient(Client);
+ Diags.setClient(Client, OwnsClient);
}
bool FixItRewriter::WriteFixedFile(FileID ID, raw_ostream &OS) {
@@ -49,7 +51,8 @@ bool FixItRewriter::WriteFixedFile(FileID ID, raw_ostream &OS) {
return false;
}
-bool FixItRewriter::WriteFixedFiles() {
+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;
@@ -69,6 +72,9 @@ bool FixItRewriter::WriteFixedFiles() {
RewriteBuffer &RewriteBuf = I->second;
RewriteBuf.write(OS);
OS.flush();
+
+ if (RewrittenFiles)
+ RewrittenFiles->push_back(std::make_pair(Entry->getName(), Filename));
}
return false;
@@ -83,11 +89,24 @@ void FixItRewriter::HandleDiagnostic(DiagnosticsEngine::Level DiagLevel,
// Default implementation (Warnings/errors count).
DiagnosticConsumer::HandleDiagnostic(DiagLevel, Info);
- Client->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.
@@ -107,8 +126,7 @@ void FixItRewriter::HandleDiagnostic(DiagnosticsEngine::Level DiagLevel,
Diag(Info.getLocation(), diag::note_fixit_in_macro);
// If this was an error, refuse to perform any rewriting.
- if (DiagLevel == DiagnosticsEngine::Error ||
- DiagLevel == DiagnosticsEngine::Fatal) {
+ if (DiagLevel >= DiagnosticsEngine::Error) {
if (++NumFailures == 1)
Diag(Info.getLocation(), diag::note_fixit_unfixed_error);
}
diff --git a/clang/lib/Rewrite/FrontendActions.cpp b/clang/lib/Rewrite/FrontendActions.cpp
index f00e7fd9c91..c1568cd5223 100644
--- a/clang/lib/Rewrite/FrontendActions.cpp
+++ b/clang/lib/Rewrite/FrontendActions.cpp
@@ -12,6 +12,7 @@
#include "clang/Lex/Preprocessor.h"
#include "clang/Parse/Parser.h"
#include "clang/Basic/FileManager.h"
+#include "clang/Frontend/FrontendActions.h"
#include "clang/Frontend/CompilerInstance.h"
#include "clang/Frontend/FrontendDiagnostic.h"
#include "clang/Frontend/Utils.h"
@@ -21,6 +22,7 @@
#include "llvm/ADT/OwningPtr.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/Support/Path.h"
+#include "llvm/Support/FileSystem.h"
using namespace clang;
//===----------------------------------------------------------------------===//
@@ -64,6 +66,22 @@ public:
return Path.str();
}
};
+
+class FixItRewriteToTemp : public FixItOptions {
+public:
+ std::string RewriteFilename(const std::string &Filename) {
+ llvm::SmallString<128> Path;
+ Path = llvm::sys::path::filename(Filename);
+ Path += "-%%%%%%%%";
+ Path += llvm::sys::path::extension(Filename);
+ int fd;
+ llvm::SmallString<128> NewPath;
+ if (llvm::sys::fs::unique_file(Path.str(), fd, NewPath)
+ == llvm::errc::success)
+ ::close(fd);
+ return NewPath.str();
+ }
+};
} // end anonymous namespace
bool FixItAction::BeginSourceFileAction(CompilerInstance &CI,
@@ -86,6 +104,45 @@ void FixItAction::EndSourceFileAction() {
Rewriter->WriteFixedFiles();
}
+bool FixItRecompile::BeginInvocation(CompilerInstance &CI) {
+
+ std::vector<std::pair<std::string, std::string> > RewrittenFiles;
+ bool err = false;
+ {
+ const FrontendOptions &FEOpts = CI.getFrontendOpts();
+ llvm::OwningPtr<FrontendAction> FixAction(new SyntaxOnlyAction());
+ FixAction->BeginSourceFile(CI, FEOpts.Inputs[0]);
+
+ llvm::OwningPtr<FixItOptions> FixItOpts;
+ if (FEOpts.FixToTemporaries)
+ FixItOpts.reset(new FixItRewriteToTemp());
+ else
+ FixItOpts.reset(new FixItRewriteInPlace());
+ FixItOpts->Silent = true;
+ FixItOpts->FixWhatYouCan = FEOpts.FixWhatYouCan;
+ FixItOpts->FixOnlyWarnings = FEOpts.FixOnlyWarnings;
+ FixItRewriter Rewriter(CI.getDiagnostics(), CI.getSourceManager(),
+ CI.getLangOpts(), FixItOpts.get());
+ FixAction->Execute();
+
+ err = Rewriter.WriteFixedFiles(&RewrittenFiles);
+
+ FixAction->EndSourceFile();
+ CI.setSourceManager(0);
+ CI.setFileManager(0);
+ }
+ if (err)
+ return false;
+ CI.getDiagnosticClient().clear();
+
+ PreprocessorOptions &PPOpts = CI.getPreprocessorOpts();
+ PPOpts.RemappedFiles.insert(PPOpts.RemappedFiles.end(),
+ RewrittenFiles.begin(), RewrittenFiles.end());
+ PPOpts.RemappedFilesKeepOriginalName = false;
+
+ return true;
+}
+
//===----------------------------------------------------------------------===//
// Preprocessor Actions
//===----------------------------------------------------------------------===//
diff --git a/clang/test/FixIt/fixit-recompile.c b/clang/test/FixIt/fixit-recompile.c
new file mode 100644
index 00000000000..a2e62fbddcd
--- /dev/null
+++ b/clang/test/FixIt/fixit-recompile.c
@@ -0,0 +1,6 @@
+// RUN: %clang_cc1 -Werror -pedantic %s -fixit-recompile -fixit-to-temporary -E -o - | FileCheck %s
+// RUN: not %clang_cc1 -Werror -pedantic %s -fixit-recompile -fixit-to-temporary -fix-only-warnings
+
+_Complex cd;
+
+// CHECK: _Complex double cd;
OpenPOWER on IntegriCloud