Skip to content

Commit 9957cbe

Browse files
committed
[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 (cherry picked from commit 1f35b52)
1 parent aa0291b commit 9957cbe

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
@@ -638,6 +638,7 @@ TypeSP DWARFASTParserClang::ParseTypeFromDWARF(const SymbolContext &sc,
638638

639639
switch (tag) {
640640
case DW_TAG_typedef:
641+
case DW_TAG_template_alias:
641642
case DW_TAG_base_type:
642643
case DW_TAG_pointer_type:
643644
case DW_TAG_reference_type:
@@ -777,7 +778,7 @@ DWARFASTParserClang::ParseTypeModifier(const SymbolContext &sc,
777778
TypeSP type_sp;
778779
CompilerType clang_type;
779780

780-
if (tag == DW_TAG_typedef) {
781+
if (tag == DW_TAG_typedef || tag == DW_TAG_template_alias) {
781782
// DeclContext will be populated when the clang type is materialized in
782783
// Type::ResolveCompilerType.
783784
PrepareContextToReceiveMembers(
@@ -865,6 +866,7 @@ DWARFASTParserClang::ParseTypeModifier(const SymbolContext &sc,
865866
encoding_data_type = Type::eEncodingIsRValueReferenceUID;
866867
break;
867868
case DW_TAG_typedef:
869+
case DW_TAG_template_alias:
868870
encoding_data_type = Type::eEncodingIsTypedefUID;
869871
break;
870872
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

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

0 commit comments

Comments
 (0)