https://github.com/zeyi2 updated https://github.com/llvm/llvm-project/pull/221961
>From ad2515a915fc57525fa27d633495e6927d367bff Mon Sep 17 00:00:00 2001 From: Zeyi Xu <[email protected]> Date: Tue, 8 Sep 2026 19:09:29 +0800 Subject: [PATCH 1/3] [clang-tidy] Fix loading clang-tidy as a Clang frontend plugin --- .../clang-tidy/plugin/CMakeLists.txt | 10 +++++++++- .../clang-tidy/plugin/ClangTidyPlugin.cpp | 20 ++++++++++++------- .../clang-tidy/plugin/ClangTidyPlugin.exports | 1 + clang-tools-extra/docs/ReleaseNotes.md | 3 +++ clang-tools-extra/test/CMakeLists.txt | 10 ++++++++++ .../infrastructure/clang-plugin-analyzer.cpp | 8 ++++++++ .../infrastructure/clang-plugin.cpp | 14 +++++++++++++ clang-tools-extra/test/lit.cfg.py | 2 ++ clang-tools-extra/test/lit.site.cfg.py.in | 1 + 9 files changed, 61 insertions(+), 8 deletions(-) create mode 100644 clang-tools-extra/clang-tidy/plugin/ClangTidyPlugin.exports create mode 100644 clang-tools-extra/test/clang-tidy/infrastructure/clang-plugin-analyzer.cpp create mode 100644 clang-tools-extra/test/clang-tidy/infrastructure/clang-plugin.cpp diff --git a/clang-tools-extra/clang-tidy/plugin/CMakeLists.txt b/clang-tools-extra/clang-tidy/plugin/CMakeLists.txt index aff2018b693b1..899c9fb057c52 100644 --- a/clang-tools-extra/clang-tidy/plugin/CMakeLists.txt +++ b/clang-tools-extra/clang-tidy/plugin/CMakeLists.txt @@ -1,6 +1,14 @@ -add_clang_library(clangTidyPlugin STATIC +if(NOT CLANG_PLUGIN_SUPPORT OR NOT CLANG_LINK_CLANG_DYLIB OR + NOT LLVM_LINK_LLVM_DYLIB) + return() +endif() + +set(LLVM_EXPORTED_SYMBOL_FILE ${CMAKE_CURRENT_SOURCE_DIR}/ClangTidyPlugin.exports) +add_llvm_library(clangTidyPlugin MODULE ClangTidyPlugin.cpp + PLUGIN_TOOL clang + LINK_LIBS clangTidy ${ALL_CLANG_TIDY_CHECKS} diff --git a/clang-tools-extra/clang-tidy/plugin/ClangTidyPlugin.cpp b/clang-tools-extra/clang-tidy/plugin/ClangTidyPlugin.cpp index 4431333906f7b..87869a3af4b94 100644 --- a/clang-tools-extra/clang-tidy/plugin/ClangTidyPlugin.cpp +++ b/clang-tools-extra/clang-tidy/plugin/ClangTidyPlugin.cpp @@ -8,10 +8,16 @@ #include "../ClangTidy.h" #include "../ClangTidyDiagnosticConsumer.h" +#include "../ClangTidyForceLinker.h" // IWYU pragma: keep #include "../ClangTidyModule.h" #include "clang/Frontend/CompilerInstance.h" #include "clang/Frontend/FrontendPluginRegistry.h" #include "clang/Frontend/MultiplexConsumer.h" +#include "clang/StaticAnalyzer/Frontend/CheckerRegistry.h" + +// NOLINTNEXTLINE(readability-identifier-naming) +extern "C" const char clang_analyzerAPIVersionString[] = + CLANG_ANALYZER_API_VERSION_STRING; namespace clang::tidy { namespace { @@ -32,6 +38,8 @@ class ClangTidyPluginAction : public PluginASTAction { std::vector<std::unique_ptr<ASTConsumer>> Consumer) : MultiplexConsumer(std::move(Consumer)), Context(std::move(Context)), DiagEngine(std::move(DiagEngine)) {} + + ~WrapConsumer() override { DiagEngine->getClient()->EndSourceFile(); } }; public: @@ -44,6 +52,8 @@ class ClangTidyPluginAction : public PluginASTAction { auto DiagEngine = std::make_unique<DiagnosticsEngine>( DiagnosticIDs::create(), *DiagOpts, DiagConsumer); Context->setDiagnosticsEngine(std::move(DiagOpts), DiagEngine.get()); + DiagConsumer->BeginSourceFile(Compiler.getLangOpts(), + &Compiler.getPreprocessor()); // Create the AST consumer. ClangTidyASTConsumerFactory Factory(*Context); @@ -54,7 +64,7 @@ class ClangTidyPluginAction : public PluginASTAction { std::move(Context), std::move(DiagEngine), std::move(Vec)); } - bool ParseArgs(const CompilerInstance &, + bool ParseArgs(const CompilerInstance &Compiler, const std::vector<std::string> &Args) override { const ClangTidyGlobalOptions GlobalOptions; const ClangTidyOptions DefaultOptions; @@ -67,7 +77,8 @@ class ClangTidyPluginAction : public PluginASTAction { OverrideOptions.Checks = std::string(Arg.substr(strlen("-checks="))); auto Options = std::make_unique<FileOptionsProvider>( - GlobalOptions, DefaultOptions, OverrideOptions); + GlobalOptions, DefaultOptions, OverrideOptions, + Compiler.getVirtualFileSystemPtr()); Context = std::make_unique<ClangTidyContext>(std::move(Options)); return true; } @@ -79,10 +90,5 @@ class ClangTidyPluginAction : public PluginASTAction { } // namespace } // namespace clang::tidy -// This anchor is used to force the linker to link in the generated object file -// and thus register the clang-tidy plugin. -// NOLINTNEXTLINE(misc-use-internal-linkage) -volatile int ClangTidyPluginAnchorSource = 0; - static clang::FrontendPluginRegistry::Add<clang::tidy::ClangTidyPluginAction> X("clang-tidy", "clang-tidy"); diff --git a/clang-tools-extra/clang-tidy/plugin/ClangTidyPlugin.exports b/clang-tools-extra/clang-tidy/plugin/ClangTidyPlugin.exports new file mode 100644 index 0000000000000..b5289dac3fca8 --- /dev/null +++ b/clang-tools-extra/clang-tidy/plugin/ClangTidyPlugin.exports @@ -0,0 +1 @@ +clang_analyzerAPIVersionString diff --git a/clang-tools-extra/docs/ReleaseNotes.md b/clang-tools-extra/docs/ReleaseNotes.md index 70dd45eb3297c..6d9bc92ffe7e2 100644 --- a/clang-tools-extra/docs/ReleaseNotes.md +++ b/clang-tools-extra/docs/ReleaseNotes.md @@ -96,6 +96,9 @@ infrastructure are described first, followed by tool-specific sections. ### Improvements to clang-tidy +- Improved clang-tidy by fixing its use as a Clang plugin, allowing checks to + run during normal compilation when Clang and LLVM are built as shared libraries. + - Improved {program}`check_clang_tidy.py` by adding support of `-std=cXX-or-earlier` values, mirroring the existing `-std=cXX-or-later`. New construct expands to the given standard and every earlier one. diff --git a/clang-tools-extra/test/CMakeLists.txt b/clang-tools-extra/test/CMakeLists.txt index 22f227a891f82..e94879b655643 100644 --- a/clang-tools-extra/test/CMakeLists.txt +++ b/clang-tools-extra/test/CMakeLists.txt @@ -7,10 +7,16 @@ set(CLANG_TOOLS_SOURCE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/..") set(CLANG_TOOLS_BINARY_DIR "${CMAKE_CURRENT_BINARY_DIR}/..") +set(CLANG_TIDY_PLUGIN_AVAILABLE OFF) +if(TARGET clangTidyPlugin) + set(CLANG_TIDY_PLUGIN_AVAILABLE ON) +endif() + llvm_canonicalize_cmake_booleans( CLANG_TIDY_ENABLE_STATIC_ANALYZER CLANG_TIDY_ENABLE_QUERY_BASED_CUSTOM_CHECKS CLANG_PLUGIN_SUPPORT + CLANG_TIDY_PLUGIN_AVAILABLE LLVM_INSTALL_TOOLCHAIN_ONLY ) @@ -76,6 +82,10 @@ if(TARGET CTTestTidyModule) endif() endif() +if(TARGET clangTidyPlugin) + list(APPEND CLANG_TOOLS_TEST_DEPS clangTidyPlugin) +endif() + add_lit_testsuite(check-clang-extra "Running clang-tools-extra/test" ${CMAKE_CURRENT_BINARY_DIR} DEPENDS ${CLANG_TOOLS_TEST_DEPS} diff --git a/clang-tools-extra/test/clang-tidy/infrastructure/clang-plugin-analyzer.cpp b/clang-tools-extra/test/clang-tidy/infrastructure/clang-plugin-analyzer.cpp new file mode 100644 index 0000000000000..347ac29d3e53d --- /dev/null +++ b/clang-tools-extra/test/clang-tidy/infrastructure/clang-plugin-analyzer.cpp @@ -0,0 +1,8 @@ +// REQUIRES: clang-plugin, static-analyzer +// RUN: %clang_cc1 -load %llvmshlibdir/clangTidyPlugin%pluginext -add-plugin clang-tidy -plugin-arg-clang-tidy -checks=-*,clang-analyzer-core.DivideZero %s -verify + +int divide() { + return 1 / 0; // expected-warning {{division by zero is undefined}} + // expected-warning@-1 {{Division by zero [clang-analyzer-core.DivideZero]}} + // expected-note@-2 {{Division by zero}} +} diff --git a/clang-tools-extra/test/clang-tidy/infrastructure/clang-plugin.cpp b/clang-tools-extra/test/clang-tidy/infrastructure/clang-plugin.cpp new file mode 100644 index 0000000000000..e946f9379ae5e --- /dev/null +++ b/clang-tools-extra/test/clang-tidy/infrastructure/clang-plugin.cpp @@ -0,0 +1,14 @@ +// REQUIRES: clang-plugin +// RUN: %clang_cc1 -load %llvmshlibdir/clangTidyPlugin%pluginext -add-plugin clang-tidy -plugin-arg-clang-tidy -checks=-*,modernize-use-nullptr,bugprone-narrowing-conversions %s -std=c++11 -verify +// RUN: %clang -Xclang -load -Xclang %llvmshlibdir/clangTidyPlugin%pluginext -Xclang -add-plugin -Xclang clang-tidy -Xclang -plugin-arg-clang-tidy -Xclang -checks=-*,modernize-use-nullptr,bugprone-narrowing-conversions -Xclang -verify %s -std=c++11 -S -emit-llvm -o - | FileCheck %s +// RUN: %clang_cc1 -load %llvmshlibdir/clangTidyPlugin%pluginext -add-plugin clang-tidy -plugin-arg-clang-tidy -checks=-* %s -std=c++11 -verify=disabled +// disabled-no-diagnostics + +extern "C" { +int *p = 0; // expected-warning {{use nullptr [modernize-use-nullptr]}} +} +// CHECK: @p = {{.*}}global ptr null + +int narrow(double value) { + return value; // expected-warning {{narrowing conversion from 'double' to 'int' [bugprone-narrowing-conversions]}} +} diff --git a/clang-tools-extra/test/lit.cfg.py b/clang-tools-extra/test/lit.cfg.py index be484b4ff217d..28c6b9bbfbd84 100644 --- a/clang-tools-extra/test/lit.cfg.py +++ b/clang-tools-extra/test/lit.cfg.py @@ -76,6 +76,8 @@ # Plugins (loadable modules) if config.has_plugins and config.llvm_plugin_ext: config.available_features.add("plugins") +if config.has_clang_tidy_plugin: + config.available_features.add("clang-plugin") # It is not realistically possible to account for all options that could # possibly be present in system and user configuration files, so disable diff --git a/clang-tools-extra/test/lit.site.cfg.py.in b/clang-tools-extra/test/lit.site.cfg.py.in index 152ea6be2771c..03535a9ae770e 100644 --- a/clang-tools-extra/test/lit.site.cfg.py.in +++ b/clang-tools-extra/test/lit.site.cfg.py.in @@ -12,6 +12,7 @@ config.host_triple = "@LLVM_HOST_TRIPLE@" config.clang_tidy_staticanalyzer = @CLANG_TIDY_ENABLE_STATIC_ANALYZER@ config.clang_tidy_custom_check = @CLANG_TIDY_ENABLE_QUERY_BASED_CUSTOM_CHECKS@ config.has_plugins = @CLANG_PLUGIN_SUPPORT@ +config.has_clang_tidy_plugin = @CLANG_TIDY_PLUGIN_AVAILABLE@ # Support substitution of the tools and libs dirs with user parameters. This is # used when we can't determine the tool dir at configuration time. config.llvm_tools_dir = lit_config.substitute("@LLVM_TOOLS_DIR@") >From 50b42f202c13ad44b29d3074e051d6c76498e087 Mon Sep 17 00:00:00 2001 From: Zeyi Xu <[email protected]> Date: Wed, 9 Sep 2026 00:50:59 +0800 Subject: [PATCH 2/3] Update clang-tools-extra/docs/ReleaseNotes.md Co-authored-by: EugeneZelenko <[email protected]> --- clang-tools-extra/docs/ReleaseNotes.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clang-tools-extra/docs/ReleaseNotes.md b/clang-tools-extra/docs/ReleaseNotes.md index 6d9bc92ffe7e2..1397e1ec5b468 100644 --- a/clang-tools-extra/docs/ReleaseNotes.md +++ b/clang-tools-extra/docs/ReleaseNotes.md @@ -96,7 +96,7 @@ infrastructure are described first, followed by tool-specific sections. ### Improvements to clang-tidy -- Improved clang-tidy by fixing its use as a Clang plugin, allowing checks to +- Improved {program}`clang-tidy` by fixing its use as a Clang plugin, allowing checks to run during normal compilation when Clang and LLVM are built as shared libraries. - Improved {program}`check_clang_tidy.py` by adding support of >From ce5761c1646a88b3c2af8b02e4848619d7e93ee6 Mon Sep 17 00:00:00 2001 From: Zeyi Xu <[email protected]> Date: Wed, 9 Sep 2026 18:43:49 +0800 Subject: [PATCH 3/3] disable plugin support on Windows --- clang-tools-extra/clang-tidy/plugin/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clang-tools-extra/clang-tidy/plugin/CMakeLists.txt b/clang-tools-extra/clang-tidy/plugin/CMakeLists.txt index 899c9fb057c52..199566d7b6436 100644 --- a/clang-tools-extra/clang-tidy/plugin/CMakeLists.txt +++ b/clang-tools-extra/clang-tidy/plugin/CMakeLists.txt @@ -1,4 +1,4 @@ -if(NOT CLANG_PLUGIN_SUPPORT OR NOT CLANG_LINK_CLANG_DYLIB OR +if(WIN32 OR NOT CLANG_PLUGIN_SUPPORT OR NOT CLANG_LINK_CLANG_DYLIB OR NOT LLVM_LINK_LLVM_DYLIB) return() endif() _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
