[cfe-commits] r149027 - in /cfe/trunk: include/clang/Basic/Diagnostic.h include/clang/Driver/CC1Options.td include/clang/Frontend/FrontendOptions.h include/clang/Rewrite/FixItRewriter.h include/clang/Rewrite/FrontendActions.h lib/Frontend/CompilerInvocation.cpp lib/FrontendTool/ExecuteCompilerInvocation.cpp lib/Rewrite/FixItRewriter.cpp lib/Rewrite/FrontendActions.cpp test/FixIt/fixit-recompile.c

Argyrios Kyrtzidis akyrtzi at gmail.com
Wed Jan 25 18:40:49 PST 2012


Author: akirtzidis
Date: Wed Jan 25 20:40:48 2012
New Revision: 149027

URL: http://llvm.org/viewvc/llvm-project?rev=149027&view=rev
Log:
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.

Added:
    cfe/trunk/test/FixIt/fixit-recompile.c
Modified:
    cfe/trunk/include/clang/Basic/Diagnostic.h
    cfe/trunk/include/clang/Driver/CC1Options.td
    cfe/trunk/include/clang/Frontend/FrontendOptions.h
    cfe/trunk/include/clang/Rewrite/FixItRewriter.h
    cfe/trunk/include/clang/Rewrite/FrontendActions.h
    cfe/trunk/lib/Frontend/CompilerInvocation.cpp
    cfe/trunk/lib/FrontendTool/ExecuteCompilerInvocation.cpp
    cfe/trunk/lib/Rewrite/FixItRewriter.cpp
    cfe/trunk/lib/Rewrite/FrontendActions.cpp

Modified: cfe/trunk/include/clang/Basic/Diagnostic.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/Diagnostic.h?rev=149027&r1=149026&r2=149027&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/Diagnostic.h (original)
+++ cfe/trunk/include/clang/Basic/Diagnostic.h Wed Jan 25 20:40:48 2012
@@ -1070,6 +1070,7 @@
 
   unsigned getNumErrors() const { return NumErrors; }
   unsigned getNumWarnings() const { return NumWarnings; }
+  virtual void clear() { NumWarnings = NumErrors = 0; }
 
   virtual ~DiagnosticConsumer();
 

Modified: cfe/trunk/include/clang/Driver/CC1Options.td
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Driver/CC1Options.td?rev=149027&r1=149026&r2=149027&view=diff
==============================================================================
--- cfe/trunk/include/clang/Driver/CC1Options.td (original)
+++ cfe/trunk/include/clang/Driver/CC1Options.td Wed Jan 25 20:40:48 2012
@@ -453,6 +453,12 @@
   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.

Modified: cfe/trunk/include/clang/Frontend/FrontendOptions.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Frontend/FrontendOptions.h?rev=149027&r1=149026&r2=149027&view=diff
==============================================================================
--- cfe/trunk/include/clang/Frontend/FrontendOptions.h (original)
+++ cfe/trunk/include/clang/Frontend/FrontendOptions.h Wed Jan 25 20:40:48 2012
@@ -102,6 +102,9 @@
   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
 

Modified: cfe/trunk/include/clang/Rewrite/FixItRewriter.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Rewrite/FixItRewriter.h?rev=149027&r1=149026&r2=149027&view=diff
==============================================================================
--- cfe/trunk/include/clang/Rewrite/FixItRewriter.h (original)
+++ cfe/trunk/include/clang/Rewrite/FixItRewriter.h Wed Jan 25 20:40:48 2012
@@ -26,6 +26,9 @@
 
 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 @@
 
   /// \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 @@
   /// \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 @@
   /// \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 @@
   /// \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

Modified: cfe/trunk/include/clang/Rewrite/FrontendActions.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Rewrite/FrontendActions.h?rev=149027&r1=149026&r2=149027&view=diff
==============================================================================
--- cfe/trunk/include/clang/Rewrite/FrontendActions.h (original)
+++ cfe/trunk/include/clang/Rewrite/FrontendActions.h Wed Jan 25 20:40:48 2012
@@ -46,6 +46,18 @@
   ~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,

Modified: cfe/trunk/lib/Frontend/CompilerInvocation.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Frontend/CompilerInvocation.cpp?rev=149027&r1=149026&r2=149027&view=diff
==============================================================================
--- cfe/trunk/lib/Frontend/CompilerInvocation.cpp (original)
+++ cfe/trunk/lib/Frontend/CompilerInvocation.cpp Wed Jan 25 20:40:48 2012
@@ -466,6 +466,12 @@
     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 @@
   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,

Modified: cfe/trunk/lib/FrontendTool/ExecuteCompilerInvocation.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/FrontendTool/ExecuteCompilerInvocation.cpp?rev=149027&r1=149026&r2=149027&view=diff
==============================================================================
--- cfe/trunk/lib/FrontendTool/ExecuteCompilerInvocation.cpp (original)
+++ cfe/trunk/lib/FrontendTool/ExecuteCompilerInvocation.cpp Wed Jan 25 20:40:48 2012
@@ -87,6 +87,10 @@
   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:

Modified: cfe/trunk/lib/Rewrite/FixItRewriter.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Rewrite/FixItRewriter.cpp?rev=149027&r1=149026&r2=149027&view=diff
==============================================================================
--- cfe/trunk/lib/Rewrite/FixItRewriter.cpp (original)
+++ cfe/trunk/lib/Rewrite/FixItRewriter.cpp Wed Jan 25 20:40:48 2012
@@ -31,14 +31,16 @@
   : 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 @@
   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 @@
     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 @@
   // 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 @@
       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);
     }

Modified: cfe/trunk/lib/Rewrite/FrontendActions.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Rewrite/FrontendActions.cpp?rev=149027&r1=149026&r2=149027&view=diff
==============================================================================
--- cfe/trunk/lib/Rewrite/FrontendActions.cpp (original)
+++ cfe/trunk/lib/Rewrite/FrontendActions.cpp Wed Jan 25 20:40:48 2012
@@ -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 @@
     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 @@
   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
 //===----------------------------------------------------------------------===//

Added: cfe/trunk/test/FixIt/fixit-recompile.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/FixIt/fixit-recompile.c?rev=149027&view=auto
==============================================================================
--- cfe/trunk/test/FixIt/fixit-recompile.c (added)
+++ cfe/trunk/test/FixIt/fixit-recompile.c Wed Jan 25 20:40:48 2012
@@ -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;





More information about the cfe-commits mailing list