From 64e1318c55b94c1c99a80fdf1424367a80a2e9d5 Mon Sep 17 00:00:00 2001 From: Paul Kirth Date: Thu, 19 Feb 2026 15:54:19 -0800 Subject: [PATCH] [clang] Add missing support for traversal kind in addMatcher overloads (#170953) This was noted in #170540, and seems to simply be an oversight. This patch just add the same logic already used in other addMatcher() implementations that honor the traversal kind. Fixes #179386. --- clang/docs/ReleaseNotes.rst | 1 + clang/lib/ASTMatchers/ASTMatchFinder.cpp | 46 ++++++++++--------- .../ASTMatchers/ASTMatchersInternalTest.cpp | 35 ++++++++++++++ 3 files changed, 61 insertions(+), 21 deletions(-) diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst index b2302cbdb3f5..8d5d704c1766 100644 --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -396,6 +396,7 @@ Fixed Point Support in Clang AST Matchers ------------ - Add ``functionTypeLoc`` matcher for matching ``FunctionTypeLoc``. +- Add missing support for ``TraversalKind`` in some ``addMatcher()`` overloads. clang-format ------------ diff --git a/clang/lib/ASTMatchers/ASTMatchFinder.cpp b/clang/lib/ASTMatchers/ASTMatchFinder.cpp index e8a0004c2e18..83ffae65c67d 100644 --- a/clang/lib/ASTMatchers/ASTMatchFinder.cpp +++ b/clang/lib/ASTMatchers/ASTMatchFinder.cpp @@ -1654,6 +1654,16 @@ private: } // end namespace } // end namespace internal +template +static internal::Matcher +adjustTraversalKind(const internal::Matcher &NodeMatch, + MatchFinder::MatchCallback *Action) { + if (Action) + if (std::optional TK = Action->getCheckTraversalKind()) + return traverse(*TK, NodeMatch); + return NodeMatch; +} + MatchFinder::MatchResult::MatchResult(const BoundNodes &Nodes, ASTContext *Context) : Nodes(Nodes), Context(Context), @@ -1669,67 +1679,61 @@ MatchFinder::~MatchFinder() {} void MatchFinder::addMatcher(const DeclarationMatcher &NodeMatch, MatchCallback *Action) { - std::optional TK; - if (Action) - TK = Action->getCheckTraversalKind(); - if (TK) - Matchers.DeclOrStmt.emplace_back(traverse(*TK, NodeMatch), Action); - else - Matchers.DeclOrStmt.emplace_back(NodeMatch, Action); + Matchers.DeclOrStmt.emplace_back(adjustTraversalKind(NodeMatch, Action), + Action); Matchers.AllCallbacks.insert(Action); } void MatchFinder::addMatcher(const TypeMatcher &NodeMatch, MatchCallback *Action) { - Matchers.Type.emplace_back(NodeMatch, Action); + Matchers.Type.emplace_back(adjustTraversalKind(NodeMatch, Action), Action); Matchers.AllCallbacks.insert(Action); } void MatchFinder::addMatcher(const StatementMatcher &NodeMatch, MatchCallback *Action) { - std::optional TK; - if (Action) - TK = Action->getCheckTraversalKind(); - if (TK) - Matchers.DeclOrStmt.emplace_back(traverse(*TK, NodeMatch), Action); - else - Matchers.DeclOrStmt.emplace_back(NodeMatch, Action); + Matchers.DeclOrStmt.emplace_back(adjustTraversalKind(NodeMatch, Action), + Action); Matchers.AllCallbacks.insert(Action); } void MatchFinder::addMatcher(const NestedNameSpecifierMatcher &NodeMatch, MatchCallback *Action) { - Matchers.NestedNameSpecifier.emplace_back(NodeMatch, Action); + Matchers.NestedNameSpecifier.emplace_back( + adjustTraversalKind(NodeMatch, Action), Action); Matchers.AllCallbacks.insert(Action); } void MatchFinder::addMatcher(const NestedNameSpecifierLocMatcher &NodeMatch, MatchCallback *Action) { - Matchers.NestedNameSpecifierLoc.emplace_back(NodeMatch, Action); + Matchers.NestedNameSpecifierLoc.emplace_back( + adjustTraversalKind(NodeMatch, Action), Action); Matchers.AllCallbacks.insert(Action); } void MatchFinder::addMatcher(const TypeLocMatcher &NodeMatch, MatchCallback *Action) { - Matchers.TypeLoc.emplace_back(NodeMatch, Action); + Matchers.TypeLoc.emplace_back(adjustTraversalKind(NodeMatch, Action), Action); Matchers.AllCallbacks.insert(Action); } void MatchFinder::addMatcher(const CXXCtorInitializerMatcher &NodeMatch, MatchCallback *Action) { - Matchers.CtorInit.emplace_back(NodeMatch, Action); + Matchers.CtorInit.emplace_back(adjustTraversalKind(NodeMatch, Action), + Action); Matchers.AllCallbacks.insert(Action); } void MatchFinder::addMatcher(const TemplateArgumentLocMatcher &NodeMatch, MatchCallback *Action) { - Matchers.TemplateArgumentLoc.emplace_back(NodeMatch, Action); + Matchers.TemplateArgumentLoc.emplace_back( + adjustTraversalKind(NodeMatch, Action), Action); Matchers.AllCallbacks.insert(Action); } void MatchFinder::addMatcher(const AttrMatcher &AttrMatch, MatchCallback *Action) { - Matchers.Attr.emplace_back(AttrMatch, Action); + Matchers.Attr.emplace_back(adjustTraversalKind(AttrMatch, Action), Action); Matchers.AllCallbacks.insert(Action); } diff --git a/clang/unittests/ASTMatchers/ASTMatchersInternalTest.cpp b/clang/unittests/ASTMatchers/ASTMatchersInternalTest.cpp index a930638f355b..3fa71804710a 100644 --- a/clang/unittests/ASTMatchers/ASTMatchersInternalTest.cpp +++ b/clang/unittests/ASTMatchers/ASTMatchersInternalTest.cpp @@ -297,6 +297,41 @@ TEST(DynTypedMatcherTest, ConstructWithTraversalKindOverridesNestedTK) { llvm::ValueIs(TK_IgnoreUnlessSpelledInSource)); } +TEST(MatchFinder, AddMatcherOverloadsHonorTraversalKind) { + StringRef Code = R"cpp( + struct B {}; + struct C : B { + C() {} + }; + )cpp"; + + // C() has an implicit initializer for B. + auto Matcher = cxxCtorInitializer(isBaseInitializer()); + + { + bool Matched = false; + MatchFinder Finder; + struct TestCallback : public MatchFinder::MatchCallback { + std::optional TK; + bool *Matched; + TestCallback(std::optional TK, bool *Matched) + : TK(TK), Matched(Matched) {} + void run(const MatchFinder::MatchResult &Result) override { + *Matched = true; + } + std::optional getCheckTraversalKind() const override { + return TK; + } + } Callback(TK_IgnoreUnlessSpelledInSource, &Matched); + Finder.addMatcher(Matcher, &Callback); + std::unique_ptr Factory( + newFrontendActionFactory(&Finder)); + ASSERT_TRUE(tooling::runToolOnCode(Factory->create(), Code)); + EXPECT_FALSE(Matched) << "Matcher not using specified TraversalKind, " + "TK_IgnoreUnlessSpelledInSource"; + } +} + TEST(IsInlineMatcher, IsInline) { EXPECT_TRUE(matches("void g(); inline void f();", functionDecl(isInline(), hasName("f"))));