Skip to content

Commit f9e7cba

Browse files
authored
Fix hasName matcher assertion with inline namespaces (#100975)
Fix handling of nodes which can be skipped in the fast path for the hasName matcher Fixes #100973
1 parent 708a9a0 commit f9e7cba

File tree

3 files changed

+23
-7
lines changed

3 files changed

+23
-7
lines changed

clang/docs/ReleaseNotes.rst

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -251,6 +251,9 @@ Fixed Point Support in Clang
251251
AST Matchers
252252
------------
253253

254+
- Fixed an issue with the `hasName` and `hasAnyName` matcher when matching
255+
inline namespaces with an enclosing namespace of the same name.
256+
254257
clang-format
255258
------------
256259

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)