From 30abda16129b16f4e2117e7f121ffefcc9d868e4 Mon Sep 17 00:00:00 2001 From: Daniel Jasper Date: Wed, 3 Oct 2012 13:28:43 +0000 Subject: [PATCH] As opposed to the clang-fixit tool described on http://clang.llvm.org/docs/ClangTools.html, this adds -fixit option to clang-check. Thus, clang-check can become a general-purpose tool to run clang capitalizing on the info stored in a compilation database. Review: http://llvm-reviews.chandlerc.com/D51 llvm-svn: 165110 --- clang/tools/clang-check/CMakeLists.txt | 1 + clang/tools/clang-check/ClangCheck.cpp | 74 ++++++++++++++++++++++++++++++++-- clang/tools/clang-check/Makefile | 4 +- 3 files changed, 74 insertions(+), 5 deletions(-) diff --git a/clang/tools/clang-check/CMakeLists.txt b/clang/tools/clang-check/CMakeLists.txt index 85e229f..f5d7616 100644 --- a/clang/tools/clang-check/CMakeLists.txt +++ b/clang/tools/clang-check/CMakeLists.txt @@ -12,6 +12,7 @@ add_clang_executable(clang-check target_link_libraries(clang-check clangTooling clangBasic + clangRewriteFrontend ) install(TARGETS clang-check diff --git a/clang/tools/clang-check/ClangCheck.cpp b/clang/tools/clang-check/ClangCheck.cpp index daa593a..6c081ac 100644 --- a/clang/tools/clang-check/ClangCheck.cpp +++ b/clang/tools/clang-check/ClangCheck.cpp @@ -7,8 +7,8 @@ // //===----------------------------------------------------------------------===// // -// This file implements a clang-check tool that runs the -// clang::SyntaxOnlyAction over a number of translation units. +// This file implements a clang-check tool that runs clang based on the info +// stored in a compilation database. // // This tool uses the Clang Tooling infrastructure, see // http://clang.llvm.org/docs/HowToSetupToolingForLLVM.html @@ -20,9 +20,13 @@ #include "clang/Driver/OptTable.h" #include "clang/Driver/Options.h" #include "clang/Frontend/ASTConsumers.h" +#include "clang/Frontend/CompilerInstance.h" +#include "clang/Rewrite/Frontend/FixItRewriter.h" +#include "clang/Rewrite/Frontend/FrontendActions.h" #include "clang/Tooling/CommonOptionsParser.h" #include "clang/Tooling/Tooling.h" #include "llvm/Support/CommandLine.h" +#include "llvm/Support/Path.h" using namespace clang::driver; using namespace clang::tooling; @@ -58,6 +62,68 @@ static cl::opt ASTDumpFilter( "ast-dump-filter", cl::desc(Options->getOptionHelpText(options::OPT_ast_dump_filter))); +static cl::opt Fixit( + "fixit", + cl::desc(Options->getOptionHelpText(options::OPT_fixit))); +static cl::opt FixWhatYouCan( + "fix-what-you-can", + cl::desc(Options->getOptionHelpText(options::OPT_fix_what_you_can))); + +namespace { + +// FIXME: Move FixItRewriteInPlace from lib/Rewrite/Frontend/FrontendActions.cpp +// into a header file and reuse that. +class FixItOptions : public clang::FixItOptions { +public: + FixItOptions() { + FixWhatYouCan = ::FixWhatYouCan; + } + + std::string RewriteFilename(const std::string& filename, int &fd) { + assert(llvm::sys::path::is_absolute(filename) && + "clang-fixit expects absolute paths only."); + + // We don't need to do permission checking here since clang will diagnose + // any I/O errors itself. + + fd = -1; // No file descriptor for file. + + return filename; + } +}; + +/// \brief Subclasses \c clang::FixItRewriter to not count fixed errors/warnings +/// in the final error counts. +/// +/// This has the side-effect that clang-check -fixit exits with code 0 on +/// successfully fixing all errors. +class FixItRewriter : public clang::FixItRewriter { +public: + FixItRewriter(clang::DiagnosticsEngine& Diags, + clang::SourceManager& SourceMgr, + const clang::LangOptions& LangOpts, + clang::FixItOptions* FixItOpts) + : clang::FixItRewriter(Diags, SourceMgr, LangOpts, FixItOpts) { + } + + virtual bool IncludeInDiagnosticCounts() const { return false; } +}; + +/// \brief Subclasses \c clang::FixItAction so that we can install the custom +/// \c FixItRewriter. +class FixItAction : public clang::FixItAction { +public: + virtual bool BeginSourceFileAction(clang::CompilerInstance& CI, + StringRef Filename) { + FixItOpts.reset(new FixItOptions); + Rewriter.reset(new FixItRewriter(CI.getDiagnostics(), CI.getSourceManager(), + CI.getLangOpts(), FixItOpts.get())); + return true; + } +}; + +} // namespace + // Anonymous namespace here causes problems with gcc <= 4.4 on MacOS 10.6. // "Non-global symbol: ... can't be a weak_definition" namespace clang_check { @@ -76,9 +142,11 @@ public: } int main(int argc, const char **argv) { - clang_check::ClangCheckActionFactory Factory; CommonOptionsParser OptionsParser(argc, argv); ClangTool Tool(OptionsParser.GetCompilations(), OptionsParser.GetSourcePathList()); + if (Fixit) + return Tool.run(newFrontendActionFactory()); + clang_check::ClangCheckActionFactory Factory; return Tool.run(newFrontendActionFactory(&Factory)); } diff --git a/clang/tools/clang-check/Makefile b/clang/tools/clang-check/Makefile index 6775c65..4262300 100644 --- a/clang/tools/clang-check/Makefile +++ b/clang/tools/clang-check/Makefile @@ -18,7 +18,7 @@ include $(CLANG_LEVEL)/../../Makefile.config LINK_COMPONENTS := $(TARGETS_TO_BUILD) asmparser support mc USEDLIBS = clangFrontend.a clangSerialization.a clangDriver.a \ clangTooling.a clangParse.a clangSema.a clangAnalysis.a \ - clangEdit.a clangAST.a clangLex.a clangBasic.a + clangEdit.a clangAST.a clangLex.a clangBasic.a \ + clangRewriteFrontend.a include $(CLANG_LEVEL)/Makefile - -- 2.7.4