The attached patch adds a new feature to clang -fixit, labelled
"-fix-what-you-can". By default, fix-it will refuse to make any fixes in a
file that contains unfixable errors. This is undesirable behaviour much of
the time, so the new -fix-what-you-can flag applies all fixits in each file.

It's implemented by extending the existing FixItPathRewriter to include a
bool FixWhatYouCan, and then renaming it to FixItOptions since it's no
longer just for rewriting paths.

Please review!

Nick
Index: include/clang/Frontend/FrontendOptions.h
===================================================================
--- include/clang/Frontend/FrontendOptions.h	(revision 110945)
+++ include/clang/Frontend/FrontendOptions.h	(working copy)
@@ -74,6 +74,8 @@
   unsigned ShowTimers : 1;                 ///< Show timers for individual
                                            /// actions.
   unsigned ShowVersion : 1;                ///< Show the -version text.
+  unsigned FixWhatYouCan : 1;              ///< Apply fixes even if there are
+                                           /// unfixable errors.
 
   /// The input files and their types.
   std::vector<std::pair<InputKind, std::string> > Inputs;
Index: include/clang/Rewrite/FrontendActions.h
===================================================================
--- include/clang/Rewrite/FrontendActions.h	(revision 110945)
+++ include/clang/Rewrite/FrontendActions.h	(working copy)
@@ -16,7 +16,7 @@
 
 namespace clang {
 class FixItRewriter;
-class FixItPathRewriter;
+class FixItOptions;
 
 //===----------------------------------------------------------------------===//
 // AST Consumer Actions
@@ -31,7 +31,7 @@
 class FixItAction : public ASTFrontendAction {
 protected:
   llvm::OwningPtr<FixItRewriter> Rewriter;
-  llvm::OwningPtr<FixItPathRewriter> PathRewriter;
+  llvm::OwningPtr<FixItOptions> FixItOpts;
 
   virtual ASTConsumer *CreateASTConsumer(CompilerInstance &CI,
                                          llvm::StringRef InFile);
Index: include/clang/Rewrite/FixItRewriter.h
===================================================================
--- include/clang/Rewrite/FixItRewriter.h	(revision 110945)
+++ include/clang/Rewrite/FixItRewriter.h	(working copy)
@@ -27,13 +27,16 @@
 class SourceManager;
 class FileEntry;
 
-class FixItPathRewriter {
+class FixItOptions {
 public:
-  virtual ~FixItPathRewriter();
+  virtual ~FixItOptions();
 
   /// \brief This file is about to be rewritten. Return the name of the file
   /// that is okay to write to.
   virtual std::string RewriteFilename(const std::string &Filename) = 0;
+
+  /// \brief Whether to abort fixing a file when not all errors could be fixed.
+  bool FixWhatYouCan;
 };
 
 class FixItRewriter : public DiagnosticClient {
@@ -50,7 +53,7 @@
 
   /// \brief Turn an input path into an output path. NULL implies overwriting
   /// the original.
-  FixItPathRewriter *PathRewriter;
+  FixItOptions *FixItOpts;
 
   /// \brief The number of rewriter failures.
   unsigned NumFailures;
@@ -60,7 +63,7 @@
 
   /// \brief Initialize a new fix-it rewriter.
   FixItRewriter(Diagnostic &Diags, SourceManager &SourceMgr,
-                const LangOptions &LangOpts, FixItPathRewriter *PathRewriter);
+                const LangOptions &LangOpts, FixItOptions *FixItOpts);
 
   /// \brief Destroy the fix-it rewriter.
   ~FixItRewriter();
Index: include/clang/Driver/CC1Options.td
===================================================================
--- include/clang/Driver/CC1Options.td	(revision 110945)
+++ include/clang/Driver/CC1Options.td	(working copy)
@@ -358,9 +358,10 @@
   HelpText<"Print performance metrics and statistics">;
 def ftime_report : Flag<"-ftime-report">,
   HelpText<"Print the amount of time each phase of compilation takes">;
-
 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">;
 
 // Generic forwarding to LLVM options. This should only be used for debugging
 // and experimental features.
Index: lib/Frontend/CompilerInvocation.cpp
===================================================================
--- lib/Frontend/CompilerInvocation.cpp	(revision 110945)
+++ lib/Frontend/CompilerInvocation.cpp	(working copy)
@@ -1050,6 +1050,7 @@
   Opts.ViewClassInheritance = Args.getLastArgValue(OPT_cxx_inheritance_view);
   Opts.ASTMergeFiles = Args.getAllArgValues(OPT_ast_merge);
   Opts.LLVMArgs = Args.getAllArgValues(OPT_mllvm);
+  Opts.FixWhatYouCan = Args.hasArg(OPT_fix_what_you_can);
 
   InputKind DashX = IK_None;
   if (const Arg *A = Args.getLastArg(OPT_x)) {
Index: lib/Rewrite/FrontendActions.cpp
===================================================================
--- lib/Rewrite/FrontendActions.cpp	(revision 110945)
+++ lib/Rewrite/FrontendActions.cpp	(working copy)
@@ -42,12 +42,14 @@
   return new ASTConsumer();
 }
 
-class FixItActionSuffixInserter : public FixItPathRewriter {
+class FixItActionSuffixInserter : public FixItOptions {
   std::string NewSuffix;
 
 public:
-  explicit FixItActionSuffixInserter(std::string NewSuffix)
-    : NewSuffix(NewSuffix) {}
+  FixItActionSuffixInserter(std::string NewSuffix, bool FixWhatYouCan)
+    : NewSuffix(NewSuffix) {
+      this->FixWhatYouCan = FixWhatYouCan;
+  }
 
   std::string RewriteFilename(const std::string &Filename) {
     llvm::sys::Path Path(Filename);
@@ -62,12 +64,13 @@
                                         llvm::StringRef Filename) {
   const FrontendOptions &FEOpts = getCompilerInstance().getFrontendOpts();
   if (!FEOpts.FixItSuffix.empty()) {
-    PathRewriter.reset(new FixItActionSuffixInserter(FEOpts.FixItSuffix));
+    FixItOpts.reset(new FixItActionSuffixInserter(FEOpts.FixItSuffix,
+                                                  FEOpts.FixWhatYouCan));
   } else {
-    PathRewriter.reset();
+    FixItOpts.reset();
   }
   Rewriter.reset(new FixItRewriter(CI.getDiagnostics(), CI.getSourceManager(),
-                                   CI.getLangOpts(), PathRewriter.get()));
+                                   CI.getLangOpts(), FixItOpts.get()));
   return true;
 }
 
Index: lib/Rewrite/FixItRewriter.cpp
===================================================================
--- lib/Rewrite/FixItRewriter.cpp	(revision 110945)
+++ lib/Rewrite/FixItRewriter.cpp	(working copy)
@@ -27,10 +27,10 @@
 
 FixItRewriter::FixItRewriter(Diagnostic &Diags, SourceManager &SourceMgr,
                              const LangOptions &LangOpts,
-                             FixItPathRewriter *PathRewriter)
+                             FixItOptions *FixItOpts)
   : Diags(Diags),
     Rewrite(SourceMgr, LangOpts),
-    PathRewriter(PathRewriter),
+    FixItOpts(FixItOpts),
     NumFailures(0) {
   Client = Diags.getClient();
   Diags.setClient(this);
@@ -49,7 +49,7 @@
 }
 
 bool FixItRewriter::WriteFixedFiles() {
-  if (NumFailures > 0) {
+  if (NumFailures > 0 && !FixItOpts->FixWhatYouCan) {
     Diag(FullSourceLoc(), diag::warn_fixit_no_changes);
     return true;
   }
@@ -57,8 +57,8 @@
   for (iterator I = buffer_begin(), E = buffer_end(); I != E; ++I) {
     const FileEntry *Entry = Rewrite.getSourceMgr().getFileEntryForID(I->first);
     std::string Filename = Entry->getName();
-    if (PathRewriter)
-      Filename = PathRewriter->RewriteFilename(Filename);
+    if (FixItOpts)
+      Filename = FixItOpts->RewriteFilename(Filename);
     std::string Err;
     llvm::raw_fd_ostream OS(Filename.c_str(), Err,
                             llvm::raw_fd_ostream::F_Binary);
@@ -164,4 +164,4 @@
   Diags.setClient(this);
 }
 
-FixItPathRewriter::~FixItPathRewriter() {}
+FixItOptions::~FixItOptions() {}
_______________________________________________
cfe-commits mailing list
[email protected]
http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits

Reply via email to