[lldb] [llvm] [lldb][dwarf] Compute fully qualified names on simplified template names with DWARFTypePrinter (PR #117071)
via llvm-commits
llvm-commits at lists.llvm.org
Wed Nov 20 14:19:35 PST 2024
llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-debuginfo
Author: Zequan Wu (ZequanWu)
<details>
<summary>Changes</summary>
This is a reland of https://github.com/llvm/llvm-project/pull/112811. Fixed the bot breakage by running ld.lld explicitly.
---
Patch is 24.81 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/117071.diff
14 Files Affected:
- (modified) lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp (+14-7)
- (modified) lldb/source/Plugins/SymbolFile/DWARF/DWARFBaseDIE.h (+8)
- (modified) lldb/source/Plugins/SymbolFile/DWARF/DWARFDIE.cpp (+37)
- (modified) lldb/source/Plugins/SymbolFile/DWARF/DWARFDIE.h (+17)
- (modified) lldb/source/Plugins/SymbolFile/DWARF/DWARFFormValue.cpp (+25)
- (modified) lldb/source/Plugins/SymbolFile/DWARF/DWARFFormValue.h (+6)
- (modified) lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp (+9-27)
- (modified) lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.cpp (-20)
- (modified) lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.h (-4)
- (added) lldb/test/Shell/SymbolFile/DWARF/x86/simplified-template-names.cpp (+36)
- (modified) lldb/unittests/SymbolFile/DWARF/DWARFDIETest.cpp (+125)
- (modified) llvm/include/llvm/DebugInfo/DWARF/DWARFDie.h (+2)
- (modified) llvm/include/llvm/DebugInfo/DWARF/DWARFTypePrinter.h (+21-12)
- (modified) llvm/lib/DebugInfo/DWARF/DWARFDie.cpp (+9)
``````````diff
diff --git a/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp b/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp
index d9bdeb560e1220..37c1132c1c9f9a 100644
--- a/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp
+++ b/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp
@@ -45,6 +45,7 @@
#include "clang/AST/Type.h"
#include "clang/Basic/Specifiers.h"
#include "llvm/ADT/StringExtras.h"
+#include "llvm/DebugInfo/DWARF/DWARFTypePrinter.h"
#include "llvm/Demangle/Demangle.h"
#include <map>
@@ -826,11 +827,11 @@ std::string DWARFASTParserClang::GetDIEClassTemplateParams(DWARFDIE die) {
if (llvm::StringRef(die.GetName()).contains("<"))
return {};
- TypeSystemClang::TemplateParameterInfos template_param_infos;
- if (ParseTemplateParameterInfos(die, template_param_infos))
- return m_ast.PrintTemplateParams(template_param_infos);
-
- return {};
+ std::string name;
+ llvm::raw_string_ostream os(name);
+ llvm::DWARFTypePrinter<DWARFDIE> type_printer(os);
+ type_printer.appendAndTerminateTemplateParameters(die);
+ return name;
}
void DWARFASTParserClang::MapDeclDIEToDefDIE(
@@ -1618,9 +1619,9 @@ void DWARFASTParserClang::GetUniqueTypeNameAndDeclaration(
case DW_TAG_structure_type:
case DW_TAG_union_type: {
if (const char *class_union_struct_name = parent_decl_ctx_die.GetName()) {
- qualified_name.insert(
- 0, GetDIEClassTemplateParams(parent_decl_ctx_die));
qualified_name.insert(0, "::");
+ qualified_name.insert(0,
+ GetDIEClassTemplateParams(parent_decl_ctx_die));
qualified_name.insert(0, class_union_struct_name);
}
parent_decl_ctx_die = parent_decl_ctx_die.GetParentDeclContextDIE();
@@ -1673,6 +1674,12 @@ DWARFASTParserClang::ParseStructureLikeDIE(const SymbolContext &sc,
if (attrs.name) {
GetUniqueTypeNameAndDeclaration(die, cu_language, unique_typename,
unique_decl);
+ if (log) {
+ dwarf->GetObjectFile()->GetModule()->LogMessage(
+ log, "SymbolFileDWARF({0:p}) - {1:x16}: {2} has unique name: {3} ",
+ static_cast<void *>(this), die.GetID(), DW_TAG_value_to_name(tag),
+ unique_typename.AsCString());
+ }
if (UniqueDWARFASTType *unique_ast_entry_type =
dwarf->GetUniqueDWARFASTTypeMap().Find(
unique_typename, die, unique_decl, byte_size,
diff --git a/lldb/source/Plugins/SymbolFile/DWARF/DWARFBaseDIE.h b/lldb/source/Plugins/SymbolFile/DWARF/DWARFBaseDIE.h
index 235343d2271223..d92de658a49e89 100644
--- a/lldb/source/Plugins/SymbolFile/DWARF/DWARFBaseDIE.h
+++ b/lldb/source/Plugins/SymbolFile/DWARF/DWARFBaseDIE.h
@@ -24,9 +24,11 @@ class DWARFUnit;
class DWARFDebugInfoEntry;
class DWARFDeclContext;
class SymbolFileDWARF;
+class DWARFFormValue;
class DWARFBaseDIE {
public:
+ using DWARFFormValue = dwarf::DWARFFormValue;
DWARFBaseDIE() = default;
DWARFBaseDIE(DWARFUnit *cu, DWARFDebugInfoEntry *die)
@@ -117,6 +119,12 @@ class DWARFBaseDIE {
enum class Recurse : bool { no, yes };
DWARFAttributes GetAttributes(Recurse recurse = Recurse::yes) const;
+ // The following methods use LLVM naming convension in order to be are used by
+ // LLVM libraries.
+ dw_tag_t getTag() const { return Tag(); }
+
+ const char *getShortName() const { return GetName(); }
+
protected:
DWARFUnit *m_cu = nullptr;
DWARFDebugInfoEntry *m_die = nullptr;
diff --git a/lldb/source/Plugins/SymbolFile/DWARF/DWARFDIE.cpp b/lldb/source/Plugins/SymbolFile/DWARF/DWARFDIE.cpp
index 4c9f1d8505f6e6..362f4c44240c76 100644
--- a/lldb/source/Plugins/SymbolFile/DWARF/DWARFDIE.cpp
+++ b/lldb/source/Plugins/SymbolFile/DWARF/DWARFDIE.cpp
@@ -572,6 +572,43 @@ bool DWARFDIE::GetDIENamesAndRanges(
return false;
}
+// The following methods use LLVM naming convension in order to be are used by
+// LLVM libraries.
llvm::iterator_range<DWARFDIE::child_iterator> DWARFDIE::children() const {
return llvm::make_range(child_iterator(*this), child_iterator());
}
+
+DWARFDIE::child_iterator DWARFDIE::begin() const {
+ return child_iterator(*this);
+}
+
+DWARFDIE::child_iterator DWARFDIE::end() const { return child_iterator(); }
+
+std::optional<DWARFFormValue> DWARFDIE::find(const dw_attr_t attr) const {
+ DWARFFormValue form_value;
+ if (m_die->GetAttributeValue(m_cu, attr, form_value, nullptr, false))
+ return form_value;
+ return std::nullopt;
+}
+
+std::optional<uint64_t> DWARFDIE::getLanguage() const {
+ if (IsValid())
+ return m_cu->GetDWARFLanguageType();
+ return std::nullopt;
+}
+
+DWARFDIE DWARFDIE::resolveReferencedType(dw_attr_t attr) const {
+ return GetReferencedDIE(attr);
+}
+
+DWARFDIE DWARFDIE::resolveReferencedType(DWARFFormValue v) const {
+ if (IsValid())
+ return v.Reference();
+ return {};
+}
+
+DWARFDIE DWARFDIE::resolveTypeUnitReference() const {
+ if (DWARFDIE reference = GetReferencedDIE(DW_AT_signature))
+ return reference;
+ return *this;
+}
diff --git a/lldb/source/Plugins/SymbolFile/DWARF/DWARFDIE.h b/lldb/source/Plugins/SymbolFile/DWARF/DWARFDIE.h
index 077b78eb26d0c3..5c1d381930c4ed 100644
--- a/lldb/source/Plugins/SymbolFile/DWARF/DWARFDIE.h
+++ b/lldb/source/Plugins/SymbolFile/DWARF/DWARFDIE.h
@@ -103,8 +103,25 @@ class DWARFDIE : public DWARFBaseDIE {
std::optional<int> &call_line, std::optional<int> &call_column,
DWARFExpressionList *frame_base) const;
+ // The following methods use LLVM naming convension in order to be are used by
+ // LLVM libraries.
+ std::optional<uint64_t> getLanguage() const;
+
+ DWARFDIE getParent() const { return GetParent(); }
+
+ DWARFDIE resolveReferencedType(dw_attr_t attr) const;
+
+ DWARFDIE resolveReferencedType(DWARFFormValue v) const;
+
+ DWARFDIE resolveTypeUnitReference() const;
+
+ std::optional<DWARFFormValue> find(const dw_attr_t attr) const;
+
/// The range of all the children of this DIE.
llvm::iterator_range<child_iterator> children() const;
+
+ child_iterator begin() const;
+ child_iterator end() const;
};
class DWARFDIE::child_iterator
diff --git a/lldb/source/Plugins/SymbolFile/DWARF/DWARFFormValue.cpp b/lldb/source/Plugins/SymbolFile/DWARF/DWARFFormValue.cpp
index 404e50d57a9251..fd3d45cef4c5e4 100644
--- a/lldb/source/Plugins/SymbolFile/DWARF/DWARFFormValue.cpp
+++ b/lldb/source/Plugins/SymbolFile/DWARF/DWARFFormValue.cpp
@@ -574,6 +574,31 @@ uint64_t DWARFFormValue::Reference(dw_offset_t base_offset) const {
}
}
+std::optional<uint64_t> DWARFFormValue::getAsUnsignedConstant() const {
+ if ((!IsDataForm(m_form)) || m_form == lldb_private::dwarf::DW_FORM_sdata)
+ return std::nullopt;
+ return m_value.uval;
+}
+
+std::optional<int64_t> DWARFFormValue::getAsSignedConstant() const {
+ if ((!IsDataForm(m_form)) ||
+ (m_form == lldb_private::dwarf::DW_FORM_udata &&
+ uint64_t(std::numeric_limits<int64_t>::max()) < m_value.uval))
+ return std::nullopt;
+ switch (m_form) {
+ case lldb_private::dwarf::DW_FORM_data4:
+ return int32_t(m_value.uval);
+ case lldb_private::dwarf::DW_FORM_data2:
+ return int16_t(m_value.uval);
+ case lldb_private::dwarf::DW_FORM_data1:
+ return int8_t(m_value.uval);
+ case lldb_private::dwarf::DW_FORM_sdata:
+ case lldb_private::dwarf::DW_FORM_data8:
+ default:
+ return m_value.sval;
+ }
+}
+
const uint8_t *DWARFFormValue::BlockData() const { return m_value.data; }
bool DWARFFormValue::IsBlockForm(const dw_form_t form) {
diff --git a/lldb/source/Plugins/SymbolFile/DWARF/DWARFFormValue.h b/lldb/source/Plugins/SymbolFile/DWARF/DWARFFormValue.h
index 8ab9163e645fea..613948f2f3c9b7 100644
--- a/lldb/source/Plugins/SymbolFile/DWARF/DWARFFormValue.h
+++ b/lldb/source/Plugins/SymbolFile/DWARF/DWARFFormValue.h
@@ -76,6 +76,12 @@ class DWARFFormValue {
void Clear();
static bool FormIsSupported(dw_form_t form);
+ // The following methods use LLVM naming convension in order to be are used by
+ // LLVM libraries.
+ std::optional<uint64_t> getAsUnsignedConstant() const;
+ std::optional<int64_t> getAsSignedConstant() const;
+ const char *getAsCString() const { return AsCString(); }
+
protected:
// Compile unit where m_value was located.
// It may be different from compile unit where m_value refers to.
diff --git a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp
index 8ce0db4588a46a..47050d86409a60 100644
--- a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp
+++ b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp
@@ -9,6 +9,7 @@
#include "SymbolFileDWARF.h"
#include "llvm/DebugInfo/DWARF/DWARFDebugLoc.h"
+#include "llvm/DebugInfo/DWARF/DWARFTypePrinter.h"
#include "llvm/Support/Casting.h"
#include "llvm/Support/FileUtilities.h"
#include "llvm/Support/Format.h"
@@ -2810,33 +2811,14 @@ void SymbolFileDWARF::FindTypes(const TypeQuery &query, TypeResults &results) {
return true; // Keep iterating over index types, language mismatch.
}
- // Check the context matches
- std::vector<lldb_private::CompilerContext> die_context;
- if (query.GetModuleSearch())
- die_context = die.GetDeclContext();
- else
- die_context = die.GetTypeLookupContext();
- assert(!die_context.empty());
- if (!query_simple.ContextMatches(die_context))
- return true; // Keep iterating over index types, context mismatch.
-
- // Try to resolve the type.
- if (Type *matching_type = ResolveType(die, true, true)) {
- ConstString name = matching_type->GetQualifiedName();
- // We have found a type that still might not match due to template
- // parameters. If we create a new TypeQuery that uses the new type's
- // fully qualified name, we can find out if this type matches at all
- // context levels. We can't use just the "match_simple" context
- // because all template parameters were stripped off. The fully
- // qualified name of the type will have the template parameters and
- // will allow us to make sure it matches correctly.
- TypeQuery die_query(name.GetStringRef(),
- TypeQueryOptions::e_exact_match);
- if (!query.ContextMatches(die_query.GetContextRef()))
- return true; // Keep iterating over index types, context mismatch.
-
- results.InsertUnique(matching_type->shared_from_this());
- }
+ std::string qualified_name;
+ llvm::raw_string_ostream os(qualified_name);
+ llvm::DWARFTypePrinter<DWARFDIE> type_printer(os);
+ type_printer.appendQualifiedName(die);
+ TypeQuery die_query(qualified_name, e_exact_match);
+ if (query.ContextMatches(die_query.GetContextRef()))
+ if (Type *matching_type = ResolveType(die, true, true))
+ results.InsertUnique(matching_type->shared_from_this());
return !results.Done(query); // Keep iterating if we aren't done.
});
if (results.Done(query)) {
diff --git a/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.cpp b/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.cpp
index 1a77c7cf9161a0..5f8163211857c3 100644
--- a/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.cpp
+++ b/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.cpp
@@ -1403,26 +1403,6 @@ static TemplateParameterList *CreateTemplateParameterList(
return template_param_list;
}
-std::string TypeSystemClang::PrintTemplateParams(
- const TemplateParameterInfos &template_param_infos) {
- llvm::SmallVector<NamedDecl *, 8> ignore;
- clang::TemplateParameterList *template_param_list =
- CreateTemplateParameterList(getASTContext(), template_param_infos,
- ignore);
- llvm::SmallVector<clang::TemplateArgument, 2> args(
- template_param_infos.GetArgs());
- if (template_param_infos.hasParameterPack()) {
- llvm::ArrayRef<TemplateArgument> pack_args =
- template_param_infos.GetParameterPackArgs();
- args.append(pack_args.begin(), pack_args.end());
- }
- std::string str;
- llvm::raw_string_ostream os(str);
- clang::printTemplateArgumentList(os, args, GetTypePrintingPolicy(),
- template_param_list);
- return str;
-}
-
clang::FunctionTemplateDecl *TypeSystemClang::CreateFunctionTemplateDecl(
clang::DeclContext *decl_ctx, OptionalClangModuleID owning_module,
clang::FunctionDecl *func_decl,
diff --git a/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.h b/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.h
index e39aedec7e3902..678eaed381fd49 100644
--- a/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.h
+++ b/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.h
@@ -1148,10 +1148,6 @@ class TypeSystemClang : public TypeSystem {
bool SetDeclIsForcefullyCompleted(const clang::TagDecl *td);
- /// Return the template parameters (including surrounding <>) in string form.
- std::string
- PrintTemplateParams(const TemplateParameterInfos &template_param_infos);
-
private:
/// Returns the PrintingPolicy used when generating the internal type names.
/// These type names are mostly used for the formatter selection.
diff --git a/lldb/test/Shell/SymbolFile/DWARF/x86/simplified-template-names.cpp b/lldb/test/Shell/SymbolFile/DWARF/x86/simplified-template-names.cpp
new file mode 100644
index 00000000000000..328d6d2e16d595
--- /dev/null
+++ b/lldb/test/Shell/SymbolFile/DWARF/x86/simplified-template-names.cpp
@@ -0,0 +1,36 @@
+// Test lldb is able to compute the fully qualified names on templates with
+// -gsimple-template-names and -fdebug-types-section.
+
+// REQUIRES: lld
+
+// Test against logging to see if we print the fully qualified names correctly.
+// RUN: %clangxx --target=x86_64-pc-linux -g -gsimple-template-names %s -c -o %t1.o
+// RUN: ld.lld %t1.o -o %t1
+// RUN: %lldb %t1 -o "log enable dwarf comp" -o "target variable v3" -o exit | FileCheck %s --check-prefix=LOG
+
+// Test that we following DW_AT_signature correctly. If not, lldb might confuse the types of v1 and v2.
+// RUN: %clangxx --target=x86_64-pc-linux -g -gsimple-template-names -fdebug-types-section %s -c -o %t2.o
+// RUN: ld.lld %t2.o -o %t2
+// RUN: %lldb %t2 -o "target variable v1 v2" -o exit | FileCheck %s --check-prefix=TYPE
+
+// LOG: unique name: t3<t2<int> >::t4
+
+// TYPE: (t2<outer_struct1::t1<int> >) v1 = {}
+// TYPE-NEXT: (t2<outer_struct2::t1<int> >) v2 = {}
+
+struct outer_struct1 {
+ template <typename> struct t1 {};
+};
+
+struct outer_struct2 {
+ template <typename> struct t1 {};
+};
+
+template <typename> struct t2 {};
+t2<outer_struct1::t1<int>> v1;
+t2<outer_struct2::t1<int>> v2;
+
+template <typename> struct t3 {
+ struct t4 {};
+};
+t3<t2<int>>::t4 v3;
diff --git a/lldb/unittests/SymbolFile/DWARF/DWARFDIETest.cpp b/lldb/unittests/SymbolFile/DWARF/DWARFDIETest.cpp
index 1e4c8f3ba07787..ae63e286cc1551 100644
--- a/lldb/unittests/SymbolFile/DWARF/DWARFDIETest.cpp
+++ b/lldb/unittests/SymbolFile/DWARF/DWARFDIETest.cpp
@@ -14,6 +14,7 @@
#include "lldb/Symbol/Type.h"
#include "lldb/lldb-private-enumerations.h"
#include "llvm/ADT/STLExtras.h"
+#include "llvm/DebugInfo/DWARF/DWARFTypePrinter.h"
#include "gmock/gmock.h"
#include "gtest/gtest.h"
@@ -394,3 +395,127 @@ TEST(DWARFDIETest, GetContextInFunction) {
EXPECT_THAT(foo_struct_die.GetTypeLookupContext(),
testing::ElementsAre(make_struct("struct_t")));
}
+
+TEST(DWARFDIETest, TestDWARFTypePrinter) {
+ // Make sure we can get template parameters and qualified names correctly with
+ // DWARFTypePrinter when using -gsimple-template-names.
+
+ // 0x0000000b: DW_TAG_compile_unit
+ // 0x0000000c: DW_TAG_base_type
+ // DW_AT_name ("int")
+ // 0x00000011: DW_TAG_structure_type
+ // DW_AT_name ("t1")
+ // 0x00000015: DW_TAG_template_type_parameter
+ // DW_AT_type (0x0000001f "t3<int>")
+ // 0x0000001a: DW_TAG_structure_type
+ // DW_AT_name ("t2")
+ // 0x0000001e: NULL
+ // 0x0000001f: DW_TAG_structure_type
+ // DW_AT_name ("t3")
+ // 0x00000023: DW_TAG_template_type_parameter
+ // DW_AT_type (0x0000000c "int")
+ // 0x00000028: NULL
+ // 0x00000029: NULL
+ const char *yamldata = R"(
+--- !ELF
+FileHeader:
+ Class: ELFCLASS64
+ Data: ELFDATA2LSB
+ Type: ET_EXEC
+ Machine: EM_386
+DWARF:
+ debug_abbrev:
+ - ID: 0
+ Table:
+ - Code: 0x1
+ Tag: DW_TAG_compile_unit
+ Children: DW_CHILDREN_yes
+ - 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
+ - Code: 0x4
+ Tag: DW_TAG_template_type_parameter
+ Children: DW_CHILDREN_no
+ Attributes:
+ - Attribute: DW_AT_type
+ Form: DW_FORM_ref4
+ - Code: 0x5
+ Tag: DW_TAG_structure_type
+ Children: DW_CHILDREN_no
+ Attributes:
+ - Attribute: DW_AT_name
+ Form: DW_FORM_string
+ - Code: 0x6
+ Tag: DW_TAG_structure_type
+ Children: DW_CHILDREN_yes
+ Attributes:
+ - Attribute: DW_AT_name
+ Form: DW_FORM_string
+ - Code: 0x7
+ Tag: DW_TAG_template_type_parameter
+ Children: DW_CHILDREN_no
+ Attributes:
+ - Attribute: DW_AT_type
+ Form: DW_FORM_ref4
+ debug_info:
+ - Version: 4
+ AddrSize: 8
+ Entries:
+ - AbbrCode: 0x1
+ - AbbrCode: 0x2
+ Values:
+ - Value: 0xDEADBEEFDEADBEEF
+ CStr: int
+ - AbbrCode: 0x3
+ Values:
+ - Value: 0xDEADBEEFDEADBEEF
+ CStr: t1
+ - AbbrCode: 0x4
+ Values:
+ - Value: 0x0000001f # update
+ - AbbrCode: 0x5
+ Values:
+ - Value: 0xDEADBEEFDEADBEEF
+ CStr: t2
+ - AbbrCode: 0x0
+ - AbbrCode: 0x6
+ Values:
+ - Value: 0xDEADBEEFDEADBEEF
+ CStr: t3
+ - AbbrCode: 0x7
+ Values:
+ - Value: 0x0000000c # update
+ - AbbrCode: 0x0
+ - AbbrCode: 0x0)";
+ YAMLModuleTester t(yamldata);
+ auto *symbol_file =
+ llvm::cast<SymbolFileDWARF>(t.GetModule()->GetSymbolFile());
+ DWARFUnit *unit = symbol_file->DebugInfo().GetUnitAtIndex(0);
+ std::string debug_str;
+ StreamString debug_os;
+ unit->Dump(&debug_os);
+ ASSERT_TRUE(unit);
+
+ DWARFDIE t1_die = unit->GetDIE(0x11);
+ std::string template_name;
+ llvm::raw_string_ostream template_name_os(template_name);
+ llvm::DWARFTypePrinter<DWARFDIE> template_name_printer(template_name_os);
+ template_name_printer.appendAndTerminateTemplateParameters(t1_die);
+ EXPECT_THAT(template_name, "<t3<int> >");
+
+ DWARFDIE t2_die = unit->GetDIE(0x1a);
+ std::string qualified_name;
+ llvm::raw_string_ostream qualified_name_os(qualified_name);
+ llvm::DWARFTypePrinter<DWARFDIE> qualified_name_printer(qualified_name_os);
+ qualified_name_printer.appendQualifiedName(t2_die);
+ EXPECT_THAT(qualified_name, "t1<t3<int> >::t2");
+}
diff --git a/llvm/include/llvm/DebugInfo/DWARF/DWARFDie.h b/llvm/include/llvm/DebugInfo/DWARF/DWARFDie.h
index 69c91835a4d9a1..2e98a4a397147b 100644
--- a/llvm/include/llvm/DebugInfo/DWARF/DWARFDie.h
+++ b/llvm/include/llvm/DebugInfo/DWARF/DWARFDie.h
@@ -226,6 +226,8 @@ class DWARFDie {
bool addressRangeContainsAddress(const ...
[truncated]
``````````
</details>
https://github.com/llvm/llvm-project/pull/117071
More information about the llvm-commits
mailing list