https://github.com/Michael137 created https://github.com/llvm/llvm-project/pull/170135
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. >From d8a151fbcadbb3afe8fcd1f6b9cdb583959f215c Mon Sep 17 00:00:00 2001 From: Michael Buch <[email protected]> Date: Mon, 1 Dec 2025 22:05:46 +0900 Subject: [PATCH 1/2] [lldb][test] DWARFASTParserClangTests: extract test setup into helper structure 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 | 293 +++++++----------- 1 file changed, 111 insertions(+), 182 deletions(-) diff --git a/lldb/unittests/SymbolFile/DWARF/DWARFASTParserClangTests.cpp b/lldb/unittests/SymbolFile/DWARF/DWARFASTParserClangTests.cpp index cef3a25a4a960..bd7aed8d8c2aa 100644 --- a/lldb/unittests/SymbolFile/DWARF/DWARFASTParserClangTests.cpp +++ b/lldb/unittests/SymbolFile/DWARF/DWARFASTParserClangTests.cpp @@ -42,6 +42,46 @@ 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 creates a DWARFASTParserClang and TypeSystem that +/// live for the duration of this object. +class DWARFASTParserClangYAMLTester { +public: + DWARFASTParserClangYAMLTester(llvm::StringRef yaml_data) + : m_module_tester(yaml_data), + m_ast_holder_up( + std::make_unique<clang_utils::TypeSystemClangHolder>("ast")), + m_stub(*m_ast_holder_up->GetAST()) {} + + 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); + } + + DWARFASTParserClangStub &GetParser() { return m_stub; } + + TypeSystemClang &GetTypeSystem() { + assert(m_ast_holder_up); + + TypeSystemClang *ts = m_ast_holder_up->GetAST(); + + assert(ts); + + return *ts; + } + +private: + YAMLModuleTester m_module_tester; + std::unique_ptr<clang_utils::TypeSystemClangHolder> m_ast_holder_up; + DWARFASTParserClangStub m_stub; +}; } // namespace // If your implementation needs to dereference the dummy pointers we are @@ -100,23 +140,15 @@ TEST_F(DWARFASTParserClangTests, - AbbrCode: 0x00000000 )"; - YAMLModuleTester t(yamldata); - ASSERT_TRUE((bool)t.GetDwarfUnit()); - - auto holder = std::make_unique<clang_utils::TypeSystemClangHolder>("ast"); - auto &ast_ctx = *holder->GetAST(); + DWARFASTParserClangYAMLTester tester(yamldata); + DWARFASTParserClangStub &ast_parser = tester.GetParser(); - DWARFASTParserClangStub ast_parser(ast_ctx); - - DWARFUnit *unit = t.GetDwarfUnit(); - const DWARFDebugInfoEntry *die_first = unit->DIE().GetDIE(); - const DWARFDebugInfoEntry *die_child0 = die_first->GetFirstChild(); - const DWARFDebugInfoEntry *die_child1 = die_child0->GetSibling(); - const DWARFDebugInfoEntry *die_child2 = die_child1->GetSibling(); - const DWARFDebugInfoEntry *die_child3 = die_child2->GetSibling(); - std::vector<DWARFDIE> dies = { - DWARFDIE(unit, die_child0), DWARFDIE(unit, die_child1), - DWARFDIE(unit, die_child2), DWARFDIE(unit, die_child3)}; + DWARFDIE die_first = tester.GetCUDIE(); + DWARFDIE die_child0 = die_first.GetFirstChild(); + DWARFDIE die_child1 = die_child0.GetSibling(); + DWARFDIE die_child2 = die_child1.GetSibling(); + DWARFDIE die_child3 = die_child2.GetSibling(); + std::vector<DWARFDIE> dies = {die_child0, die_child1, die_child2, die_child3}; std::vector<clang::DeclContext *> decl_ctxs = { (clang::DeclContext *)1LL, (clang::DeclContext *)2LL, (clang::DeclContext *)2LL, (clang::DeclContext *)3LL}; @@ -248,17 +280,9 @@ TEST_F(DWARFASTParserClangTests, TestCallingConventionParsing) { - 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); - DWARFDIE cu_die(unit, cu_entry); + DWARFASTParserClangYAMLTester tester(yamldata); - 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 +291,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 +419,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 +431,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 +570,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 +614,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 +730,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 +752,8 @@ TEST_F(DWARFASTParserClangTests, TestUniqueDWARFASTTypeMap_CppInsertMapFind) { ParsedDWARFTypeAttributes attrs(def_die); ASSERT_TRUE(attrs.decl.IsValid()); + DWARFASTParserClangStub &ast_parser = tester.GetParser(); + SymbolContext sc; bool new_type = false; lldb::TypeSP type_sp = ast_parser.ParseTypeFromDWARF(sc, decl_die, &new_type); @@ -906,18 +898,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 +914,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 +928,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 +1059,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 +1078,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 +1216,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 +1386,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 = static_cast<DWARFASTParserClang *>(ts->GetDWARFParser()); + DWARFASTParserClangYAMLTester tester(yamldata); + DWARFDIE cu_die = tester.GetCUDIE(); auto subprogram = cu_die.GetFirstChild(); ASSERT_TRUE(subprogram.IsValid()); @@ -1442,11 +1395,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 +1564,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 +1584,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 +1593,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 +1657,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 +1669,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 +1792,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 +1816,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 +1832,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 +1849,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 +1866,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 7c2317564d8bd07e4c2ac15d2bb8514997040786 Mon Sep 17 00:00:00 2001 From: Michael Buch <[email protected]> Date: Mon, 1 Dec 2025 18:48:28 +0900 Subject: [PATCH 2/2] [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 | 100 ++++++++++++++++++ 2 files changed, 103 insertions(+), 1 deletion(-) diff --git a/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp b/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp index 36aa49ac3de95..3d556aea7b183 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 bd7aed8d8c2aa..9e2722d53cc6d 100644 --- a/lldb/unittests/SymbolFile/DWARF/DWARFASTParserClangTests.cpp +++ b/lldb/unittests/SymbolFile/DWARF/DWARFASTParserClangTests.cpp @@ -12,6 +12,7 @@ #include "TestingSupport/Symbol/ClangTestUtils.h" #include "TestingSupport/Symbol/YAMLModuleTester.h" #include "lldb/Core/Debugger.h" +#include "lldb/Symbol/Type.h" #include "gmock/gmock.h" #include "gtest/gtest.h" @@ -1882,3 +1883,102 @@ 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 +... +)"; + DWARFASTParserClangYAMLTester tester(yamldata); + DWARFDIE cu_die = tester.GetCUDIE(); + + auto alias_die = cu_die.GetFirstChild().GetSibling(); + ASSERT_TRUE(alias_die.IsValid()); + + 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>"); +} _______________________________________________ lldb-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
