mirror of
https://github.com/capstone-engine/llvm-capstone.git
synced 2024-11-30 00:51:02 +00:00
[ASTMatchers] Make it possible to build mapAnyOf through the registry
This commit is contained in:
parent
d3bccdcd50
commit
45e210dbeb
@ -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 @@ public:
|
||||
|
||||
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
|
||||
|
@ -311,6 +311,14 @@ public:
|
||||
|
||||
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 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
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.
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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());
|
||||
|
Loading…
Reference in New Issue
Block a user