Skip to content

Commit 16cabf2

Browse files
committed
[ASTMatchers] HasNameMatcher handles extern "C"
Summary: Fixes [[ https://bugs.llvm.org/show_bug.cgi?id=42193 | hasName AST matcher is confused by extern "C" in namespace. ]] Reviewers: klimek, aaron.ballman, gribozavr2 Reviewed By: aaron.ballman Subscribers: cfe-commits Tags: #clang Differential Revision: https://reviews.llvm.org/D75202
1 parent 949134e commit 16cabf2

File tree

2 files changed

+22
-1
lines changed

2 files changed

+22
-1
lines changed

clang/lib/ASTMatchers/ASTMatchersInternal.cpp

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -513,7 +513,13 @@ bool HasNameMatcher::matchesNodeFullFast(const NamedDecl &Node) const {
513513
if (Ctx->isFunctionOrMethod())
514514
return Patterns.foundMatch(/*AllowFullyQualified=*/false);
515515

516-
for (; Ctx && isa<NamedDecl>(Ctx); Ctx = Ctx->getParent()) {
516+
for (; Ctx; Ctx = Ctx->getParent()) {
517+
// Linkage Spec can just be ignored
518+
// FIXME: Any other DeclContext kinds that can be safely disregarded
519+
if (isa<LinkageSpecDecl>(Ctx))
520+
continue;
521+
if (!isa<NamedDecl>(Ctx))
522+
break;
517523
if (Patterns.foundMatch(/*AllowFullyQualified=*/false))
518524
return true;
519525

clang/unittests/ASTMatchers/ASTMatchersNarrowingTest.cpp

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1643,6 +1643,21 @@ TEST(Matcher, HasNameSupportsFunctionScope) {
16431643
EXPECT_TRUE(matches(code, fieldDecl(hasName("::a::F(int)::S::m"))));
16441644
}
16451645

1646+
TEST(Matcher, HasNameQualifiedSupportsLinkage) {
1647+
// https://bugs.llvm.org/show_bug.cgi?id=42193
1648+
std::string code = R"cpp(namespace foo { extern "C" void test(); })cpp";
1649+
EXPECT_TRUE(matches(code, functionDecl(hasName("test"))));
1650+
EXPECT_TRUE(matches(code, functionDecl(hasName("foo::test"))));
1651+
EXPECT_TRUE(matches(code, functionDecl(hasName("::foo::test"))));
1652+
EXPECT_TRUE(notMatches(code, functionDecl(hasName("::test"))));
1653+
1654+
code = R"cpp(namespace foo { extern "C" { void test(); } })cpp";
1655+
EXPECT_TRUE(matches(code, functionDecl(hasName("test"))));
1656+
EXPECT_TRUE(matches(code, functionDecl(hasName("foo::test"))));
1657+
EXPECT_TRUE(matches(code, functionDecl(hasName("::foo::test"))));
1658+
EXPECT_TRUE(notMatches(code, functionDecl(hasName("::test"))));
1659+
}
1660+
16461661
TEST(Matcher, HasAnyName) {
16471662
const std::string Code = "namespace a { namespace b { class C; } }";
16481663

0 commit comments

Comments
 (0)