Skip to content

Commit 4dfe212

Browse files
authored
[lldb][DWARFASTParserClang] Added a check for the specialization existence (#154123)
[lldb][DWARFASTParserClang] Added a check for the specialization existence While debugging an application with incorrect dwarf information, where DW_TAG_template_value_parameter was lost, I found that lldb does not check that the corresponding specialization exists. As a result, at the stage when ASTImporter works, the type is completed in such a way that it inherits from itself. And during the calculation of layout, an infinite recursion occurs. To catch this error, I added a corresponding check at the stage of restoring the type from dwarf information. I also added a trivial assert in clang to check that the class does not inherit from itself.
1 parent 31180ba commit 4dfe212

File tree

5 files changed

+729
-1
lines changed

5 files changed

+729
-1
lines changed

lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1901,6 +1901,17 @@ DWARFASTParserClang::ParseStructureLikeDIE(const SymbolContext &sc,
19011901
m_ast.CreateClassTemplateSpecializationDecl(
19021902
containing_decl_ctx, GetOwningClangModule(die), class_template_decl,
19031903
tag_decl_kind, template_param_infos);
1904+
if (!class_specialization_decl) {
1905+
if (log) {
1906+
dwarf->GetObjectFile()->GetModule()->LogMessage(
1907+
log,
1908+
"SymbolFileDWARF({0:p}) - Failed to create specialization for "
1909+
"clang::ClassTemplateDecl({1}, {2:p}).",
1910+
this, llvm::StringRef(attrs.name), class_template_decl);
1911+
}
1912+
return TypeSP();
1913+
}
1914+
19041915
clang_type =
19051916
m_ast.CreateClassTemplateSpecializationType(class_specialization_decl);
19061917

lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1693,6 +1693,11 @@ TypeSystemClang::CreateClassTemplateSpecializationDecl(
16931693
class_template_specialization_decl->setInstantiationOf(class_template_decl);
16941694
class_template_specialization_decl->setTemplateArgs(
16951695
TemplateArgumentList::CreateCopy(ast, args));
1696+
void *insert_pos = nullptr;
1697+
if (class_template_decl->findSpecialization(args, insert_pos))
1698+
return nullptr;
1699+
class_template_decl->AddSpecialization(class_template_specialization_decl,
1700+
insert_pos);
16961701
class_template_specialization_decl->setDeclName(
16971702
class_template_decl->getDeclName());
16981703

lldb/unittests/SymbolFile/DWARF/CMakeLists.txt

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ add_lldb_unittest(SymbolFileDWARFTests
2727

2828
set(test_inputs
2929
test-dwarf.exe
30-
DW_AT_default_value-test.yaml)
30+
DW_AT_default_value-test.yaml
31+
DW_AT_spec_decl_exists-test.yaml)
3132

3233
add_unittest_inputs(SymbolFileDWARFTests "${test_inputs}")

lldb/unittests/SymbolFile/DWARF/DWARFASTParserClangTests.cpp

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -599,6 +599,40 @@ TEST_F(DWARFASTParserClangTests, TestDefaultTemplateParamParsing) {
599599
}
600600
}
601601

602+
TEST_F(DWARFASTParserClangTests, TestSpecDeclExistsError) {
603+
// Tests that parsing a ClassTemplateSpecializationDecl that already exists
604+
// is handled gracefully.
605+
auto BufferOrError = llvm::MemoryBuffer::getFile(
606+
GetInputFilePath("DW_AT_spec_decl_exists-test.yaml"), /*IsText=*/true);
607+
ASSERT_TRUE(BufferOrError);
608+
YAMLModuleTester t(BufferOrError.get()->getBuffer());
609+
610+
DWARFUnit *unit = t.GetDwarfUnit();
611+
ASSERT_NE(unit, nullptr);
612+
const DWARFDebugInfoEntry *cu_entry = unit->DIE().GetDIE();
613+
ASSERT_EQ(cu_entry->Tag(), DW_TAG_compile_unit);
614+
DWARFDIE cu_die(unit, cu_entry);
615+
616+
auto holder = std::make_unique<clang_utils::TypeSystemClangHolder>("ast");
617+
auto &ast_ctx = *holder->GetAST();
618+
DWARFASTParserClangStub ast_parser(ast_ctx);
619+
620+
llvm::SmallVector<lldb::TypeSP, 2> specializations;
621+
for (DWARFDIE die : cu_die.children()) {
622+
SymbolContext sc;
623+
bool new_type = false;
624+
auto type = ast_parser.ParseTypeFromDWARF(sc, die, &new_type);
625+
llvm::StringRef die_name = llvm::StringRef(die.GetName());
626+
if (die_name.starts_with("_Optional_payload")) {
627+
specializations.push_back(std::move(type));
628+
}
629+
}
630+
631+
ASSERT_EQ(specializations.size(), 2U);
632+
ASSERT_NE(specializations[0], nullptr);
633+
ASSERT_EQ(specializations[1], nullptr);
634+
}
635+
602636
TEST_F(DWARFASTParserClangTests, TestUniqueDWARFASTTypeMap_CppInsertMapFind) {
603637
// This tests the behaviour of UniqueDWARFASTTypeMap under
604638
// following scenario:

0 commit comments

Comments
 (0)