From ad0a45833b940057cc74364c82271247bd7925e1 Mon Sep 17 00:00:00 2001 From: Stephen Kelly Date: Sun, 5 Jan 2020 20:48:20 +0000 Subject: [PATCH] Allow using traverse() with bindings --- clang/include/clang/ASTMatchers/ASTMatchers.h | 11 ++++++++++ clang/lib/ASTMatchers/ASTMatchersInternal.cpp | 5 +++++ .../ASTMatchers/ASTMatchersTraversalTest.cpp | 22 +++++++++++++++++++ 3 files changed, 38 insertions(+) diff --git a/clang/include/clang/ASTMatchers/ASTMatchers.h b/clang/include/clang/ASTMatchers/ASTMatchers.h index 7db5f7a5de82..54ccaabadbe4 100644 --- a/clang/include/clang/ASTMatchers/ASTMatchers.h +++ b/clang/include/clang/ASTMatchers/ASTMatchers.h @@ -714,6 +714,17 @@ internal::Matcher traverse(ast_type_traits::TraversalKind TK, .template unconditionalConvertTo(); } +template +internal::BindableMatcher +traverse(ast_type_traits::TraversalKind TK, + const internal::BindableMatcher &InnerMatcher) { + return internal::BindableMatcher( + internal::DynTypedMatcher::constructRestrictedWrapper( + new internal::TraversalMatcher(TK, InnerMatcher), + InnerMatcher.getID().first) + .template unconditionalConvertTo()); +} + template internal::TraversalWrapper> traverse(ast_type_traits::TraversalKind TK, diff --git a/clang/lib/ASTMatchers/ASTMatchersInternal.cpp b/clang/lib/ASTMatchers/ASTMatchersInternal.cpp index efa628cfeefc..75846ab2d4b1 100644 --- a/clang/lib/ASTMatchers/ASTMatchersInternal.cpp +++ b/clang/lib/ASTMatchers/ASTMatchersInternal.cpp @@ -112,6 +112,11 @@ public: return Result; } + llvm::Optional + TraversalKind() const override { + return InnerMatcher->TraversalKind(); + } + private: const std::string ID; const IntrusiveRefCntPtr InnerMatcher; diff --git a/clang/unittests/ASTMatchers/ASTMatchersTraversalTest.cpp b/clang/unittests/ASTMatchers/ASTMatchersTraversalTest.cpp index ea1ad424c94d..327ed979962f 100644 --- a/clang/unittests/ASTMatchers/ASTMatchersTraversalTest.cpp +++ b/clang/unittests/ASTMatchers/ASTMatchersTraversalTest.cpp @@ -1700,6 +1700,28 @@ void bar() hasDescendant(floatLiteral()))))); } +template +bool matcherTemplateWithBinding(StringRef Code, const MatcherT &M) { + return matchAndVerifyResultTrue( + Code, M.bind("matchedStmt"), + std::make_unique>("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(