Skip to content

Commit 7c23175

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 7c23175

File tree

2 files changed

+103
-1
lines changed

2 files changed

+103
-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: 100 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
#include "TestingSupport/Symbol/ClangTestUtils.h"
1313
#include "TestingSupport/Symbol/YAMLModuleTester.h"
1414
#include "lldb/Core/Debugger.h"
15+
#include "lldb/Symbol/Type.h"
1516
#include "gmock/gmock.h"
1617
#include "gtest/gtest.h"
1718

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

0 commit comments

Comments
 (0)