Skip to content

Commit 1f35b52

Browse files
authored
[lldb][DWARFASTParserClang] Treat DW_TAG_template_alias like we do DW_TAG_typedef (llvm#170135)
Depends on: * llvm#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. rdar://137499401
1 parent 1c86f4a commit 1f35b52

File tree

2 files changed

+226
-2
lines changed

2 files changed

+226
-2
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: 223 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -145,7 +145,6 @@ TEST_F(DWARFASTParserClangTests,
145145
- Value: 0x0000000000000001
146146
- AbbrCode: 0x00000000
147147
)";
148-
149148
YAMLModuleTester t(yamldata);
150149
ASSERT_TRUE((bool)t.GetDwarfUnit());
151150

@@ -1896,3 +1895,226 @@ TEST_F(DWARFASTParserClangTests, TestBitIntParsing) {
18961895
EXPECT_EQ(type_sp->GetForwardCompilerType().GetTypeName(), "_BitInt(64)");
18971896
}
18981897
}
1898+
1899+
TEST_F(DWARFASTParserClangTests, TestTemplateAlias_NoSimpleTemplateNames) {
1900+
// Tests that we correctly parse the DW_TAG_template_alias generated by
1901+
// -gno-simple-template-names.
1902+
1903+
const char *yamldata = R"(
1904+
--- !ELF
1905+
FileHeader:
1906+
Class: ELFCLASS64
1907+
Data: ELFDATA2LSB
1908+
Type: ET_EXEC
1909+
Machine: EM_AARCH64
1910+
DWARF:
1911+
debug_abbrev:
1912+
- ID: 0
1913+
Table:
1914+
- Code: 0x1
1915+
Tag: DW_TAG_compile_unit
1916+
Children: DW_CHILDREN_yes
1917+
Attributes:
1918+
- Attribute: DW_AT_language
1919+
Form: DW_FORM_data2
1920+
- Code: 0x2
1921+
Tag: DW_TAG_base_type
1922+
Children: DW_CHILDREN_no
1923+
Attributes:
1924+
- Attribute: DW_AT_name
1925+
Form: DW_FORM_string
1926+
- Code: 0x3
1927+
Tag: DW_TAG_template_alias
1928+
Children: DW_CHILDREN_yes
1929+
Attributes:
1930+
- Attribute: DW_AT_name
1931+
Form: DW_FORM_string
1932+
- Attribute: DW_AT_type
1933+
Form: DW_FORM_ref4
1934+
- Code: 0x4
1935+
Tag: DW_TAG_template_type_parameter
1936+
Children: DW_CHILDREN_no
1937+
Attributes:
1938+
- Attribute: DW_AT_name
1939+
Form: DW_FORM_string
1940+
- Attribute: DW_AT_type
1941+
Form: DW_FORM_ref4
1942+
1943+
debug_info:
1944+
- Version: 5
1945+
UnitType: DW_UT_compile
1946+
AddrSize: 8
1947+
Entries:
1948+
1949+
# DW_TAG_compile_unit
1950+
# DW_AT_language (DW_LANG_C_plus_plus)
1951+
1952+
- AbbrCode: 0x1
1953+
Values:
1954+
- Value: 0x04
1955+
1956+
# DW_TAG_base_type
1957+
# DW_AT_name ('int')
1958+
1959+
- AbbrCode: 0x2
1960+
Values:
1961+
- CStr: int
1962+
1963+
# DW_TAG_template_alias
1964+
# DW_AT_name ('Foo<int>')
1965+
# DW_AT_type ('int')
1966+
# DW_TAG_template_type_parameter
1967+
# DW_AT_name ('T')
1968+
# DW_AT_type ('int')
1969+
1970+
- AbbrCode: 0x3
1971+
Values:
1972+
- CStr: Foo<int>
1973+
- Value: 0xf
1974+
1975+
- AbbrCode: 0x4
1976+
Values:
1977+
- CStr: T
1978+
- Value: 0xf
1979+
1980+
- AbbrCode: 0x0
1981+
- AbbrCode: 0x0
1982+
...
1983+
)";
1984+
DWARFASTParserClangYAMLTester tester(yamldata);
1985+
DWARFDIE cu_die = tester.GetCUDIE();
1986+
1987+
auto alias_die = cu_die.GetFirstChild().GetSibling();
1988+
ASSERT_EQ(alias_die.Tag(), DW_TAG_template_alias);
1989+
1990+
SymbolContext sc;
1991+
auto type_sp =
1992+
tester.GetParser().ParseTypeFromDWARF(sc, alias_die,
1993+
/*type_is_new_ptr=*/nullptr);
1994+
ASSERT_NE(type_sp, nullptr);
1995+
1996+
EXPECT_TRUE(type_sp->IsTypedef());
1997+
EXPECT_EQ(type_sp->GetName(), "Foo<int>");
1998+
EXPECT_EQ(type_sp->GetForwardCompilerType().GetTypeName(), "Foo<int>");
1999+
}
2000+
2001+
TEST_F(DWARFASTParserClangTests,
2002+
TestTemplateAlias_InStruct_NoSimpleTemplateNames) {
2003+
// Tests that we correctly parse the DW_TAG_template_alias scoped inside a
2004+
// DW_TAG_structure_type *declaration* generated by
2005+
// -gno-simple-template-names. This tests the codepath the forcefully
2006+
// completes the context of the alias via PrepareContextToReceiveMembers.
2007+
2008+
const char *yamldata = R"(
2009+
--- !ELF
2010+
FileHeader:
2011+
Class: ELFCLASS64
2012+
Data: ELFDATA2LSB
2013+
Type: ET_EXEC
2014+
Machine: EM_AARCH64
2015+
DWARF:
2016+
debug_abbrev:
2017+
- ID: 0
2018+
Table:
2019+
- Code: 0x1
2020+
Tag: DW_TAG_compile_unit
2021+
Children: DW_CHILDREN_yes
2022+
Attributes:
2023+
- Attribute: DW_AT_language
2024+
Form: DW_FORM_data2
2025+
- Code: 0x2
2026+
Tag: DW_TAG_base_type
2027+
Children: DW_CHILDREN_no
2028+
Attributes:
2029+
- Attribute: DW_AT_name
2030+
Form: DW_FORM_string
2031+
- Code: 0x3
2032+
Tag: DW_TAG_structure_type
2033+
Children: DW_CHILDREN_yes
2034+
Attributes:
2035+
- Attribute: DW_AT_name
2036+
Form: DW_FORM_string
2037+
- Attribute: DW_AT_declaration
2038+
Form: DW_FORM_flag_present
2039+
- Code: 0x4
2040+
Tag: DW_TAG_template_alias
2041+
Children: DW_CHILDREN_yes
2042+
Attributes:
2043+
- Attribute: DW_AT_name
2044+
Form: DW_FORM_string
2045+
- Attribute: DW_AT_type
2046+
Form: DW_FORM_ref4
2047+
- Code: 0x5
2048+
Tag: DW_TAG_template_type_parameter
2049+
Children: DW_CHILDREN_no
2050+
Attributes:
2051+
- Attribute: DW_AT_name
2052+
Form: DW_FORM_string
2053+
- Attribute: DW_AT_type
2054+
Form: DW_FORM_ref4
2055+
2056+
debug_info:
2057+
- Version: 5
2058+
UnitType: DW_UT_compile
2059+
AddrSize: 8
2060+
Entries:
2061+
2062+
# DW_TAG_compile_unit
2063+
# DW_AT_language (DW_LANG_C_plus_plus)
2064+
2065+
- AbbrCode: 0x1
2066+
Values:
2067+
- Value: 0x04
2068+
2069+
# DW_TAG_base_type
2070+
# DW_AT_name ('int')
2071+
2072+
- AbbrCode: 0x2
2073+
Values:
2074+
- CStr: int
2075+
2076+
# DW_TAG_structure_type
2077+
# DW_AT_name ('Foo')
2078+
2079+
- AbbrCode: 0x3
2080+
Values:
2081+
- CStr: Foo
2082+
2083+
# DW_TAG_template_alias
2084+
# DW_AT_name ('Bar<int>')
2085+
# DW_AT_type ('int')
2086+
# DW_TAG_template_type_parameter
2087+
# DW_AT_name ('T')
2088+
# DW_AT_type ('int')
2089+
2090+
- AbbrCode: 0x4
2091+
Values:
2092+
- CStr: Bar<int>
2093+
- Value: 0xf
2094+
2095+
- AbbrCode: 0x5
2096+
Values:
2097+
- CStr: T
2098+
- Value: 0xf
2099+
2100+
- AbbrCode: 0x0
2101+
- AbbrCode: 0x0
2102+
- AbbrCode: 0x0
2103+
...
2104+
)";
2105+
DWARFASTParserClangYAMLTester tester(yamldata);
2106+
DWARFDIE cu_die = tester.GetCUDIE();
2107+
2108+
auto alias_die = cu_die.GetFirstChild().GetSibling().GetFirstChild();
2109+
ASSERT_EQ(alias_die.Tag(), DW_TAG_template_alias);
2110+
2111+
SymbolContext sc;
2112+
auto type_sp =
2113+
tester.GetParser().ParseTypeFromDWARF(sc, alias_die,
2114+
/*type_is_new_ptr=*/nullptr);
2115+
ASSERT_NE(type_sp, nullptr);
2116+
2117+
EXPECT_TRUE(type_sp->IsTypedef());
2118+
EXPECT_EQ(type_sp->GetName(), "Bar<int>");
2119+
EXPECT_EQ(type_sp->GetForwardCompilerType().GetTypeName(), "Foo::Bar<int>");
2120+
}

0 commit comments

Comments
 (0)