https://github.com/Michael137 updated https://github.com/llvm/llvm-project/pull/170135
>From 0daeab2b5b9ae6423910ee7248b6579c3b6498b4 Mon Sep 17 00:00:00 2001 From: Michael Buch <[email protected]> Date: Tue, 2 Dec 2025 15:42:00 +0900 Subject: [PATCH 1/3] [lldb][DWARFASTParserClang] Complete and make use of LLVM's RTTI support We almost had RTTI support for `DWARFASTParserClang`, but because `classof` was protected, using `llvm::cast`/etc. on it would fail to compile with: ``` llvm/include/llvm/Support/Casting.h:64:57: error: 'classof' is a protected member of 'DWARFASTParserClang' 64 | static inline bool doit(const From &Val) { return To::classof(&Val); } | ^ llvm/include/llvm/Support/Casting.h:110:32: note: in instantiation of member function 'llvm::isa_impl<DWARFASTParserClang, lldb_private::plugin::dwarf::DWARFASTParser>::doit' requested here 110 | return isa_impl<To, From>::doit(*Val); ``` This patch makes `classof` public and turns `static_cast`s of `DWARFASTParserClang` into `llvm::cast`s. --- .../Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp | 10 ++++------ .../Plugins/SymbolFile/DWARF/DWARFASTParserClang.h | 9 +++++---- .../Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp | 11 +++++------ lldb/unittests/Symbol/TestClangASTImporter.cpp | 2 +- .../SymbolFile/DWARF/DWARFASTParserClangTests.cpp | 4 ++-- 5 files changed, 17 insertions(+), 19 deletions(-) diff --git a/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp b/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp index 36aa49ac3de95..7160c6eec564b 100644 --- a/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp +++ b/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp @@ -3707,12 +3707,10 @@ bool DWARFASTParserClang::CopyUniqueClassMethodTypes( } } - DWARFASTParserClang *src_dwarf_ast_parser = - static_cast<DWARFASTParserClang *>( - SymbolFileDWARF::GetDWARFParser(*src_class_die.GetCU())); - DWARFASTParserClang *dst_dwarf_ast_parser = - static_cast<DWARFASTParserClang *>( - SymbolFileDWARF::GetDWARFParser(*dst_class_die.GetCU())); + auto *src_dwarf_ast_parser = llvm::cast<DWARFASTParserClang>( + SymbolFileDWARF::GetDWARFParser(*src_class_die.GetCU())); + auto *dst_dwarf_ast_parser = llvm::cast<DWARFASTParserClang>( + SymbolFileDWARF::GetDWARFParser(*dst_class_die.GetCU())); auto link = [&](DWARFDIE src, DWARFDIE dst) { auto &die_to_type = dst_class_die.GetDWARF()->GetDIEToType(); clang::DeclContext *dst_decl_ctx = diff --git a/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.h b/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.h index f5f707129d67d..6eb2b6b48787b 100644 --- a/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.h +++ b/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.h @@ -47,6 +47,11 @@ class DWARFASTParserClang : public lldb_private::plugin::dwarf::DWARFASTParser { ~DWARFASTParserClang() override; + // LLVM RTTI support + static bool classof(const DWARFASTParser *Parser) { + return Parser->GetKind() == Kind::DWARFASTParserClang; + } + // DWARFASTParser interface. lldb::TypeSP ParseTypeFromDWARF(const lldb_private::SymbolContext &sc, @@ -264,10 +269,6 @@ class DWARFASTParserClang : public lldb_private::plugin::dwarf::DWARFASTParser { lldb::ModuleSP GetModuleForType(const lldb_private::plugin::dwarf::DWARFDIE &die); - static bool classof(const DWARFASTParser *Parser) { - return Parser->GetKind() == Kind::DWARFASTParserClang; - } - private: struct FieldInfo { /// Size in bits that this field occupies. Can but diff --git a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp index a8654869d6093..69951ee03357e 100644 --- a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp +++ b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp @@ -1560,8 +1560,8 @@ bool SymbolFileDWARF::HasForwardDeclForCompilerType( auto clang_type_system = compiler_type.GetTypeSystem<TypeSystemClang>(); if (!clang_type_system) return false; - DWARFASTParserClang *ast_parser = - static_cast<DWARFASTParserClang *>(clang_type_system->GetDWARFParser()); + auto *ast_parser = + llvm::cast<DWARFASTParserClang>(clang_type_system->GetDWARFParser()); return ast_parser->GetClangASTImporter().CanImport(compiler_type); } @@ -1569,8 +1569,8 @@ bool SymbolFileDWARF::CompleteType(CompilerType &compiler_type) { std::lock_guard<std::recursive_mutex> guard(GetModuleMutex()); auto clang_type_system = compiler_type.GetTypeSystem<TypeSystemClang>(); if (clang_type_system) { - DWARFASTParserClang *ast_parser = - static_cast<DWARFASTParserClang *>(clang_type_system->GetDWARFParser()); + auto *ast_parser = + llvm::cast<DWARFASTParserClang>(clang_type_system->GetDWARFParser()); if (ast_parser && ast_parser->GetClangASTImporter().CanImport(compiler_type)) return ast_parser->GetClangASTImporter().CompleteType(compiler_type); @@ -1614,8 +1614,7 @@ bool SymbolFileDWARF::CompleteType(CompilerType &compiler_type) { if (decl_die != def_die) { GetDIEToType()[def_die.GetDIE()] = type; - DWARFASTParserClang *ast_parser = - static_cast<DWARFASTParserClang *>(dwarf_ast); + auto *ast_parser = llvm::cast<DWARFASTParserClang>(dwarf_ast); ast_parser->MapDeclDIEToDefDIE(decl_die, def_die); } diff --git a/lldb/unittests/Symbol/TestClangASTImporter.cpp b/lldb/unittests/Symbol/TestClangASTImporter.cpp index f1b3d7911c4bd..07c42088b9101 100644 --- a/lldb/unittests/Symbol/TestClangASTImporter.cpp +++ b/lldb/unittests/Symbol/TestClangASTImporter.cpp @@ -287,7 +287,7 @@ TEST_F(TestClangASTImporter, RecordLayoutFromOrigin) { clang_utils::SourceASTWithRecord source; auto *dwarf_parser = - static_cast<DWARFASTParserClang *>(source.ast->GetDWARFParser()); + llvm::cast<DWARFASTParserClang>(source.ast->GetDWARFParser()); auto &importer = dwarf_parser->GetClangASTImporter(); // Set the layout for the origin decl in the origin ClangASTImporter. diff --git a/lldb/unittests/SymbolFile/DWARF/DWARFASTParserClangTests.cpp b/lldb/unittests/SymbolFile/DWARF/DWARFASTParserClangTests.cpp index cef3a25a4a960..298dfe3a6fdd5 100644 --- a/lldb/unittests/SymbolFile/DWARF/DWARFASTParserClangTests.cpp +++ b/lldb/unittests/SymbolFile/DWARF/DWARFASTParserClangTests.cpp @@ -1257,7 +1257,7 @@ TEST_F(DWARFASTParserClangTests, TestParseSubroutine_ExplicitObjectParameter) { ASSERT_TRUE(static_cast<bool>(ts_or_err)); llvm::consumeError(ts_or_err.takeError()); auto *parser = - static_cast<DWARFASTParserClang *>((*ts_or_err)->GetDWARFParser()); + llvm::cast<DWARFASTParserClang>((*ts_or_err)->GetDWARFParser()); auto context_die = cu_die.GetFirstChild(); ASSERT_TRUE(context_die.IsValid()); @@ -1434,7 +1434,7 @@ TEST_F(DWARFASTParserClangTests, TestParseSubroutine_ParameterCreation) { llvm::consumeError(ts_or_err.takeError()); auto *ts = static_cast<TypeSystemClang *>(ts_or_err->get()); - auto *parser = static_cast<DWARFASTParserClang *>(ts->GetDWARFParser()); + auto *parser = llvm::cast<DWARFASTParserClang>(ts->GetDWARFParser()); auto subprogram = cu_die.GetFirstChild(); ASSERT_TRUE(subprogram.IsValid()); >From ac6659bdc2d264bb08bf02d27f1c983fb8c0811d Mon Sep 17 00:00:00 2001 From: Michael Buch <[email protected]> Date: Mon, 1 Dec 2025 22:05:46 +0900 Subject: [PATCH 2/3] [lldb][test] DWARFASTParserClangTests: extract test setup into helper structure Depends on: * https://github.com/llvm/llvm-project/pull/170249 We keep repeating the boilerplate of creating a `DWARFASTParserClangStub` and `TypeSystemClangHolder` in all the unit-test cases. Lets extract this into a helper to make the tests easier to grok. --- .../DWARF/DWARFASTParserClangTests.cpp | 276 +++++++----------- 1 file changed, 109 insertions(+), 167 deletions(-) diff --git a/lldb/unittests/SymbolFile/DWARF/DWARFASTParserClangTests.cpp b/lldb/unittests/SymbolFile/DWARF/DWARFASTParserClangTests.cpp index 298dfe3a6fdd5..37e7b601db9d9 100644 --- a/lldb/unittests/SymbolFile/DWARF/DWARFASTParserClangTests.cpp +++ b/lldb/unittests/SymbolFile/DWARF/DWARFASTParserClangTests.cpp @@ -42,6 +42,52 @@ class DWARFASTParserClangStub : public DWARFASTParserClang { return keys; } }; + +/// Helper structure for DWARFASTParserClang tests that want to parse DWARF +/// generated using yaml2obj. On construction parses the supplied YAML data +/// into a DWARF module and thereafter vends a DWARFASTParserClang and +/// TypeSystemClang that are guaranteed to live for the duration of this object. +class DWARFASTParserClangYAMLTester { +public: + DWARFASTParserClangYAMLTester(llvm::StringRef yaml_data) + : m_module_tester(yaml_data) {} + + DWARFDIE GetCUDIE() { + DWARFUnit *unit = m_module_tester.GetDwarfUnit(); + assert(unit); + + const DWARFDebugInfoEntry *cu_entry = unit->DIE().GetDIE(); + assert(cu_entry->Tag() == DW_TAG_compile_unit); + + return DWARFDIE(unit, cu_entry); + } + + DWARFASTParserClang &GetParser() { + auto *parser = GetTypeSystem().GetDWARFParser(); + + assert(llvm::isa_and_nonnull<DWARFASTParserClang>(parser)); + + return *llvm::dyn_cast<DWARFASTParserClang>(parser); + } + + TypeSystemClang &GetTypeSystem() { + ModuleSP module_sp = m_module_tester.GetModule(); + assert(module_sp); + + SymbolFile *symfile = module_sp->GetSymbolFile(); + assert(symfile); + + TypeSystemSP ts_sp = llvm::cantFail( + symfile->GetTypeSystemForLanguage(lldb::eLanguageTypeC_plus_plus)); + + assert(llvm::isa_and_nonnull<TypeSystemClang>(ts_sp.get())); + + return llvm::cast<TypeSystemClang>(*ts_sp); + } + +private: + YAMLModuleTester m_module_tester; +}; } // namespace // If your implementation needs to dereference the dummy pointers we are @@ -99,7 +145,6 @@ TEST_F(DWARFASTParserClangTests, - Value: 0x0000000000000001 - AbbrCode: 0x00000000 )"; - YAMLModuleTester t(yamldata); ASSERT_TRUE((bool)t.GetDwarfUnit()); @@ -248,17 +293,9 @@ TEST_F(DWARFASTParserClangTests, TestCallingConventionParsing) { - AbbrCode: 0x0 ... )"; - YAMLModuleTester t(yamldata); + DWARFASTParserClangYAMLTester tester(yamldata); - DWARFUnit *unit = t.GetDwarfUnit(); - ASSERT_NE(unit, nullptr); - const DWARFDebugInfoEntry *cu_entry = unit->DIE().GetDIE(); - ASSERT_EQ(cu_entry->Tag(), DW_TAG_compile_unit); - DWARFDIE cu_die(unit, cu_entry); - - auto holder = std::make_unique<clang_utils::TypeSystemClangHolder>("ast"); - auto &ast_ctx = *holder->GetAST(); - DWARFASTParserClangStub ast_parser(ast_ctx); + DWARFDIE cu_die = tester.GetCUDIE(); std::vector<std::string> found_function_types; // The DWARF above is just a list of functions. Parse all of them to @@ -267,7 +304,8 @@ TEST_F(DWARFASTParserClangTests, TestCallingConventionParsing) { ASSERT_EQ(func.Tag(), DW_TAG_subprogram); SymbolContext sc; bool new_type = false; - lldb::TypeSP type = ast_parser.ParseTypeFromDWARF(sc, func, &new_type); + lldb::TypeSP type = + tester.GetParser().ParseTypeFromDWARF(sc, func, &new_type); found_function_types.push_back( type->GetForwardCompilerType().GetTypeName().AsCString()); } @@ -394,18 +432,9 @@ TEST_F(DWARFASTParserClangTests, TestPtrAuthParsing) { - AbbrCode: 0x00 # end of child tags of 0x0c ... )"; - YAMLModuleTester t(yamldata); - - DWARFUnit *unit = t.GetDwarfUnit(); - ASSERT_NE(unit, nullptr); - const DWARFDebugInfoEntry *cu_entry = unit->DIE().GetDIE(); - ASSERT_EQ(cu_entry->Tag(), DW_TAG_compile_unit); - DWARFDIE cu_die(unit, cu_entry); - - auto holder = std::make_unique<clang_utils::TypeSystemClangHolder>("ast"); - auto &ast_ctx = *holder->GetAST(); - DWARFASTParserClangStub ast_parser(ast_ctx); + DWARFASTParserClangYAMLTester tester(yamldata); + DWARFDIE cu_die = tester.GetCUDIE(); DWARFDIE ptrauth_variable = cu_die.GetFirstChild(); ASSERT_EQ(ptrauth_variable.Tag(), DW_TAG_variable); DWARFDIE ptrauth_type = @@ -415,7 +444,7 @@ TEST_F(DWARFASTParserClangTests, TestPtrAuthParsing) { SymbolContext sc; bool new_type = false; lldb::TypeSP type_sp = - ast_parser.ParseTypeFromDWARF(sc, ptrauth_type, &new_type); + tester.GetParser().ParseTypeFromDWARF(sc, ptrauth_type, &new_type); CompilerType compiler_type = type_sp->GetForwardCompilerType(); ASSERT_EQ(compiler_type.GetPtrAuthKey(), 0U); ASSERT_EQ(compiler_type.GetPtrAuthAddressDiversity(), false); @@ -554,24 +583,17 @@ TEST_F(DWARFASTParserClangTests, TestDefaultTemplateParamParsing) { auto BufferOrError = llvm::MemoryBuffer::getFile( GetInputFilePath("DW_AT_default_value-test.yaml"), /*IsText=*/true); ASSERT_TRUE(BufferOrError); - YAMLModuleTester t(BufferOrError.get()->getBuffer()); - DWARFUnit *unit = t.GetDwarfUnit(); - ASSERT_NE(unit, nullptr); - const DWARFDebugInfoEntry *cu_entry = unit->DIE().GetDIE(); - ASSERT_EQ(cu_entry->Tag(), DW_TAG_compile_unit); - DWARFDIE cu_die(unit, cu_entry); - - auto holder = std::make_unique<clang_utils::TypeSystemClangHolder>("ast"); - auto &ast_ctx = *holder->GetAST(); - DWARFASTParserClangStub ast_parser(ast_ctx); + DWARFASTParserClangYAMLTester tester(BufferOrError.get()->getBuffer()); + DWARFDIE cu_die = tester.GetCUDIE(); llvm::SmallVector<lldb::TypeSP, 2> types; for (DWARFDIE die : cu_die.children()) { if (die.Tag() == DW_TAG_class_type) { SymbolContext sc; bool new_type = false; - types.push_back(ast_parser.ParseTypeFromDWARF(sc, die, &new_type)); + types.push_back( + tester.GetParser().ParseTypeFromDWARF(sc, die, &new_type)); } } @@ -605,23 +627,14 @@ TEST_F(DWARFASTParserClangTests, TestSpecDeclExistsError) { auto BufferOrError = llvm::MemoryBuffer::getFile( GetInputFilePath("DW_AT_spec_decl_exists-test.yaml"), /*IsText=*/true); ASSERT_TRUE(BufferOrError); - YAMLModuleTester t(BufferOrError.get()->getBuffer()); - - DWARFUnit *unit = t.GetDwarfUnit(); - ASSERT_NE(unit, nullptr); - const DWARFDebugInfoEntry *cu_entry = unit->DIE().GetDIE(); - ASSERT_EQ(cu_entry->Tag(), DW_TAG_compile_unit); - DWARFDIE cu_die(unit, cu_entry); - - auto holder = std::make_unique<clang_utils::TypeSystemClangHolder>("ast"); - auto &ast_ctx = *holder->GetAST(); - DWARFASTParserClangStub ast_parser(ast_ctx); + DWARFASTParserClangYAMLTester tester(BufferOrError.get()->getBuffer()); + DWARFDIE cu_die = tester.GetCUDIE(); llvm::SmallVector<lldb::TypeSP, 2> specializations; for (DWARFDIE die : cu_die.children()) { SymbolContext sc; bool new_type = false; - auto type = ast_parser.ParseTypeFromDWARF(sc, die, &new_type); + auto type = tester.GetParser().ParseTypeFromDWARF(sc, die, &new_type); llvm::StringRef die_name = llvm::StringRef(die.GetName()); if (die_name.starts_with("_Optional_payload")) { specializations.push_back(std::move(type)); @@ -730,18 +743,8 @@ TEST_F(DWARFASTParserClangTests, TestUniqueDWARFASTTypeMap_CppInsertMapFind) { - AbbrCode: 0x00 # end of child tags of 0x0c ... )"; - YAMLModuleTester t(yamldata); - - DWARFUnit *unit = t.GetDwarfUnit(); - ASSERT_NE(unit, nullptr); - const DWARFDebugInfoEntry *cu_entry = unit->DIE().GetDIE(); - ASSERT_EQ(cu_entry->Tag(), DW_TAG_compile_unit); - ASSERT_EQ(unit->GetDWARFLanguageType(), DW_LANG_C_plus_plus); - DWARFDIE cu_die(unit, cu_entry); - - auto holder = std::make_unique<clang_utils::TypeSystemClangHolder>("ast"); - auto &ast_ctx = *holder->GetAST(); - DWARFASTParserClangStub ast_parser(ast_ctx); + DWARFASTParserClangYAMLTester tester(yamldata); + DWARFDIE cu_die = tester.GetCUDIE(); DWARFDIE decl_die; DWARFDIE def_die; @@ -762,6 +765,8 @@ TEST_F(DWARFASTParserClangTests, TestUniqueDWARFASTTypeMap_CppInsertMapFind) { ParsedDWARFTypeAttributes attrs(def_die); ASSERT_TRUE(attrs.decl.IsValid()); + DWARFASTParserClang &ast_parser = tester.GetParser(); + SymbolContext sc; bool new_type = false; lldb::TypeSP type_sp = ast_parser.ParseTypeFromDWARF(sc, decl_die, &new_type); @@ -906,18 +911,8 @@ TEST_F(DWARFASTParserClangTests, TestObjectPointer) { - AbbrCode: 0x0 ... )"; - YAMLModuleTester t(yamldata); - - DWARFUnit *unit = t.GetDwarfUnit(); - ASSERT_NE(unit, nullptr); - const DWARFDebugInfoEntry *cu_entry = unit->DIE().GetDIE(); - ASSERT_EQ(cu_entry->Tag(), DW_TAG_compile_unit); - ASSERT_EQ(unit->GetDWARFLanguageType(), DW_LANG_C_plus_plus); - DWARFDIE cu_die(unit, cu_entry); - - auto holder = std::make_unique<clang_utils::TypeSystemClangHolder>("ast"); - auto &ast_ctx = *holder->GetAST(); - DWARFASTParserClangStub ast_parser(ast_ctx); + DWARFASTParserClangYAMLTester tester(yamldata); + DWARFDIE cu_die = tester.GetCUDIE(); auto context_die = cu_die.GetFirstChild(); ASSERT_TRUE(context_die.IsValid()); @@ -932,7 +927,8 @@ TEST_F(DWARFASTParserClangTests, TestObjectPointer) { auto param_die = decl_die.GetFirstChild(); ASSERT_TRUE(param_die.IsValid()); - EXPECT_EQ(param_die, ast_parser.GetObjectParameter(decl_die, context_die)); + EXPECT_EQ(param_die, + tester.GetParser().GetObjectParameter(decl_die, context_die)); } { @@ -945,8 +941,8 @@ TEST_F(DWARFASTParserClangTests, TestObjectPointer) { auto param_die = subprogram_definition.GetFirstChild(); ASSERT_TRUE(param_die.IsValid()); - EXPECT_EQ(param_die, ast_parser.GetObjectParameter(subprogram_definition, - context_die)); + EXPECT_EQ(param_die, tester.GetParser().GetObjectParameter( + subprogram_definition, context_die)); } } @@ -1076,18 +1072,8 @@ TEST_F(DWARFASTParserClangTests, - AbbrCode: 0x0 ... )"; - YAMLModuleTester t(yamldata); - - DWARFUnit *unit = t.GetDwarfUnit(); - ASSERT_NE(unit, nullptr); - const DWARFDebugInfoEntry *cu_entry = unit->DIE().GetDIE(); - ASSERT_EQ(cu_entry->Tag(), DW_TAG_compile_unit); - ASSERT_EQ(unit->GetDWARFLanguageType(), DW_LANG_C_plus_plus); - DWARFDIE cu_die(unit, cu_entry); - - auto holder = std::make_unique<clang_utils::TypeSystemClangHolder>("ast"); - auto &ast_ctx = *holder->GetAST(); - DWARFASTParserClangStub ast_parser(ast_ctx); + DWARFASTParserClangYAMLTester tester(yamldata); + DWARFDIE cu_die = tester.GetCUDIE(); auto context_die = cu_die.GetFirstChild(); ASSERT_TRUE(context_die.IsValid()); @@ -1105,7 +1091,7 @@ TEST_F(DWARFASTParserClangTests, auto param_die = subprogram_definition.GetFirstChild(); ASSERT_TRUE(param_die.IsValid()); EXPECT_EQ(param_die, - ast_parser.GetObjectParameter(subprogram_definition, {})); + tester.GetParser().GetObjectParameter(subprogram_definition, {})); } TEST_F(DWARFASTParserClangTests, TestParseSubroutine_ExplicitObjectParameter) { @@ -1243,14 +1229,8 @@ TEST_F(DWARFASTParserClangTests, TestParseSubroutine_ExplicitObjectParameter) { - AbbrCode: 0x0 ... )"; - YAMLModuleTester t(yamldata); - - DWARFUnit *unit = t.GetDwarfUnit(); - ASSERT_NE(unit, nullptr); - const DWARFDebugInfoEntry *cu_entry = unit->DIE().GetDIE(); - ASSERT_EQ(cu_entry->Tag(), DW_TAG_compile_unit); - ASSERT_EQ(unit->GetDWARFLanguageType(), DW_LANG_C_plus_plus); - DWARFDIE cu_die(unit, cu_entry); + DWARFASTParserClangYAMLTester tester(yamldata); + DWARFDIE cu_die = tester.GetCUDIE(); auto ts_or_err = cu_die.GetDWARF()->GetTypeSystemForLanguage(eLanguageTypeC_plus_plus); @@ -1419,22 +1399,8 @@ TEST_F(DWARFASTParserClangTests, TestParseSubroutine_ParameterCreation) { - AbbrCode: 0x0 ... )"; - YAMLModuleTester t(yamldata); - - DWARFUnit *unit = t.GetDwarfUnit(); - ASSERT_NE(unit, nullptr); - const DWARFDebugInfoEntry *cu_entry = unit->DIE().GetDIE(); - ASSERT_EQ(cu_entry->Tag(), DW_TAG_compile_unit); - ASSERT_EQ(unit->GetDWARFLanguageType(), DW_LANG_C_plus_plus); - DWARFDIE cu_die(unit, cu_entry); - - auto ts_or_err = - cu_die.GetDWARF()->GetTypeSystemForLanguage(eLanguageTypeC_plus_plus); - ASSERT_TRUE(static_cast<bool>(ts_or_err)); - llvm::consumeError(ts_or_err.takeError()); - - auto *ts = static_cast<TypeSystemClang *>(ts_or_err->get()); - auto *parser = llvm::cast<DWARFASTParserClang>(ts->GetDWARFParser()); + DWARFASTParserClangYAMLTester tester(yamldata); + DWARFDIE cu_die = tester.GetCUDIE(); auto subprogram = cu_die.GetFirstChild(); ASSERT_TRUE(subprogram.IsValid()); @@ -1442,11 +1408,13 @@ TEST_F(DWARFASTParserClangTests, TestParseSubroutine_ParameterCreation) { SymbolContext sc; bool new_type; - auto type_sp = parser->ParseTypeFromDWARF(sc, subprogram, &new_type); + auto type_sp = + tester.GetParser().ParseTypeFromDWARF(sc, subprogram, &new_type); ASSERT_NE(type_sp, nullptr); - auto result = ts->GetTranslationUnitDecl()->lookup( - clang_utils::getDeclarationName(*ts, "func")); + TypeSystemClang &ts = tester.GetTypeSystem(); + auto result = ts.GetTranslationUnitDecl()->lookup( + clang_utils::getDeclarationName(ts, "func")); ASSERT_TRUE(result.isSingleResult()); auto const *func = llvm::cast<clang::FunctionDecl>(result.front()); @@ -1609,19 +1577,8 @@ TEST_F(DWARFASTParserClangTests, TestObjectPointer_IndexEncoding) { - AbbrCode: 0x0 ... )"; - - YAMLModuleTester t(yamldata); - - DWARFUnit *unit = t.GetDwarfUnit(); - ASSERT_NE(unit, nullptr); - const DWARFDebugInfoEntry *cu_entry = unit->DIE().GetDIE(); - ASSERT_EQ(cu_entry->Tag(), DW_TAG_compile_unit); - ASSERT_EQ(unit->GetDWARFLanguageType(), DW_LANG_C_plus_plus); - DWARFDIE cu_die(unit, cu_entry); - - auto holder = std::make_unique<clang_utils::TypeSystemClangHolder>("ast"); - auto &ast_ctx = *holder->GetAST(); - DWARFASTParserClangStub ast_parser(ast_ctx); + DWARFASTParserClangYAMLTester tester(yamldata); + DWARFDIE cu_die = tester.GetCUDIE(); auto context_die = cu_die.GetFirstChild(); ASSERT_TRUE(context_die.IsValid()); @@ -1640,7 +1597,8 @@ TEST_F(DWARFASTParserClangTests, TestObjectPointer_IndexEncoding) { auto param_die = sub1.GetFirstChild().GetSibling(); ASSERT_TRUE(param_die.IsValid()); - EXPECT_EQ(param_die, ast_parser.GetObjectParameter(sub1, context_die)); + EXPECT_EQ(param_die, + tester.GetParser().GetObjectParameter(sub1, context_die)); } // Object parameter is at constant index 0 @@ -1648,7 +1606,8 @@ TEST_F(DWARFASTParserClangTests, TestObjectPointer_IndexEncoding) { auto param_die = sub2.GetFirstChild(); ASSERT_TRUE(param_die.IsValid()); - EXPECT_EQ(param_die, ast_parser.GetObjectParameter(sub2, context_die)); + EXPECT_EQ(param_die, + tester.GetParser().GetObjectParameter(sub2, context_die)); } } @@ -1711,19 +1670,8 @@ TEST_F(DWARFASTParserClangTests, TestTypeBitSize) { - Value: 0x02 ... )"; - - YAMLModuleTester t(yamldata); - - DWARFUnit *unit = t.GetDwarfUnit(); - ASSERT_NE(unit, nullptr); - const DWARFDebugInfoEntry *cu_entry = unit->DIE().GetDIE(); - ASSERT_EQ(cu_entry->Tag(), DW_TAG_compile_unit); - ASSERT_EQ(unit->GetDWARFLanguageType(), DW_LANG_C_plus_plus); - DWARFDIE cu_die(unit, cu_entry); - - auto holder = std::make_unique<clang_utils::TypeSystemClangHolder>("ast"); - auto &ast_ctx = *holder->GetAST(); - DWARFASTParserClangStub ast_parser(ast_ctx); + DWARFASTParserClangYAMLTester tester(yamldata); + DWARFDIE cu_die = tester.GetCUDIE(); auto type_die = cu_die.GetFirstChild(); ASSERT_TRUE(type_die.IsValid()); @@ -1734,8 +1682,8 @@ TEST_F(DWARFASTParserClangTests, TestTypeBitSize) { EXPECT_EQ(attrs.data_bit_size.value_or(0), 2U); SymbolContext sc; - auto type_sp = - ast_parser.ParseTypeFromDWARF(sc, type_die, /*type_is_new_ptr=*/nullptr); + auto type_sp = tester.GetParser().ParseTypeFromDWARF( + sc, type_die, /*type_is_new_ptr=*/nullptr); ASSERT_NE(type_sp, nullptr); EXPECT_EQ(llvm::expectedToOptional(type_sp->GetByteSize(nullptr)).value_or(0), @@ -1857,27 +1805,17 @@ TEST_F(DWARFASTParserClangTests, TestBitIntParsing) { ... )"; - - YAMLModuleTester t(yamldata); - - DWARFUnit *unit = t.GetDwarfUnit(); - ASSERT_NE(unit, nullptr); - const DWARFDebugInfoEntry *cu_entry = unit->DIE().GetDIE(); - ASSERT_EQ(cu_entry->Tag(), DW_TAG_compile_unit); - ASSERT_EQ(unit->GetDWARFLanguageType(), DW_LANG_C_plus_plus); - DWARFDIE cu_die(unit, cu_entry); - - auto holder = std::make_unique<clang_utils::TypeSystemClangHolder>("ast"); - auto &ast_ctx = *holder->GetAST(); - DWARFASTParserClangStub ast_parser(ast_ctx); + DWARFASTParserClangYAMLTester tester(yamldata); + DWARFDIE cu_die = tester.GetCUDIE(); auto type_die = cu_die.GetFirstChild(); ASSERT_TRUE(type_die.IsValid()); { SymbolContext sc; - auto type_sp = ast_parser.ParseTypeFromDWARF(sc, type_die, - /*type_is_new_ptr=*/nullptr); + auto type_sp = + tester.GetParser().ParseTypeFromDWARF(sc, type_die, + /*type_is_new_ptr=*/nullptr); ASSERT_NE(type_sp, nullptr); EXPECT_EQ( @@ -1891,8 +1829,9 @@ TEST_F(DWARFASTParserClangTests, TestBitIntParsing) { { type_die = type_die.GetSibling(); SymbolContext sc; - auto type_sp = ast_parser.ParseTypeFromDWARF(sc, type_die, - /*type_is_new_ptr=*/nullptr); + auto type_sp = + tester.GetParser().ParseTypeFromDWARF(sc, type_die, + /*type_is_new_ptr=*/nullptr); ASSERT_NE(type_sp, nullptr); EXPECT_EQ( @@ -1906,8 +1845,9 @@ TEST_F(DWARFASTParserClangTests, TestBitIntParsing) { { type_die = type_die.GetSibling(); SymbolContext sc; - auto type_sp = ast_parser.ParseTypeFromDWARF(sc, type_die, - /*type_is_new_ptr=*/nullptr); + auto type_sp = + tester.GetParser().ParseTypeFromDWARF(sc, type_die, + /*type_is_new_ptr=*/nullptr); ASSERT_NE(type_sp, nullptr); EXPECT_EQ( @@ -1922,8 +1862,9 @@ TEST_F(DWARFASTParserClangTests, TestBitIntParsing) { { type_die = type_die.GetSibling(); SymbolContext sc; - auto type_sp = ast_parser.ParseTypeFromDWARF(sc, type_die, - /*type_is_new_ptr=*/nullptr); + auto type_sp = + tester.GetParser().ParseTypeFromDWARF(sc, type_die, + /*type_is_new_ptr=*/nullptr); ASSERT_NE(type_sp, nullptr); EXPECT_EQ( @@ -1938,8 +1879,9 @@ TEST_F(DWARFASTParserClangTests, TestBitIntParsing) { { type_die = type_die.GetSibling(); SymbolContext sc; - auto type_sp = ast_parser.ParseTypeFromDWARF(sc, type_die, - /*type_is_new_ptr=*/nullptr); + auto type_sp = + tester.GetParser().ParseTypeFromDWARF(sc, type_die, + /*type_is_new_ptr=*/nullptr); ASSERT_NE(type_sp, nullptr); EXPECT_EQ( >From 3401bc58fbc14899d7d2e843831eb8b44edca36c Mon Sep 17 00:00:00 2001 From: Michael Buch <[email protected]> Date: Mon, 1 Dec 2025 18:48:28 +0900 Subject: [PATCH 3/3] [lldb][DWARFASTParserClang] Treat DW_TAG_template_alias like we do DW_TAG_typedef Depends on: * https://github.com/llvm/llvm-project/pull/170132 Clang gained the `-gtemplate-alias` not too long ago, which emits C++ alias templates as `DW_TAG_template_alias` (instead of `DW_TAG_typedef`). The main difference is that `DW_TAG_template_alias` has `DW_TAG_template_XXX` children. The flag was not enabled by default because consumers (mainly LLDB) didn't know how to handle it. This patch adds rudimentary support for debugging with `DW_TAG_template_alias`. This patch simply creates the same kind of `TypedefDecl` as we do for `DW_TAG_typedef`. The more complete solution would be to create a `TypeAliasTemplateDecl` and associated `TypeAliasDecl`. But that would require DWARF to carry generic template information, but currently each `DW_TAG_template_alias` represents a concrete instantiation. We could probably hack up some working AST representation that includes the template parameters, but I currently don't see a compelling reason to. All we need is the `DW_AT_name` and the `DW_AT_type` that the typedef refers to. One compelling reason to support `DW_TAG_template_alias` is that with `-gsimple-template-names`, `DW_TAG_typedef`s for alias templates have their template parameters stripped from the `DW_AT_name`. With just a plain `DW_TAG_typedef`, LLDB has no way to reconstruct the full `DW_AT_name`. But since `DW_TAG_template_alias` can carry template parameter children, LLDB can reconstitute the name by concatenating the `DW_AT_name`s of the child tags. --- .../SymbolFile/DWARF/DWARFASTParserClang.cpp | 4 +- .../DWARF/DWARFASTParserClangTests.cpp | 220 ++++++++++++++++++ 2 files changed, 223 insertions(+), 1 deletion(-) diff --git a/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp b/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp index 7160c6eec564b..d65aa40b5be86 100644 --- a/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp +++ b/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp @@ -623,6 +623,7 @@ TypeSP DWARFASTParserClang::ParseTypeFromDWARF(const SymbolContext &sc, switch (tag) { case DW_TAG_typedef: + case DW_TAG_template_alias: case DW_TAG_base_type: case DW_TAG_pointer_type: case DW_TAG_reference_type: @@ -748,7 +749,7 @@ DWARFASTParserClang::ParseTypeModifier(const SymbolContext &sc, TypeSP type_sp; CompilerType clang_type; - if (tag == DW_TAG_typedef) { + if (tag == DW_TAG_typedef || tag == DW_TAG_template_alias) { // DeclContext will be populated when the clang type is materialized in // Type::ResolveCompilerType. PrepareContextToReceiveMembers( @@ -836,6 +837,7 @@ DWARFASTParserClang::ParseTypeModifier(const SymbolContext &sc, encoding_data_type = Type::eEncodingIsRValueReferenceUID; break; case DW_TAG_typedef: + case DW_TAG_template_alias: encoding_data_type = Type::eEncodingIsTypedefUID; break; case DW_TAG_const_type: diff --git a/lldb/unittests/SymbolFile/DWARF/DWARFASTParserClangTests.cpp b/lldb/unittests/SymbolFile/DWARF/DWARFASTParserClangTests.cpp index 37e7b601db9d9..5d2d7ae6dcc40 100644 --- a/lldb/unittests/SymbolFile/DWARF/DWARFASTParserClangTests.cpp +++ b/lldb/unittests/SymbolFile/DWARF/DWARFASTParserClangTests.cpp @@ -1895,3 +1895,223 @@ TEST_F(DWARFASTParserClangTests, TestBitIntParsing) { EXPECT_EQ(type_sp->GetForwardCompilerType().GetTypeName(), "_BitInt(64)"); } } + +TEST_F(DWARFASTParserClangTests, TestTemplateAlias_NoSimpleTemplateNames) { + // Tests that we correctly parse the DW_TAG_template_alias generated by + // -gno-simple-template-names. + + const char *yamldata = R"( +--- !ELF +FileHeader: + Class: ELFCLASS64 + Data: ELFDATA2LSB + Type: ET_EXEC + Machine: EM_AARCH64 +DWARF: + debug_abbrev: + - ID: 0 + Table: + - Code: 0x1 + Tag: DW_TAG_compile_unit + Children: DW_CHILDREN_yes + Attributes: + - Attribute: DW_AT_language + Form: DW_FORM_data2 + - Code: 0x2 + Tag: DW_TAG_base_type + Children: DW_CHILDREN_no + Attributes: + - Attribute: DW_AT_name + Form: DW_FORM_string + - Code: 0x3 + Tag: DW_TAG_template_alias + Children: DW_CHILDREN_yes + Attributes: + - Attribute: DW_AT_name + Form: DW_FORM_string + - Attribute: DW_AT_type + Form: DW_FORM_ref4 + - Code: 0x4 + Tag: DW_TAG_template_type_parameter + Children: DW_CHILDREN_no + Attributes: + - Attribute: DW_AT_name + Form: DW_FORM_string + - Attribute: DW_AT_type + Form: DW_FORM_ref4 + + debug_info: + - Version: 5 + UnitType: DW_UT_compile + AddrSize: 8 + Entries: + +# DW_TAG_compile_unit +# DW_AT_language (DW_LANG_C_plus_plus) + + - AbbrCode: 0x1 + Values: + - Value: 0x04 + +# DW_TAG_base_type +# DW_AT_name ('int') + + - AbbrCode: 0x2 + Values: + - CStr: int + +# DW_TAG_template_alias +# DW_AT_name ('Foo<int>') +# DW_AT_type ('int') +# DW_TAG_template_type_parameter +# DW_AT_name ('T') +# DW_AT_type ('int') + + - AbbrCode: 0x3 + Values: + - CStr: Foo<int> + - Value: 0xf + + - AbbrCode: 0x4 + Values: + - CStr: T + - Value: 0xf + + - AbbrCode: 0x0 + - AbbrCode: 0x0 +... +)"; + DWARFASTParserClangYAMLTester tester(yamldata); + DWARFDIE cu_die = tester.GetCUDIE(); + + auto alias_die = cu_die.GetFirstChild().GetSibling(); + ASSERT_EQ(alias_die.Tag(), DW_TAG_template_alias); + + SymbolContext sc; + auto type_sp = + tester.GetParser().ParseTypeFromDWARF(sc, alias_die, + /*type_is_new_ptr=*/nullptr); + ASSERT_NE(type_sp, nullptr); + + EXPECT_TRUE(type_sp->IsTypedef()); + EXPECT_EQ(type_sp->GetName(), "Foo<int>"); + EXPECT_EQ(type_sp->GetForwardCompilerType().GetTypeName(), "Foo<int>"); +} + +TEST_F(DWARFASTParserClangTests, TestTemplateAlias_InStruct_NoSimpleTemplateNames) { + // Tests that we correctly parse the DW_TAG_template_alias scoped inside a DW_TAG_structure_type + // *declaration* generated by -gno-simple-template-names. + + const char *yamldata = R"( +--- !ELF +FileHeader: + Class: ELFCLASS64 + Data: ELFDATA2LSB + Type: ET_EXEC + Machine: EM_AARCH64 +DWARF: + debug_abbrev: + - ID: 0 + Table: + - Code: 0x1 + Tag: DW_TAG_compile_unit + Children: DW_CHILDREN_yes + Attributes: + - Attribute: DW_AT_language + Form: DW_FORM_data2 + - Code: 0x2 + Tag: DW_TAG_base_type + Children: DW_CHILDREN_no + Attributes: + - Attribute: DW_AT_name + Form: DW_FORM_string + - Code: 0x3 + Tag: DW_TAG_structure_type + Children: DW_CHILDREN_yes + Attributes: + - Attribute: DW_AT_name + Form: DW_FORM_string + - Attribute: DW_AT_declaration + Form: DW_FORM_flag_present + - Code: 0x4 + Tag: DW_TAG_template_alias + Children: DW_CHILDREN_yes + Attributes: + - Attribute: DW_AT_name + Form: DW_FORM_string + - Attribute: DW_AT_type + Form: DW_FORM_ref4 + - Code: 0x5 + Tag: DW_TAG_template_type_parameter + Children: DW_CHILDREN_no + Attributes: + - Attribute: DW_AT_name + Form: DW_FORM_string + - Attribute: DW_AT_type + Form: DW_FORM_ref4 + + debug_info: + - Version: 5 + UnitType: DW_UT_compile + AddrSize: 8 + Entries: + +# DW_TAG_compile_unit +# DW_AT_language (DW_LANG_C_plus_plus) + + - AbbrCode: 0x1 + Values: + - Value: 0x04 + +# DW_TAG_base_type +# DW_AT_name ('int') + + - AbbrCode: 0x2 + Values: + - CStr: int + +# DW_TAG_structure_type +# DW_AT_name ('Foo') + + - AbbrCode: 0x3 + Values: + - CStr: Foo + +# DW_TAG_template_alias +# DW_AT_name ('Bar<int>') +# DW_AT_type ('int') +# DW_TAG_template_type_parameter +# DW_AT_name ('T') +# DW_AT_type ('int') + + - AbbrCode: 0x4 + Values: + - CStr: Bar<int> + - Value: 0xf + + - AbbrCode: 0x5 + Values: + - CStr: T + - Value: 0xf + + - AbbrCode: 0x0 + - AbbrCode: 0x0 + - AbbrCode: 0x0 +... +)"; + DWARFASTParserClangYAMLTester tester(yamldata); + DWARFDIE cu_die = tester.GetCUDIE(); + + auto alias_die = cu_die.GetFirstChild().GetSibling().GetFirstChild(); + ASSERT_EQ(alias_die.Tag(), DW_TAG_template_alias); + + SymbolContext sc; + auto type_sp = + tester.GetParser().ParseTypeFromDWARF(sc, alias_die, + /*type_is_new_ptr=*/nullptr); + ASSERT_NE(type_sp, nullptr); + + EXPECT_TRUE(type_sp->IsTypedef()); + EXPECT_EQ(type_sp->GetName(), "Bar<int>"); + EXPECT_EQ(type_sp->GetForwardCompilerType().GetTypeName(), "Foo::Bar<int>"); +} _______________________________________________ lldb-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
