Skip to content

Commit 84f137a

Browse files
committed
Reland "enable plugins for clang-tidy"
This reverts commit ab3b898 but disables the new test if the user has disabled support for building it.
1 parent d5ce90f commit 84f137a

File tree

9 files changed

+142
-2
lines changed

9 files changed

+142
-2
lines changed

clang-tools-extra/clang-tidy/tool/CMakeLists.txt

+11-2
Original file line numberDiff line numberDiff line change
@@ -29,11 +29,17 @@ clang_target_link_libraries(clangTidyMain
2929
clangToolingCore
3030
)
3131

32+
# Support plugins.
33+
if(CLANG_PLUGIN_SUPPORT)
34+
set(support_plugins SUPPORT_PLUGINS)
35+
endif()
36+
3237
add_clang_tool(clang-tidy
3338
ClangTidyToolMain.cpp
34-
)
35-
add_dependencies(clang-tidy
39+
40+
DEPENDS
3641
clang-resource-headers
42+
${support_plugins}
3743
)
3844
clang_target_link_libraries(clang-tidy
3945
PRIVATE
@@ -50,6 +56,9 @@ target_link_libraries(clang-tidy
5056
${ALL_CLANG_TIDY_CHECKS}
5157
)
5258

59+
if(CLANG_PLUGIN_SUPPORT)
60+
export_executable_symbols_for_plugins(clang-tidy)
61+
endif()
5362

5463
install(PROGRAMS clang-tidy-diff.py
5564
DESTINATION "${CMAKE_INSTALL_DATADIR}/clang"

clang-tools-extra/clang-tidy/tool/ClangTidyMain.cpp

+6
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
#include "../GlobList.h"
2121
#include "clang/Tooling/CommonOptionsParser.h"
2222
#include "llvm/Support/InitLLVM.h"
23+
#include "llvm/Support/PluginLoader.h"
2324
#include "llvm/Support/Process.h"
2425
#include "llvm/Support/Signals.h"
2526
#include "llvm/Support/TargetSelect.h"
@@ -386,6 +387,11 @@ getVfsFromFile(const std::string &OverlayFile,
386387

387388
int clangTidyMain(int argc, const char **argv) {
388389
llvm::InitLLVM X(argc, argv);
390+
391+
// Enable help for -load option, if plugins are enabled.
392+
if (cl::Option *LoadOpt = cl::getRegisteredOptions().lookup("load"))
393+
LoadOpt->addCategory(ClangTidyCategory);
394+
389395
llvm::Expected<CommonOptionsParser> OptionsParser =
390396
CommonOptionsParser::create(argc, argv, ClangTidyCategory,
391397
cl::ZeroOrMore);

clang-tools-extra/docs/ReleaseNotes.rst

+2
Original file line numberDiff line numberDiff line change
@@ -207,6 +207,8 @@ Improvements to clang-tidy
207207
- Added support for `NOLINTBEGIN` ... `NOLINTEND` comments to suppress
208208
Clang-Tidy warnings over multiple lines.
209209

210+
- Added support for external plugin checks with `-load`.
211+
210212
New checks
211213
^^^^^^^^^^
212214

clang-tools-extra/docs/clang-tidy/Contributing.rst

+20
Original file line numberDiff line numberDiff line change
@@ -634,6 +634,26 @@ This keeps the test directory from getting cluttered.
634634
.. _FileCheck: https://llvm.org/docs/CommandGuide/FileCheck.html
635635
.. _test/clang-tidy/google-readability-casting.cpp: https://reviews.llvm.org/diffusion/L/browse/clang-tools-extra/trunk/test/clang-tidy/google-readability-casting.cpp
636636

637+
Out-of-tree check plugins
638+
-------------------------
639+
640+
Developing an out-of-tree check as a plugin largely follows the steps
641+
outlined above. The plugin is a shared library whose code lives outside
642+
the clang-tidy build system. Build and link this shared library against
643+
LLVM as done for other kinds of Clang plugins.
644+
645+
The plugin can be loaded by passing `-load` to `clang-tidy` in addition to the
646+
names of the checks to enable.
647+
648+
.. code-block:: console
649+
650+
$ clang-tidy --checks=-*,my-explicit-constructor -list-checks -load myplugin.so
651+
652+
There is no expectations regarding ABI and API stability, so the plugin must be
653+
compiled against the version of clang-tidy that will be loading the plugin.
654+
655+
The plugins can use threads, TLS, or any other facilities available to in-tree
656+
code which is accessible from the external headers.
637657

638658
Running clang-tidy on LLVM
639659
--------------------------

clang-tools-extra/docs/clang-tidy/index.rst

+9
Original file line numberDiff line numberDiff line change
@@ -218,6 +218,15 @@ An overview of all the command-line options:
218218
--list-checks -
219219
List all enabled checks and exit. Use with
220220
-checks=* to list all available checks.
221+
-load=<plugin> -
222+
Load the dynamic object ``plugin``. This
223+
object should register new static analyzer
224+
or clang-tidy passes. Once loaded, the
225+
object will add new command line options
226+
to run various analyses. To see the new
227+
complete list of passes, use the
228+
:option:`--list-checks` and
229+
:option:`-load` options together.
221230
-p=<string> - Build path
222231
--quiet -
223232
Run clang-tidy in quiet mode. This suppresses

clang-tools-extra/test/CMakeLists.txt

+20
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@ string(REPLACE ${CMAKE_CFG_INTDIR} ${LLVM_BUILD_MODE} CLANG_TOOLS_DIR ${LLVM_RUN
1717

1818
llvm_canonicalize_cmake_booleans(
1919
CLANG_TIDY_ENABLE_STATIC_ANALYZER
20+
LLVM_ENABLE_PLUGINS
21+
LLVM_INSTALL_TOOLCHAIN_ONLY
2022
)
2123

2224
configure_lit_site_cfg(
@@ -78,6 +80,24 @@ foreach(dep ${LLVM_UTILS_DEPS})
7880
endif()
7981
endforeach()
8082

83+
if (NOT LLVM_INSTALL_TOOLCHAIN_ONLY)
84+
llvm_add_library(
85+
CTTestTidyModule
86+
MODULE clang-tidy/CTTestTidyModule.cpp
87+
PLUGIN_TOOL clang-tidy
88+
DEPENDS clang-tidy-headers)
89+
90+
if(TARGET CTTestTidyModule)
91+
list(APPEND CLANG_TOOLS_TEST_DEPS CTTestTidyModule LLVMHello)
92+
target_include_directories(CTTestTidyModule PUBLIC BEFORE "${CLANG_TOOLS_SOURCE_DIR}")
93+
if(LLVM_ENABLE_PLUGINS AND (WIN32 OR CYGWIN))
94+
set(LLVM_LINK_COMPONENTS
95+
Support
96+
)
97+
endif()
98+
endif()
99+
endif()
100+
81101
add_lit_testsuite(check-clang-tools "Running the Clang extra tools' regression tests"
82102
${CMAKE_CURRENT_BINARY_DIR}
83103
DEPENDS ${CLANG_TOOLS_TEST_DEPS}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
// REQUIRES: plugins
2+
// RUN: clang-tidy -checks='-*,mytest*' --list-checks -load %llvmshlibdir/CTTestTidyModule%pluginext -load %llvmshlibdir/LLVMHello%pluginext | FileCheck --check-prefix=CHECK-LIST %s
3+
// CHECK-LIST: Enabled checks:
4+
// CHECK-LIST-NEXT: mytest1
5+
// CHECK-LIST-NEXT: mytest2
6+
// RUN: clang-tidy -checks='-*,mytest*,misc-definitions-in-headers' -load %llvmshlibdir/CTTestTidyModule%pluginext /dev/null -- -xc 2>&1 | FileCheck %s
7+
// CHECK: 3 warnings generated.
8+
// CHECK-NEXT: warning: mytest success [misc-definitions-in-headers,mytest1,mytest2]
9+
10+
#include "clang-tidy/ClangTidy.h"
11+
#include "clang-tidy/ClangTidyCheck.h"
12+
#include "clang-tidy/ClangTidyModule.h"
13+
#include "clang-tidy/ClangTidyModuleRegistry.h"
14+
#include "clang/AST/ASTContext.h"
15+
#include "clang/ASTMatchers/ASTMatchFinder.h"
16+
17+
using namespace clang;
18+
using namespace clang::tidy;
19+
using namespace clang::ast_matchers;
20+
21+
namespace {
22+
class MyTestCheck : public ClangTidyCheck {
23+
24+
public:
25+
MyTestCheck(StringRef Name, ClangTidyContext *Context)
26+
: ClangTidyCheck(Name, Context) {}
27+
28+
void registerMatchers(ast_matchers::MatchFinder *Finder) override {
29+
Finder->addMatcher(translationUnitDecl().bind("tu"), this);
30+
}
31+
32+
void check(const ast_matchers::MatchFinder::MatchResult &Result) override {
33+
auto S = Result.Nodes.getNodeAs<TranslationUnitDecl>("tu");
34+
if (S)
35+
diag("mytest success");
36+
}
37+
38+
private:
39+
};
40+
41+
class CTTestModule : public ClangTidyModule {
42+
public:
43+
void addCheckFactories(ClangTidyCheckFactories &CheckFactories) override {
44+
CheckFactories.registerCheck<MyTestCheck>("mytest1");
45+
CheckFactories.registerCheck<MyTestCheck>("mytest2");
46+
// intentionally collide with an existing test name, overriding it
47+
CheckFactories.registerCheck<MyTestCheck>("misc-definitions-in-headers");
48+
}
49+
};
50+
} // namespace
51+
52+
namespace tidy1 {
53+
// Register the CTTestTidyModule using this statically initialized variable.
54+
static ClangTidyModuleRegistry::Add<::CTTestModule>
55+
X("mytest-module", "Adds my checks.");
56+
} // namespace tidy1
57+
58+
namespace tidy2 {
59+
// intentionally collide with an existing test group name, merging with it
60+
static ClangTidyModuleRegistry::Add<::CTTestModule>
61+
X("misc-module", "Adds miscellaneous lint checks.");
62+
} // namespace tidy2
63+
64+
// This anchor is used to force the linker to link in the generated object file
65+
// and thus register the CTTestModule.
66+
volatile int CTTestModuleAnchorSource = 0;

clang-tools-extra/test/lit.cfg.py

+6
Original file line numberDiff line numberDiff line change
@@ -149,3 +149,9 @@
149149
"clangd", "benchmarks")
150150
config.substitutions.append(('%clangd-benchmark-dir',
151151
'%s' % (clangd_benchmarks_dir)))
152+
config.substitutions.append(('%llvmshlibdir', config.clang_libs_dir))
153+
config.substitutions.append(('%pluginext', config.llvm_plugin_ext))
154+
155+
# Plugins (loadable modules)
156+
if config.has_plugins and config.llvm_plugin_ext:
157+
config.available_features.add('plugins')

clang-tools-extra/test/lit.site.cfg.py.in

+2
Original file line numberDiff line numberDiff line change
@@ -4,13 +4,15 @@ import sys
44

55
config.llvm_tools_dir = "@LLVM_TOOLS_DIR@"
66
config.llvm_libs_dir = "@LLVM_LIBS_DIR@"
7+
config.llvm_plugin_ext = "@LLVM_PLUGIN_EXT@"
78
config.lit_tools_dir = "@LLVM_LIT_TOOLS_DIR@"
89
config.clang_tools_binary_dir = "@CLANG_TOOLS_BINARY_DIR@"
910
config.clang_tools_dir = "@CLANG_TOOLS_DIR@"
1011
config.clang_libs_dir = "@SHLIBDIR@"
1112
config.python_executable = "@Python3_EXECUTABLE@"
1213
config.target_triple = "@TARGET_TRIPLE@"
1314
config.clang_tidy_staticanalyzer = @CLANG_TIDY_ENABLE_STATIC_ANALYZER@
15+
config.has_plugins = @LLVM_ENABLE_PLUGINS@ & ~@LLVM_INSTALL_TOOLCHAIN_ONLY@
1416

1517
# Support substitution of the tools and libs dirs with user parameters. This is
1618
# used when we can't determine the tool dir at configuration time.

0 commit comments

Comments
 (0)