Skip to content

Commit 83792f3

Browse files
committed
[lldb][DWARFASTParserClang] Treat DW_TAG_template_alias like we do DW_TAG_typedef
Depends on: * #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.
1 parent d8a151f commit 83792f3

File tree

2 files changed

+102
-1
lines changed

2 files changed

+102
-1
lines changed

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

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -623,6 +623,7 @@ TypeSP DWARFASTParserClang::ParseTypeFromDWARF(const SymbolContext &sc,
623623

624624
switch (tag) {
625625
case DW_TAG_typedef:
626+
case DW_TAG_template_alias:
626627
case DW_TAG_base_type:
627628
case DW_TAG_pointer_type:
628629
case DW_TAG_reference_type:
@@ -748,7 +749,7 @@ DWARFASTParserClang::ParseTypeModifier(const SymbolContext &sc,
748749
TypeSP type_sp;
749750
CompilerType clang_type;
750751

751-
if (tag == DW_TAG_typedef) {
752+
if (tag == DW_TAG_typedef || tag == DW_TAG_template_alias) {
752753
// DeclContext will be populated when the clang type is materialized in
753754
// Type::ResolveCompilerType.
754755
PrepareContextToReceiveMembers(
@@ -836,6 +837,7 @@ DWARFASTParserClang::ParseTypeModifier(const SymbolContext &sc,
836837
encoding_data_type = Type::eEncodingIsRValueReferenceUID;
837838
break;
838839
case DW_TAG_typedef:
840+
case DW_TAG_template_alias:
839841
encoding_data_type = Type::eEncodingIsTypedefUID;
840842
break;
841843
case DW_TAG_const_type:

lldb/unittests/SymbolFile/DWARF/DWARFASTParserClangTests.cpp

Lines changed: 99 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1882,3 +1882,102 @@ TEST_F(DWARFASTParserClangTests, TestBitIntParsing) {
18821882
EXPECT_EQ(type_sp->GetForwardCompilerType().GetTypeName(), "_BitInt(64)");
18831883
}
18841884
}
1885+
1886+
TEST_F(DWARFASTParserClangTests, TestTemplateAlias_NoSimpleTemplateNames) {
1887+
// Tests that we correctly parse the DW_TAG_template_alias generated by
1888+
// -gno-simple-template-names.
1889+
1890+
const char *yamldata = R"(
1891+
--- !ELF
1892+
FileHeader:
1893+
Class: ELFCLASS64
1894+
Data: ELFDATA2LSB
1895+
Type: ET_EXEC
1896+
Machine: EM_AARCH64
1897+
DWARF:
1898+
debug_abbrev:
1899+
- ID: 0
1900+
Table:
1901+
- Code: 0x1
1902+
Tag: DW_TAG_compile_unit
1903+
Children: DW_CHILDREN_yes
1904+
Attributes:
1905+
- Attribute: DW_AT_language
1906+
Form: DW_FORM_data2
1907+
- Code: 0x2
1908+
Tag: DW_TAG_base_type
1909+
Children: DW_CHILDREN_no
1910+
Attributes:
1911+
- Attribute: DW_AT_name
1912+
Form: DW_FORM_string
1913+
- Code: 0x3
1914+
Tag: DW_TAG_template_alias
1915+
Children: DW_CHILDREN_yes
1916+
Attributes:
1917+
- Attribute: DW_AT_name
1918+
Form: DW_FORM_string
1919+
- Attribute: DW_AT_type
1920+
Form: DW_FORM_ref4
1921+
- Code: 0x4
1922+
Tag: DW_TAG_template_type_parameter
1923+
Children: DW_CHILDREN_no
1924+
Attributes:
1925+
- Attribute: DW_AT_name
1926+
Form: DW_FORM_string
1927+
- Attribute: DW_AT_type
1928+
Form: DW_FORM_ref4
1929+
1930+
debug_info:
1931+
- Version: 5
1932+
UnitType: DW_UT_compile
1933+
AddrSize: 8
1934+
Entries:
1935+
1936+
# DW_TAG_compile_unit
1937+
# DW_AT_language (DW_LANG_C_plus_plus)
1938+
1939+
- AbbrCode: 0x1
1940+
Values:
1941+
- Value: 0x04
1942+
1943+
# DW_TAG_base_type
1944+
# DW_AT_name ('int')
1945+
1946+
- AbbrCode: 0x2
1947+
Values:
1948+
- CStr: int
1949+
1950+
# DW_TAG_template_alias
1951+
# DW_AT_name ('Foo<int>')
1952+
# DW_AT_type ('int')
1953+
# DW_TAG_template_type_parameter
1954+
# DW_AT_name ('T')
1955+
# DW_AT_type ('int')
1956+
1957+
- AbbrCode: 0x3
1958+
Values:
1959+
- CStr: Foo<int>
1960+
- Value: 0xf
1961+
1962+
- AbbrCode: 0x4
1963+
Values:
1964+
- CStr: T
1965+
- Value: 0xf
1966+
...
1967+
)";
1968+
DWARFASTParserClangYAMLTester tester(yamldata);
1969+
DWARFDIE cu_die = tester.GetCUDIE();
1970+
1971+
auto alias_die = cu_die.GetFirstChild().GetSibling();
1972+
ASSERT_TRUE(alias_die.IsValid());
1973+
1974+
SymbolContext sc;
1975+
auto type_sp =
1976+
tester.GetParser().ParseTypeFromDWARF(sc, alias_die,
1977+
/*type_is_new_ptr=*/nullptr);
1978+
ASSERT_NE(type_sp, nullptr);
1979+
1980+
EXPECT_TRUE(type_sp->IsTypedef());
1981+
EXPECT_EQ(type_sp->GetName(), "Foo<int>");
1982+
EXPECT_EQ(type_sp->GetForwardCompilerType().GetTypeName(), "Foo<int>");
1983+
}

0 commit comments

Comments
 (0)