diff options
author | Argyrios Kyrtzidis <akyrtzi@gmail.com> | 2012-01-26 02:40:48 +0000 |
---|---|---|
committer | Argyrios Kyrtzidis <akyrtzi@gmail.com> | 2012-01-26 02:40:48 +0000 |
commit | 24e9afff4345b331c8eab721741c3d6cf6600bbf (patch) | |
tree | 448a5967ebb13639c601d69768120328419d6702 /clang/lib | |
parent | 7b878febf1bb8bec97f0ed55d5c09298b329ad12 (diff) | |
download | bcm5719-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/lib')
-rw-r--r-- | clang/lib/Frontend/CompilerInvocation.cpp | 9 | ||||
-rw-r--r-- | clang/lib/FrontendTool/ExecuteCompilerInvocation.cpp | 4 | ||||
-rw-r--r-- | clang/lib/Rewrite/FixItRewriter.cpp | 30 | ||||
-rw-r--r-- | clang/lib/Rewrite/FrontendActions.cpp | 57 |
4 files changed, 94 insertions, 6 deletions
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 //===----------------------------------------------------------------------===// |