Index: clang-tidy/CMakeLists.txt =================================================================== --- clang-tidy/CMakeLists.txt +++ clang-tidy/CMakeLists.txt @@ -2,6 +2,10 @@ Support ) +if(CLANG_PLUGIN_SUPPORT) + set(LLVM_NO_DEAD_STRIP 1) +endif() + add_clang_library(clangTidy ClangTidy.cpp ClangTidyModule.cpp Index: clang-tidy/ClangTidy.cpp =================================================================== --- clang-tidy/ClangTidy.cpp +++ clang-tidy/ClangTidy.cpp @@ -33,6 +33,7 @@ #include "clang/Rewrite/Frontend/FixItRewriter.h" #include "clang/Rewrite/Frontend/FrontendActions.h" #include "clang/StaticAnalyzer/Frontend/AnalysisConsumer.h" +#include "clang/StaticAnalyzer/Frontend/CheckerRegistration.h" #include "clang/Tooling/Refactoring.h" #include "clang/Tooling/ReplacementsYaml.h" #include "clang/Tooling/Tooling.h" @@ -55,14 +56,7 @@ namespace { static const char *AnalyzerCheckNamePrefix = "clang-analyzer-"; -static StringRef StaticAnalyzerChecks[] = { -#define GET_CHECKERS -#define CHECKER(FULLNAME, CLASS, DESCFILE, HELPTEXT, GROUPINDEX, HIDDEN) \ - FULLNAME, -#include "../../../lib/StaticAnalyzer/Checkers/Checkers.inc" -#undef CHECKER -#undef GET_CHECKERS -}; +static std::vector StaticAnalyzerChecks; class AnalyzerDiagnosticConsumer : public ento::PathDiagnosticConsumer { public: @@ -392,6 +386,11 @@ class Action : public ASTFrontendAction { public: Action(ClangTidyASTConsumerFactory *Factory) : Factory(Factory) {} + bool BeginInvocation(CompilerInstance &CI) override { + StaticAnalyzerChecks = + ento::getCheckerList(CI.getFrontendOpts().Plugins); + return true; + } std::unique_ptr CreateASTConsumer(CompilerInstance &Compiler, StringRef File) override { return Factory->CreateASTConsumer(Compiler, File); Index: clang-tidy/tool/CMakeLists.txt =================================================================== --- clang-tidy/tool/CMakeLists.txt +++ clang-tidy/tool/CMakeLists.txt @@ -20,3 +20,6 @@ install(TARGETS clang-tidy RUNTIME DESTINATION bin) +if(CLANG_PLUGIN_SUPPORT) + set_target_properties(clang-tidy PROPERTIES ENABLE_EXPORTS 1) +endif() Index: clang-tidy/tool/ClangTidyMain.cpp =================================================================== --- clang-tidy/tool/ClangTidyMain.cpp +++ clang-tidy/tool/ClangTidyMain.cpp @@ -270,16 +270,6 @@ std::string FileName = OptionsParser.getSourcePathList().front(); ClangTidyOptions EffectiveOptions = OptionsProvider->getOptions(FileName); - std::vector EnabledChecks = getCheckNames(EffectiveOptions); - - // FIXME: Allow using --list-checks without positional arguments. - if (ListChecks) { - llvm::outs() << "Enabled checks:"; - for (auto CheckName : EnabledChecks) - llvm::outs() << "\n " << CheckName; - llvm::outs() << "\n\n"; - return 0; - } if (DumpConfig) { EffectiveOptions.CheckOptions = getCheckOptions(EffectiveOptions); @@ -289,12 +279,6 @@ return 0; } - if (EnabledChecks.empty()) { - llvm::errs() << "Error: no checks enabled.\n"; - llvm::cl::PrintHelpMessage(/*Hidden=*/false, /*Categorized=*/true); - return 1; - } - ProfileData Profile; std::vector Errors; @@ -302,6 +286,24 @@ runClangTidy(std::move(OptionsProvider), OptionsParser.getCompilations(), OptionsParser.getSourcePathList(), &Errors, EnableCheckProfile ? &Profile : nullptr); + + std::vector EnabledChecks = getCheckNames(EffectiveOptions); + + // FIXME: Allow using --list-checks without positional arguments. + if (ListChecks) { + llvm::outs() << "Enabled checks:"; + for (auto CheckName : EnabledChecks) + llvm::outs() << "\n " << CheckName; + llvm::outs() << "\n\n"; + return 0; + } + + if (EnabledChecks.empty()) { + llvm::errs() << "Error: no checks enabled.\n"; + llvm::cl::PrintHelpMessage(/*Hidden=*/false, /*Categorized=*/true); + return 1; + } + bool FoundErrors = std::find_if(Errors.begin(), Errors.end(), [](const ClangTidyError &E) { return E.DiagLevel == ClangTidyError::Error; Index: clang-tidy/tool/Makefile =================================================================== --- clang-tidy/tool/Makefile +++ clang-tidy/tool/Makefile @@ -11,9 +11,12 @@ TOOLNAME = clang-tidy -# No plugins, optimize startup time. -TOOL_NO_EXPORTS = 1 +ifeq ($(CLANG_PLUGIN_SUPPORT), 1) +NO_DEAD_STRIP := 1 +else +TOOL_NO_EXPORTS := 1 +endif include $(CLANG_LEVEL)/../../Makefile.config LINK_COMPONENTS := $(TARGETS_TO_BUILD) asmparser bitreader support mc option USEDLIBS = clangTidy.a clangTidyLLVMModule.a clangTidyGoogleModule.a \ Index: test/clang-tidy/clang-static-analyzer-plugin.cpp =================================================================== --- test/clang-tidy/clang-static-analyzer-plugin.cpp +++ test/clang-tidy/clang-static-analyzer-plugin.cpp @@ -0,0 +1,14 @@ +// RUN: clang-tidy %s -checks='-*,clang-analyzer-example.MainCallChecker' -- -load %llvmshlibdir/SampleAnalyzerPlugin%pluginext | FileCheck %s +// REQUIRES: plugins, examples + +// Test that the MainCallChecker example analyzer plugin loads and runs. + +int main(); + +void caller() { + main(); + // CHECK: warning: call to main +} + +namespace i { +}