Skip to content

Commit 9e3f5ae

Browse files
committed
Fix hasName matcher assertion with inline namespaces
Fix handling of nodes which can be skipped in the fast path for the hasName matcher
1 parent 154d00d commit 9e3f5ae

File tree

2 files changed

+20
-7
lines changed

2 files changed

+20
-7
lines changed

clang/lib/ASTMatchers/ASTMatchersInternal.cpp

Lines changed: 16 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -537,14 +537,23 @@ class PatternSet {
537537
/// that didn't match.
538538
/// Return true if there are still any patterns left.
539539
bool consumeNameSuffix(StringRef NodeName, bool CanSkip) {
540-
for (size_t I = 0; I < Patterns.size();) {
541-
if (::clang::ast_matchers::internal::consumeNameSuffix(Patterns[I].P,
542-
NodeName) ||
543-
CanSkip) {
544-
++I;
545-
} else {
546-
Patterns.erase(Patterns.begin() + I);
540+
if (CanSkip) {
541+
// If we can skip the node, then we need to handle the case where a
542+
// skipped node has the same name as its parent.
543+
// namespace a { inline namespace a { class A; } }
544+
// cxxRecordDecl(hasName("::a::A"))
545+
// To do this, any patterns that match should be duplicated in our set,
546+
// one of them with the tail removed.
547+
for (size_t I = 0, E = Patterns.size(); I != E; ++I) {
548+
StringRef Pattern = Patterns[I].P;
549+
if (ast_matchers::internal::consumeNameSuffix(Patterns[I].P, NodeName))
550+
Patterns.push_back({Pattern, Patterns[I].IsFullyQualified});
547551
}
552+
} else {
553+
llvm::erase_if(Patterns, [&NodeName](auto &Pattern) {
554+
return !::clang::ast_matchers::internal::consumeNameSuffix(Pattern.P,
555+
NodeName);
556+
});
548557
}
549558
return !Patterns.empty();
550559
}

clang/unittests/ASTMatchers/ASTMatchersNarrowingTest.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2552,6 +2552,10 @@ TEST_P(ASTMatchersTest, HasName_MatchesNamespaces) {
25522552
recordDecl(hasName("a+b::C"))));
25532553
EXPECT_TRUE(notMatches("namespace a { namespace b { class AC; } }",
25542554
recordDecl(hasName("C"))));
2555+
EXPECT_TRUE(matches("namespace a { inline namespace a { class C; } }",
2556+
recordDecl(hasName("::a::C"))));
2557+
EXPECT_TRUE(matches("namespace a { inline namespace a { class C; } }",
2558+
recordDecl(hasName("::a::a::C"))));
25552559
}
25562560

25572561
TEST_P(ASTMatchersTest, HasName_MatchesOuterClasses) {

0 commit comments

Comments
 (0)