[clang] 45e210d - [ASTMatchers] Make it possible to build mapAnyOf through the registry
Stephen Kelly via cfe-commits
cfe-commits at lists.llvm.org
Sun Feb 7 07:37:26 PST 2021
Author: Stephen Kelly
Date: 2021-02-07T15:36:15Z
New Revision: 45e210dbebfae916b213e52be15c276032aeb60d
URL: https://github.com/llvm/llvm-project/commit/45e210dbebfae916b213e52be15c276032aeb60d
DIFF: https://github.com/llvm/llvm-project/commit/45e210dbebfae916b213e52be15c276032aeb60d.diff
LOG: [ASTMatchers] Make it possible to build mapAnyOf through the registry
Added:
Modified:
clang/include/clang/ASTMatchers/Dynamic/Registry.h
clang/lib/ASTMatchers/Dynamic/Marshallers.h
clang/lib/ASTMatchers/Dynamic/Registry.cpp
clang/unittests/ASTMatchers/Dynamic/RegistryTest.cpp
Removed:
################################################################################
diff --git a/clang/include/clang/ASTMatchers/Dynamic/Registry.h b/clang/include/clang/ASTMatchers/Dynamic/Registry.h
index 9ce77c33d6d8..f91f5fe01c4e 100644
--- a/clang/include/clang/ASTMatchers/Dynamic/Registry.h
+++ b/clang/include/clang/ASTMatchers/Dynamic/Registry.h
@@ -33,6 +33,23 @@ namespace internal {
class MatcherDescriptor;
+/// A smart (owning) pointer for MatcherDescriptor. We can't use unique_ptr
+/// because MatcherDescriptor is forward declared
+class MatcherDescriptorPtr {
+public:
+ explicit MatcherDescriptorPtr(MatcherDescriptor *);
+ ~MatcherDescriptorPtr();
+ MatcherDescriptorPtr(MatcherDescriptorPtr &&) = default;
+ MatcherDescriptorPtr &operator=(MatcherDescriptorPtr &&) = default;
+ MatcherDescriptorPtr(const MatcherDescriptorPtr &) = delete;
+ MatcherDescriptorPtr &operator=(const MatcherDescriptorPtr &) = delete;
+
+ MatcherDescriptor *get() { return Ptr; }
+
+private:
+ MatcherDescriptor *Ptr;
+};
+
} // namespace internal
using MatcherCtor = const internal::MatcherDescriptor *;
@@ -68,6 +85,12 @@ class Registry {
static ASTNodeKind nodeMatcherType(MatcherCtor);
+ static bool isBuilderMatcher(MatcherCtor Ctor);
+
+ static internal::MatcherDescriptorPtr
+ buildMatcherCtor(MatcherCtor, SourceRange NameRange,
+ ArrayRef<ParserValue> Args, Diagnostics *Error);
+
/// 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 71d7443c91ca..3ffa0d6af217 100644
--- a/clang/lib/ASTMatchers/Dynamic/Marshallers.h
+++ b/clang/lib/ASTMatchers/Dynamic/Marshallers.h
@@ -311,6 +311,14 @@ class MatcherDescriptor {
virtual ASTNodeKind nodeMatcherType() const { return ASTNodeKind(); }
+ virtual bool isBuilderMatcher() const { return false; }
+
+ virtual std::unique_ptr<MatcherDescriptor>
+ buildMatcherCtor(SourceRange NameRange, ArrayRef<ParserValue> Args,
+ Diagnostics *Error) const {
+ return {};
+ }
+
/// 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;
@@ -996,6 +1004,62 @@ class MapAnyOfMatcherDescriptor : public MatcherDescriptor {
}
};
+class MapAnyOfBuilderDescriptor : public MatcherDescriptor {
+public:
+ VariantMatcher create(SourceRange, ArrayRef<ParserValue>,
+ Diagnostics *) const override {
+ return {};
+ }
+
+ bool isBuilderMatcher() const override { return true; }
+
+ std::unique_ptr<MatcherDescriptor>
+ buildMatcherCtor(SourceRange, ArrayRef<ParserValue> Args,
+ Diagnostics *) const override {
+
+ std::vector<ASTNodeKind> NodeKinds;
+ for (auto Arg : Args) {
+ if (!Arg.Value.isNodeKind())
+ return {};
+ NodeKinds.push_back(Arg.Value.getNodeKind());
+ }
+
+ if (NodeKinds.empty())
+ return {};
+
+ ASTNodeKind CladeNodeKind = NodeKinds.front().getCladeKind();
+
+ for (auto NK : NodeKinds)
+ {
+ if (!NK.getCladeKind().isSame(CladeNodeKind))
+ return {};
+ }
+
+ return std::make_unique<MapAnyOfMatcherDescriptor>(CladeNodeKind,
+ NodeKinds);
+ }
+
+ bool isVariadic() const override { return true; }
+
+ unsigned getNumArgs() const override { return 0; }
+
+ void getArgKinds(ASTNodeKind ThisKind, unsigned,
+ std::vector<ArgKind> &ArgKinds) const override {
+ ArgKinds.push_back(ArgKind::MakeNodeArg(ThisKind));
+ return;
+ }
+ bool isConvertibleTo(ASTNodeKind Kind, unsigned *Specificity = nullptr,
+ ASTNodeKind *LeastDerivedKind = nullptr) const override {
+ if (Specificity)
+ *Specificity = 1;
+ if (LeastDerivedKind)
+ *LeastDerivedKind = Kind;
+ return true;
+ }
+
+ bool isPolymorphic() const override { return false; }
+};
+
/// Helper functions to select the appropriate marshaller functions.
/// They detect the number of arguments, arguments types and return type.
diff --git a/clang/lib/ASTMatchers/Dynamic/Registry.cpp b/clang/lib/ASTMatchers/Dynamic/Registry.cpp
index 908a9ee8ae62..ef5fd64a3666 100644
--- a/clang/lib/ASTMatchers/Dynamic/Registry.cpp
+++ b/clang/lib/ASTMatchers/Dynamic/Registry.cpp
@@ -102,6 +102,9 @@ RegistryMaps::RegistryMaps() {
// Other:
// equalsNode
+ registerMatcher("mapAnyOf",
+ std::make_unique<internal::MapAnyOfBuilderDescriptor>());
+
REGISTER_OVERLOADED_2(callee);
REGISTER_OVERLOADED_2(hasAnyCapture);
REGISTER_OVERLOADED_2(hasPrefix);
@@ -566,6 +569,22 @@ ASTNodeKind Registry::nodeMatcherType(MatcherCtor Ctor) {
return Ctor->nodeMatcherType();
}
+internal::MatcherDescriptorPtr::MatcherDescriptorPtr(MatcherDescriptor *Ptr)
+ : Ptr(Ptr) {}
+
+internal::MatcherDescriptorPtr::~MatcherDescriptorPtr() { delete Ptr; }
+
+bool Registry::isBuilderMatcher(MatcherCtor Ctor) {
+ return Ctor->isBuilderMatcher();
+}
+
+internal::MatcherDescriptorPtr
+Registry::buildMatcherCtor(MatcherCtor Ctor, SourceRange NameRange,
+ ArrayRef<ParserValue> Args, Diagnostics *Error) {
+ return internal::MatcherDescriptorPtr(
+ Ctor->buildMatcherCtor(NameRange, Args, Error).release());
+}
+
// static
llvm::Optional<MatcherCtor> 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 386fd523bb24..a7368d819ccd 100644
--- a/clang/unittests/ASTMatchers/Dynamic/RegistryTest.cpp
+++ b/clang/unittests/ASTMatchers/Dynamic/RegistryTest.cpp
@@ -497,6 +497,20 @@ TEST_F(RegistryTest, Completion) {
"Matcher<CXXRecordDecl> isSameOrDerivedFrom(string|Matcher<NamedDecl>)"));
}
+TEST_F(RegistryTest, MatcherBuilder) {
+ auto Ctor = *lookupMatcherCtor("mapAnyOf");
+ EXPECT_TRUE(Registry::isBuilderMatcher(Ctor));
+ auto BuiltCtor = Registry::buildMatcherCtor(Ctor, {}, Args(ASTNodeKind::getFromNodeKind<WhileStmt>(), ASTNodeKind::getFromNodeKind<ForStmt>()), nullptr);
+ EXPECT_TRUE(BuiltCtor.get());
+ auto LoopMatcher = Registry::constructMatcher(BuiltCtor.get(), SourceRange(), Args(), nullptr).getTypedMatcher<Stmt>();
+ EXPECT_TRUE(matches("void f() { for (;;) {} }", LoopMatcher));
+ EXPECT_TRUE(matches("void f() { while (true) {} }", LoopMatcher));
+ EXPECT_FALSE(matches("void f() { if (true) {} }", LoopMatcher));
+
+ auto NotBuiltCtor = Registry::buildMatcherCtor(Ctor, {}, Args(ASTNodeKind::getFromNodeKind<FunctionDecl>(), ASTNodeKind::getFromNodeKind<ForStmt>()), nullptr);
+ EXPECT_FALSE(NotBuiltCtor.get());
+}
+
TEST_F(RegistryTest, NodeType) {
EXPECT_TRUE(Registry::nodeMatcherType(*lookupMatcherCtor("callExpr")).isSame(ASTNodeKind::getFromNodeKind<CallExpr>()));
EXPECT_TRUE(Registry::nodeMatcherType(*lookupMatcherCtor("has")).isNone());
More information about the cfe-commits
mailing list