diff --git a/clang/include/clang/Driver/CC1Options.td b/clang/include/clang/Driver/CC1Options.td index 4a69974d9274..bfa8c8ba02e5 100644 --- a/clang/include/clang/Driver/CC1Options.td +++ b/clang/include/clang/Driver/CC1Options.td @@ -358,9 +358,10 @@ def print_stats : Flag<"-print-stats">, 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. diff --git a/clang/include/clang/Frontend/FrontendOptions.h b/clang/include/clang/Frontend/FrontendOptions.h index 7040b5c1f857..48ce5074faae 100644 --- a/clang/include/clang/Frontend/FrontendOptions.h +++ b/clang/include/clang/Frontend/FrontendOptions.h @@ -74,6 +74,8 @@ public: 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 > Inputs; diff --git a/clang/include/clang/Rewrite/FixItRewriter.h b/clang/include/clang/Rewrite/FixItRewriter.h index 4ebcef0fff61..9b2e0160c5d6 100644 --- a/clang/include/clang/Rewrite/FixItRewriter.h +++ b/clang/include/clang/Rewrite/FixItRewriter.h @@ -27,13 +27,16 @@ namespace clang { 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 @@ class FixItRewriter : public DiagnosticClient { /// \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 @@ public: /// \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(); diff --git a/clang/include/clang/Rewrite/FrontendActions.h b/clang/include/clang/Rewrite/FrontendActions.h index 2ff8d0a5b60a..2b5f88ccee9d 100644 --- a/clang/include/clang/Rewrite/FrontendActions.h +++ b/clang/include/clang/Rewrite/FrontendActions.h @@ -16,7 +16,7 @@ namespace clang { class FixItRewriter; -class FixItPathRewriter; +class FixItOptions; //===----------------------------------------------------------------------===// // AST Consumer Actions @@ -31,7 +31,7 @@ protected: class FixItAction : public ASTFrontendAction { protected: llvm::OwningPtr Rewriter; - llvm::OwningPtr PathRewriter; + llvm::OwningPtr FixItOpts; virtual ASTConsumer *CreateASTConsumer(CompilerInstance &CI, llvm::StringRef InFile); diff --git a/clang/lib/Frontend/CompilerInvocation.cpp b/clang/lib/Frontend/CompilerInvocation.cpp index 4ed4b07565d7..aa6888bd1d72 100644 --- a/clang/lib/Frontend/CompilerInvocation.cpp +++ b/clang/lib/Frontend/CompilerInvocation.cpp @@ -369,6 +369,8 @@ static void FrontendOptsToArgs(const FrontendOptions &Opts, Res.push_back("-ftime-report"); if (Opts.ShowVersion) Res.push_back("-version"); + if (Opts.FixWhatYouCan) + Res.push_back("-fix-what-you-can"); bool NeedLang = false; for (unsigned i = 0, e = Opts.Inputs.size(); i != e; ++i) @@ -1051,6 +1053,7 @@ static InputKind ParseFrontendArgs(FrontendOptions &Opts, ArgList &Args, 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)) { diff --git a/clang/lib/Rewrite/FixItRewriter.cpp b/clang/lib/Rewrite/FixItRewriter.cpp index 29ac7e380bfe..875af7a7c77b 100644 --- a/clang/lib/Rewrite/FixItRewriter.cpp +++ b/clang/lib/Rewrite/FixItRewriter.cpp @@ -27,10 +27,10 @@ using namespace clang; 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::WriteFixedFile(FileID ID, llvm::raw_ostream &OS) { } bool FixItRewriter::WriteFixedFiles() { - if (NumFailures > 0) { + if (NumFailures > 0 && !FixItOpts->FixWhatYouCan) { Diag(FullSourceLoc(), diag::warn_fixit_no_changes); return true; } @@ -57,8 +57,8 @@ bool FixItRewriter::WriteFixedFiles() { 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 @@ void FixItRewriter::Diag(FullSourceLoc Loc, unsigned DiagID) { Diags.setClient(this); } -FixItPathRewriter::~FixItPathRewriter() {} +FixItOptions::~FixItOptions() {} diff --git a/clang/lib/Rewrite/FrontendActions.cpp b/clang/lib/Rewrite/FrontendActions.cpp index 6da3b4bf519c..6d98987a1470 100644 --- a/clang/lib/Rewrite/FrontendActions.cpp +++ b/clang/lib/Rewrite/FrontendActions.cpp @@ -42,12 +42,14 @@ ASTConsumer *FixItAction::CreateASTConsumer(CompilerInstance &CI, 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 @@ bool FixItAction::BeginSourceFileAction(CompilerInstance &CI, 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; }