[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.
This commit is contained in:
Paul Kirth 2026-02-19 15:54:19 -08:00 committed by GitHub
parent 13f659c21d
commit 64e1318c55
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 61 additions and 21 deletions

View File

@ -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
------------

View File

@ -1654,6 +1654,16 @@ private:
} // end namespace
} // end namespace internal
template <typename T>
static internal::Matcher<T>
adjustTraversalKind(const internal::Matcher<T> &NodeMatch,
MatchFinder::MatchCallback *Action) {
if (Action)
if (std::optional<TraversalKind> 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<TraversalKind> 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<TraversalKind> 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);
}

View File

@ -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<TraversalKind> TK;
bool *Matched;
TestCallback(std::optional<TraversalKind> TK, bool *Matched)
: TK(TK), Matched(Matched) {}
void run(const MatchFinder::MatchResult &Result) override {
*Matched = true;
}
std::optional<TraversalKind> getCheckTraversalKind() const override {
return TK;
}
} Callback(TK_IgnoreUnlessSpelledInSource, &Matched);
Finder.addMatcher(Matcher, &Callback);
std::unique_ptr<FrontendActionFactory> 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"))));