diff --git a/clang/include/clang/ASTMatchers/Dynamic/Registry.h b/clang/include/clang/ASTMatchers/Dynamic/Registry.h index 215206b2f50cd7..9ce77c33d6d8db 100644 --- a/clang/include/clang/ASTMatchers/Dynamic/Registry.h +++ b/clang/include/clang/ASTMatchers/Dynamic/Registry.h @@ -66,6 +66,8 @@ class Registry { public: Registry() = delete; + static ASTNodeKind nodeMatcherType(MatcherCtor); + /// Look up a matcher in the registry by name, /// /// \return An opaque value which may be used to refer to the matcher diff --git a/clang/lib/ASTMatchers/Dynamic/Marshallers.h b/clang/lib/ASTMatchers/Dynamic/Marshallers.h index 411062392dad80..71d7443c91cae5 100644 --- a/clang/lib/ASTMatchers/Dynamic/Marshallers.h +++ b/clang/lib/ASTMatchers/Dynamic/Marshallers.h @@ -309,6 +309,8 @@ class MatcherDescriptor { ArrayRef Args, Diagnostics *Error) const = 0; + virtual ASTNodeKind nodeMatcherType() const { return ASTNodeKind(); } + /// Returns whether the matcher is variadic. Variadic matchers can take any /// number of arguments, but they must be of the same type. virtual bool isVariadic() const = 0; @@ -576,6 +578,8 @@ class VariadicFuncMatcherDescriptor : public MatcherDescriptor { LeastDerivedKind); } + ASTNodeKind nodeMatcherType() const override { return RetKinds[0]; } + private: const RunFunc Func; const std::string MatcherName; @@ -611,6 +615,8 @@ class DynCastAllOfMatcherDescriptor : public VariadicFuncMatcherDescriptor { } } + ASTNodeKind nodeMatcherType() const override { return DerivedKind; } + private: const ASTNodeKind DerivedKind; }; diff --git a/clang/lib/ASTMatchers/Dynamic/Registry.cpp b/clang/lib/ASTMatchers/Dynamic/Registry.cpp index 0887eb7e0881df..908a9ee8ae62f7 100644 --- a/clang/lib/ASTMatchers/Dynamic/Registry.cpp +++ b/clang/lib/ASTMatchers/Dynamic/Registry.cpp @@ -562,6 +562,10 @@ RegistryMaps::~RegistryMaps() = default; static llvm::ManagedStatic RegistryData; +ASTNodeKind Registry::nodeMatcherType(MatcherCtor Ctor) { + return Ctor->nodeMatcherType(); +} + // static llvm::Optional Registry::lookupMatcherCtor(StringRef MatcherName) { auto it = RegistryData->constructors().find(MatcherName); diff --git a/clang/unittests/ASTMatchers/Dynamic/RegistryTest.cpp b/clang/unittests/ASTMatchers/Dynamic/RegistryTest.cpp index 7d6c51f965ec6b..386fd523bb247b 100644 --- a/clang/unittests/ASTMatchers/Dynamic/RegistryTest.cpp +++ b/clang/unittests/ASTMatchers/Dynamic/RegistryTest.cpp @@ -497,6 +497,12 @@ TEST_F(RegistryTest, Completion) { "Matcher isSameOrDerivedFrom(string|Matcher)")); } +TEST_F(RegistryTest, NodeType) { + EXPECT_TRUE(Registry::nodeMatcherType(*lookupMatcherCtor("callExpr")).isSame(ASTNodeKind::getFromNodeKind())); + EXPECT_TRUE(Registry::nodeMatcherType(*lookupMatcherCtor("has")).isNone()); + EXPECT_TRUE(Registry::nodeMatcherType(*lookupMatcherCtor("allOf")).isNone()); +} + TEST_F(RegistryTest, HasArgs) { Matcher Value = constructMatcher( "decl", constructMatcher("hasAttr", StringRef("attr::WarnUnused")))