Allow using traverse() with bindings

This commit is contained in:
Stephen Kelly 2020-01-05 20:48:20 +00:00
parent 4711512384
commit ad0a45833b
3 changed files with 38 additions and 0 deletions

View File

@ -714,6 +714,17 @@ internal::Matcher<T> traverse(ast_type_traits::TraversalKind TK,
.template unconditionalConvertTo<T>();
}
template <typename T>
internal::BindableMatcher<T>
traverse(ast_type_traits::TraversalKind TK,
const internal::BindableMatcher<T> &InnerMatcher) {
return internal::BindableMatcher<T>(
internal::DynTypedMatcher::constructRestrictedWrapper(
new internal::TraversalMatcher<T>(TK, InnerMatcher),
InnerMatcher.getID().first)
.template unconditionalConvertTo<T>());
}
template <typename... T>
internal::TraversalWrapper<internal::VariadicOperatorMatcher<T...>>
traverse(ast_type_traits::TraversalKind TK,

View File

@ -112,6 +112,11 @@ public:
return Result;
}
llvm::Optional<ast_type_traits::TraversalKind>
TraversalKind() const override {
return InnerMatcher->TraversalKind();
}
private:
const std::string ID;
const IntrusiveRefCntPtr<DynMatcherInterface> InnerMatcher;

View File

@ -1700,6 +1700,28 @@ void bar()
hasDescendant(floatLiteral())))));
}
template <typename MatcherT>
bool matcherTemplateWithBinding(StringRef Code, const MatcherT &M) {
return matchAndVerifyResultTrue(
Code, M.bind("matchedStmt"),
std::make_unique<VerifyIdIsBoundTo<ReturnStmt>>("matchedStmt", 1));
}
TEST(Traversal, traverseWithBinding) {
// Some existing matcher code expects to take a matcher as a
// template arg and bind to it. Verify that that works.
EXPECT_TRUE(matcherTemplateWithBinding(
R"cpp(
int foo()
{
return 42.0;
}
)cpp",
traverse(ast_type_traits::TK_AsIs,
returnStmt(has(implicitCastExpr(has(floatLiteral())))))));
}
TEST(Traversal, traverseMatcherNesting) {
StringRef Code = R"cpp(