[Lldb-commits] [lldb] [lldb][DWARFASTParserClang] Treat DW_TAG_template_alias like we do DW_TAG_typedef (PR #170135)
Michael Buch via lldb-commits
lldb-commits at lists.llvm.org
Tue Dec 2 18:01:16 PST 2025
https://github.com/Michael137 updated https://github.com/llvm/llvm-project/pull/170135
>From 8eefaa41dc8318f9b06ec19246358981c2db3083 Mon Sep 17 00:00:00 2001
From: Michael Buch <michaelbuch12 at gmail.com>
Date: Mon, 1 Dec 2025 22:05:46 +0900
Subject: [PATCH 1/4] [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.
---
lldb/unittests/SymbolFile/DWARF/DWARFASTParserClangTests.cpp | 1 -
1 file changed, 1 deletion(-)
diff --git a/lldb/unittests/SymbolFile/DWARF/DWARFASTParserClangTests.cpp b/lldb/unittests/SymbolFile/DWARF/DWARFASTParserClangTests.cpp
index 642dde9924f3a..f8afd70b32271 100644
--- a/lldb/unittests/SymbolFile/DWARF/DWARFASTParserClangTests.cpp
+++ b/lldb/unittests/SymbolFile/DWARF/DWARFASTParserClangTests.cpp
@@ -145,7 +145,6 @@ TEST_F(DWARFASTParserClangTests,
- Value: 0x0000000000000001
- AbbrCode: 0x00000000
)";
-
YAMLModuleTester t(yamldata);
ASSERT_TRUE((bool)t.GetDwarfUnit());
>From 5e0fa9fb269a560bb61a15d4b38aa90c05abd062 Mon Sep 17 00:00:00 2001
From: Michael Buch <michaelbuch12 at gmail.com>
Date: Mon, 1 Dec 2025 18:48:28 +0900
Subject: [PATCH 2/4] [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 f8afd70b32271..ef4cf3285ffe3 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>");
+}
>From 2c68458b3b387e924b546907842b72b19f0917ba Mon Sep 17 00:00:00 2001
From: Michael Buch <michaelbuch12 at gmail.com>
Date: Tue, 2 Dec 2025 16:10:00 +0900
Subject: [PATCH 3/4] fixup! clang-format
---
.../SymbolFile/DWARF/DWARFASTParserClangTests.cpp | 8 +++++---
1 file changed, 5 insertions(+), 3 deletions(-)
diff --git a/lldb/unittests/SymbolFile/DWARF/DWARFASTParserClangTests.cpp b/lldb/unittests/SymbolFile/DWARF/DWARFASTParserClangTests.cpp
index ef4cf3285ffe3..5e82c50d375d6 100644
--- a/lldb/unittests/SymbolFile/DWARF/DWARFASTParserClangTests.cpp
+++ b/lldb/unittests/SymbolFile/DWARF/DWARFASTParserClangTests.cpp
@@ -1998,9 +1998,11 @@ TEST_F(DWARFASTParserClangTests, TestTemplateAlias_NoSimpleTemplateNames) {
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.
+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
>From 50c73e80dd630a316e1b0a8e83d02f5ab6d92869 Mon Sep 17 00:00:00 2001
From: Michael Buch <michaelbuch12 at gmail.com>
Date: Tue, 2 Dec 2025 16:11:20 +0900
Subject: [PATCH 4/4] fixup! elaborate on test comment
---
lldb/unittests/SymbolFile/DWARF/DWARFASTParserClangTests.cpp | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/lldb/unittests/SymbolFile/DWARF/DWARFASTParserClangTests.cpp b/lldb/unittests/SymbolFile/DWARF/DWARFASTParserClangTests.cpp
index 5e82c50d375d6..6a753b6b33edf 100644
--- a/lldb/unittests/SymbolFile/DWARF/DWARFASTParserClangTests.cpp
+++ b/lldb/unittests/SymbolFile/DWARF/DWARFASTParserClangTests.cpp
@@ -2002,7 +2002,8 @@ 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.
+ // -gno-simple-template-names. This tests the codepath the forcefully
+ // completes the context of the alias via PrepareContextToReceiveMembers.
const char *yamldata = R"(
--- !ELF
More information about the lldb-commits
mailing list