[Lldb-commits] [lldb] [lldb] handle existing ClassTemplateSpecializationDecl gracefully (PR #207705)
via lldb-commits
lldb-commits at lists.llvm.org
Mon Jul 6 04:05:51 PDT 2026
llvmorg-github-actions[bot] wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-lldb
Author: Konstantin Bolshakov (konstantinbo)
<details>
<summary>Changes</summary>
This fixes #<!-- -->207704
Assisted-by: Github Copilot (Claude Opus 4.8)
---
Full diff: https://github.com/llvm/llvm-project/pull/207705.diff
2 Files Affected:
- (modified) lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp (+20-15)
- (modified) lldb/unittests/SymbolFile/DWARF/DWARFASTParserClangTests.cpp (+26-3)
``````````diff
diff --git a/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp b/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp
index 0506b7d4da40f..f6deb3abd3881 100644
--- a/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp
+++ b/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp
@@ -1882,22 +1882,27 @@ TypeSP DWARFASTParserClang::ParseStructureLikeDIE(
m_ast.CreateClassTemplateSpecializationDecl(
containing_decl_ctx, GetOwningClangModule(die), class_template_decl,
tag_decl_kind, template_param_infos);
- if (!class_specialization_decl) {
- if (log) {
- dwarf->GetObjectFile()->GetModule()->LogMessage(
- log,
- "SymbolFileDWARF({0:p}) - Failed to create specialization for "
- "clang::ClassTemplateDecl({1}, {2:p}).",
- this, llvm::StringRef(attrs.name), class_template_decl);
- }
- return TypeSP();
+ if (class_specialization_decl) {
+ clang_type =
+ m_ast.CreateClassTemplateSpecializationType(class_specialization_decl);
+
+ m_ast.SetMetadata(class_template_decl, metadata);
+ m_ast.SetMetadata(class_specialization_decl, metadata);
+ } else if (log) {
+ // A specialization with identical template arguments already exists.
+ // This happens with malformed/duplicated DWARF, e.g. GCC emits several
+ // reduced copies of a std::tuple<...> instantiation whose only template
+ // child is an empty DW_TAG_GNU_template_parameter_pack, so every copy
+ // collapses to the same (empty) argument list. Failing to parse the type
+ // here would leave members that reference it (such as unique_ptr's _M_t)
+ // with a null type and crash data formatters. Instead, fall through and
+ // build a plain (non-template) record type below.
+ dwarf->GetObjectFile()->GetModule()->LogMessage(
+ log,
+ "SymbolFileDWARF({0:p}) - Specialization for clang::ClassTemplateDecl"
+ "({1}, {2:p}) already exists; falling back to a non-template record.",
+ this, llvm::StringRef(attrs.name), class_template_decl);
}
-
- clang_type =
- m_ast.CreateClassTemplateSpecializationType(class_specialization_decl);
-
- m_ast.SetMetadata(class_template_decl, metadata);
- m_ast.SetMetadata(class_specialization_decl, metadata);
}
if (!clang_type) {
diff --git a/lldb/unittests/SymbolFile/DWARF/DWARFASTParserClangTests.cpp b/lldb/unittests/SymbolFile/DWARF/DWARFASTParserClangTests.cpp
index a95d6ecfab790..66b220aa8dc98 100644
--- a/lldb/unittests/SymbolFile/DWARF/DWARFASTParserClangTests.cpp
+++ b/lldb/unittests/SymbolFile/DWARF/DWARFASTParserClangTests.cpp
@@ -622,8 +622,15 @@ TEST_F(DWARFASTParserClangTests, TestDefaultTemplateParamParsing) {
}
TEST_F(DWARFASTParserClangTests, TestSpecDeclExistsError) {
- // Tests that parsing a ClassTemplateSpecializationDecl that already exists
- // is handled gracefully.
+ // Tests that parsing a second class DIE whose template arguments collapse to
+ // an already-existing ClassTemplateSpecializationDecl is handled gracefully.
+ // The malformed input drops DW_TAG_template_value_parameter entries, which
+ // makes two distinct specializations look structurally identical. Rather than
+ // failing to parse the second type (which would leave members referring to it
+ // with a null type and crash data formatters), the parser falls back to a
+ // plain, non-template record type. Critically, neither resulting type may end
+ // up inheriting from itself, which used to cause infinite recursion during
+ // layout.
auto BufferOrError = llvm::MemoryBuffer::getFile(
GetInputFilePath("DW_AT_spec_decl_exists-test.yaml"), /*IsText=*/true);
ASSERT_TRUE(BufferOrError);
@@ -643,7 +650,23 @@ TEST_F(DWARFASTParserClangTests, TestSpecDeclExistsError) {
ASSERT_EQ(specializations.size(), 2U);
ASSERT_NE(specializations[0], nullptr);
- ASSERT_EQ(specializations[1], nullptr);
+ ASSERT_NE(specializations[1], nullptr);
+
+ // Completing each type must not recurse infinitely, and no type may inherit
+ // from itself.
+ for (auto const &type_sp : specializations) {
+ CompilerType ct = type_sp->GetFullCompilerType();
+ auto const *record = llvm::dyn_cast_or_null<clang::CXXRecordDecl>(
+ ClangUtil::GetAsTagDecl(ct));
+ ASSERT_NE(record, nullptr);
+ if (!record->hasDefinition())
+ continue;
+ for (clang::CXXBaseSpecifier const &base : record->bases()) {
+ clang::CXXRecordDecl const *base_decl =
+ base.getType()->getAsCXXRecordDecl();
+ EXPECT_NE(base_decl, record);
+ }
+ }
}
TEST_F(DWARFASTParserClangTests, TestUniqueDWARFASTTypeMap_CppInsertMapFind) {
``````````
</details>
https://github.com/llvm/llvm-project/pull/207705
More information about the lldb-commits
mailing list