[clangd] Guard against null TemplateName in DumpVisitor (#181554)

Add a guard against null values for TemplateName in
DumpVisitor::TraverseTemplateName.

clangd’s DumpVisitor may attempt to traverse a null TemplateName when
handling dependent nested template names. On LLVM main this can lead to
a crash in TemplateName::getKind().

Add a defensive check in DumpVisitor::TraverseTemplateName() to skip
null TemplateName instances before invoking traverseNode(). Following
the same design as other functions in the class.

No functional change is intended beyond preventing the crash.

Fixes: #180902

---------

Signed-off-by: Emily Dror <emilydror01@gmail.com>
This commit is contained in:
Emily Dror 2026-02-20 00:55:09 +02:00 committed by GitHub
parent f5f8435605
commit 192883904a
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 31 additions and 2 deletions

View file

@ -347,8 +347,8 @@ public:
});
}
bool TraverseTemplateName(const TemplateName &TN) {
return traverseNode("template name", TN,
[&] { Base::TraverseTemplateName(TN); });
return TN.isNull() || traverseNode("template name", TN,
[&] { Base::TraverseTemplateName(TN); });
}
bool TraverseTemplateArgumentLoc(const TemplateArgumentLoc &TAL) {
return traverseNode("template argument", TAL,

View file

@ -227,6 +227,35 @@ TEST(DumpASTTests, UnbalancedBraces) {
ASSERT_EQ(Node.range, Case.range("func"));
}
TEST(DumpASTTests, NestedTemplates) {
// Test that we don't crash while trying to dump AST of a template function
// with nested template names such as Foo<V>::template Bar<W>::Value.
const char *Code = R"cpp(
template <typename T>
struct TypeA {
template <typename U>
struct TypeB {
static U Value;
};
};
template <typename V, typename W>
auto func() {
return TypeA<V>::template TypeB<W>::Value;
}
)cpp";
ParsedAST AST = TestTU::withCode(Code).build();
const NamedDecl &Func = findDecl(AST, [](const NamedDecl &D) {
return isa<FunctionDecl>(D) && D.getNameAsString() == "func";
});
const ASTNode Node =
dumpAST(DynTypedNode::create(Func), AST.getTokens(), AST.getASTContext());
EXPECT_EQ(Node.kind, "Function");
}
} // namespace
} // namespace clangd
} // namespace clang