diff --git a/lldb/packages/Python/lldbsuite/test/make/Makefile.rules b/lldb/packages/Python/lldbsuite/test/make/Makefile.rules --- a/lldb/packages/Python/lldbsuite/test/make/Makefile.rules +++ b/lldb/packages/Python/lldbsuite/test/make/Makefile.rules @@ -227,7 +227,8 @@ DEBUG_INFO_FLAG ?= -gdwarf endif -DEBUG_INFO_FLAG ?= -g +# DO NOT SUBMIT +DEBUG_INFO_FLAG ?= -g -gsimple-template-names CFLAGS ?= $(DEBUG_INFO_FLAG) -O0 diff --git a/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp b/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp --- a/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp +++ b/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp @@ -1542,8 +1542,94 @@ // only one thing can exist at a given decl context. We ignore the // file and line that things are declared on. std::string qualified_name; - if (die.GetQualifiedName(qualified_name)) + + // The name may not contain template parameters due to simplified template + // names, we must reconstruct the full name from child template parameter + // dies. + if (die.IsValid()) { + auto get_template_params_string = [this](DWARFDIE die) { + if (llvm::StringRef(die.GetName()).contains("<")) + return std::string(); + TypeSystemClang::TemplateParameterInfos template_param_infos; + if (ParseTemplateParameterInfos(die, template_param_infos)) { + std::string all_template_names; + llvm::SmallVector &args = + template_param_infos.args; + if (template_param_infos.hasParameterPack()) { + args = template_param_infos.packed_args->args; + } + for (auto &arg : args) { + std::string template_name; + llvm::raw_string_ostream os(template_name); + arg.dump(os); + if (!template_name.empty()) { + if (all_template_names.empty()) { + all_template_names.append("<"); + } else { + all_template_names.append(", "); + } + all_template_names.append(template_name); + } + } + if (!all_template_names.empty()) { + all_template_names.append(">"); + // does the spacing here matter? + } + return all_template_names; + } + return std::string(); + }; + const char *name = die.GetName(); + if (name) { + DWARFDIE parent_decl_ctx_die = die.GetParentDeclContextDIE(); + // TODO: change this to get the correct decl context parent.... + while (parent_decl_ctx_die) { + const dw_tag_t parent_tag = parent_decl_ctx_die.Tag(); + switch (parent_tag) { + case DW_TAG_namespace: { + const char *namespace_name = parent_decl_ctx_die.GetName(); + if (namespace_name) { + qualified_name.insert(0, "::"); + qualified_name.insert(0, namespace_name); + } else { + qualified_name.insert(0, "(anonymous namespace)::"); + } + parent_decl_ctx_die = + parent_decl_ctx_die.GetParentDeclContextDIE(); + break; + } + + case DW_TAG_class_type: + case DW_TAG_structure_type: + case DW_TAG_union_type: { + const char *class_union_struct_name = + parent_decl_ctx_die.GetName(); + + if (class_union_struct_name) { + qualified_name.insert( + 0, get_template_params_string(parent_decl_ctx_die)); + qualified_name.insert(0, "::"); + qualified_name.insert(0, class_union_struct_name); + } + parent_decl_ctx_die = + parent_decl_ctx_die.GetParentDeclContextDIE(); + break; + } + + default: + parent_decl_ctx_die.Clear(); + break; + } + } + + if (qualified_name.empty()) + qualified_name.append("::"); + + qualified_name.append(name); + qualified_name.append(get_template_params_string(die)); + } unique_typename = ConstString(qualified_name); + } unique_decl.Clear(); } @@ -1716,36 +1802,40 @@ metadata.SetUserID(die.GetID()); metadata.SetIsDynamicCXXType(dwarf->ClassOrStructIsVirtual(die)); - if (attrs.name.GetStringRef().contains('<')) { - TypeSystemClang::TemplateParameterInfos template_param_infos; - if (ParseTemplateParameterInfos(die, template_param_infos)) { - clang::ClassTemplateDecl *class_template_decl = - m_ast.ParseClassTemplateDecl( - decl_ctx, GetOwningClangModule(die), attrs.accessibility, - attrs.name.GetCString(), tag_decl_kind, template_param_infos); - if (!class_template_decl) { - if (log) { - dwarf->GetObjectFile()->GetModule()->LogMessage( - log, - "SymbolFileDWARF(%p) - 0x%8.8x: %s type \"%s\" " - "clang::ClassTemplateDecl failed to return a decl.", - static_cast(this), die.GetOffset(), - DW_TAG_value_to_name(tag), attrs.name.GetCString()); - } - return TypeSP(); + bool is_template = false; + TypeSystemClang::TemplateParameterInfos template_param_infos; + if (ParseTemplateParameterInfos(die, template_param_infos)) { + is_template = !template_param_infos.args.empty() || + template_param_infos.packed_args; + } + + if (is_template) { + clang::ClassTemplateDecl *class_template_decl = + m_ast.ParseClassTemplateDecl( + decl_ctx, GetOwningClangModule(die), attrs.accessibility, + attrs.name.GetCString(), tag_decl_kind, template_param_infos); + if (!class_template_decl) { + if (log) { + dwarf->GetObjectFile()->GetModule()->LogMessage( + log, + "SymbolFileDWARF(%p) - 0x%8.8x: %s type \"%s\" " + "clang::ClassTemplateDecl failed to return a decl.", + static_cast(this), die.GetOffset(), + DW_TAG_value_to_name(tag), attrs.name.GetCString()); } + return TypeSP(); + } - clang::ClassTemplateSpecializationDecl *class_specialization_decl = - m_ast.CreateClassTemplateSpecializationDecl( - decl_ctx, GetOwningClangModule(die), class_template_decl, - tag_decl_kind, template_param_infos); - clang_type = m_ast.CreateClassTemplateSpecializationType( - class_specialization_decl); - clang_type_was_created = true; + clang::ClassTemplateSpecializationDecl *class_specialization_decl = + m_ast.CreateClassTemplateSpecializationDecl( + decl_ctx, GetOwningClangModule(die), class_template_decl, + tag_decl_kind, template_param_infos); + clang_type = m_ast.CreateClassTemplateSpecializationType( + class_specialization_decl); + clang_type_was_created = true; - m_ast.SetMetadata(class_template_decl, metadata); - m_ast.SetMetadata(class_specialization_decl, metadata); - } + m_ast.SetMetadata(class_template_decl, metadata); + m_ast.SetMetadata(class_specialization_decl, metadata); } if (!clang_type_was_created) { diff --git a/lldb/source/Plugins/SymbolFile/DWARF/DWARFDIE.h b/lldb/source/Plugins/SymbolFile/DWARF/DWARFDIE.h --- a/lldb/source/Plugins/SymbolFile/DWARF/DWARFDIE.h +++ b/lldb/source/Plugins/SymbolFile/DWARF/DWARFDIE.h @@ -30,8 +30,6 @@ const char *GetPubname() const; - const char *GetQualifiedName(std::string &storage) const; - using DWARFBaseDIE::GetName; void GetName(lldb_private::Stream &s) const; diff --git a/lldb/source/Plugins/SymbolFile/DWARF/DWARFDIE.cpp b/lldb/source/Plugins/SymbolFile/DWARF/DWARFDIE.cpp --- a/lldb/source/Plugins/SymbolFile/DWARF/DWARFDIE.cpp +++ b/lldb/source/Plugins/SymbolFile/DWARF/DWARFDIE.cpp @@ -215,13 +215,6 @@ return nullptr; } -const char *DWARFDIE::GetQualifiedName(std::string &storage) const { - if (IsValid()) - return m_die->GetQualifiedName(m_cu, storage); - else - return nullptr; -} - // GetName // // Get value of the DW_AT_name attribute and place that value into the supplied diff --git a/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugInfoEntry.h b/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugInfoEntry.h --- a/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugInfoEntry.h +++ b/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugInfoEntry.h @@ -99,11 +99,6 @@ const char *GetPubname(const DWARFUnit *cu) const; - const char *GetQualifiedName(DWARFUnit *cu, std::string &storage) const; - - const char *GetQualifiedName(DWARFUnit *cu, const DWARFAttributes &attributes, - std::string &storage) const; - bool GetDIENamesAndRanges( DWARFUnit *cu, const char *&name, const char *&mangled, DWARFRangeList &rangeList, int &decl_file, int &decl_line, diff --git a/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugInfoEntry.cpp b/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugInfoEntry.cpp --- a/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugInfoEntry.cpp +++ b/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugInfoEntry.cpp @@ -798,66 +798,6 @@ return DWARFDIE(); } -const char *DWARFDebugInfoEntry::GetQualifiedName(DWARFUnit *cu, - std::string &storage) const { - DWARFAttributes attributes; - GetAttributes(cu, attributes, Recurse::yes); - return GetQualifiedName(cu, attributes, storage); -} - -const char * -DWARFDebugInfoEntry::GetQualifiedName(DWARFUnit *cu, - const DWARFAttributes &attributes, - std::string &storage) const { - - const char *name = GetName(cu); - - if (name) { - DWARFDIE parent_decl_ctx_die = GetParentDeclContextDIE(cu); - storage.clear(); - // TODO: change this to get the correct decl context parent.... - while (parent_decl_ctx_die) { - const dw_tag_t parent_tag = parent_decl_ctx_die.Tag(); - switch (parent_tag) { - case DW_TAG_namespace: { - const char *namespace_name = parent_decl_ctx_die.GetName(); - if (namespace_name) { - storage.insert(0, "::"); - storage.insert(0, namespace_name); - } else { - storage.insert(0, "(anonymous namespace)::"); - } - parent_decl_ctx_die = parent_decl_ctx_die.GetParentDeclContextDIE(); - } break; - - case DW_TAG_class_type: - case DW_TAG_structure_type: - case DW_TAG_union_type: { - const char *class_union_struct_name = parent_decl_ctx_die.GetName(); - - if (class_union_struct_name) { - storage.insert(0, "::"); - storage.insert(0, class_union_struct_name); - } - parent_decl_ctx_die = parent_decl_ctx_die.GetParentDeclContextDIE(); - } break; - - default: - parent_decl_ctx_die.Clear(); - break; - } - } - - if (storage.empty()) - storage.append("::"); - - storage.append(name); - } - if (storage.empty()) - return nullptr; - return storage.c_str(); -} - lldb::offset_t DWARFDebugInfoEntry::GetFirstAttributeOffset() const { return GetOffset() + llvm::getULEB128Size(m_abbr_idx); } diff --git a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp --- a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp +++ b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp @@ -2475,6 +2475,39 @@ return types.GetSize() < max_matches; }); + if (types.Empty()) { + const llvm::StringRef nameRef = name.GetStringRef(); + auto it = nameRef.find('<'); + if (it != llvm::StringRef::npos) { + const llvm::StringRef nameNoTemplateParams = nameRef.slice(0, it); + const llvm::StringRef templateParams = nameRef.slice(it, nameRef.size()); + m_index->GetTypes(ConstString(nameNoTemplateParams), [&](DWARFDIE die) { + if (!DIEInDeclContext(parent_decl_ctx, die)) + return true; // The containing decl contexts don't match + + TypeSP Ty = GetTypeForDIE(die); + llvm::StringRef qualName = Ty->GetQualifiedName().AsCString(); + auto it = qualName.find('<'); + if (it == llvm::StringRef::npos) + return true; + + llvm::StringRef qualNameTemplateParams = + qualName.slice(it, qualName.size()); + if (templateParams != qualNameTemplateParams) + return true; + + Type *matching_type = ResolveType(die, true, true); + if (!matching_type) + return true; + + // We found a type pointer, now find the shared pointer form our type + // list + types.InsertUnique(matching_type->shared_from_this()); + return types.GetSize() < max_matches; + }); + } + } + // Next search through the reachable Clang modules. This only applies for // DWARF objects compiled with -gmodules that haven't been processed by // dsymutil. @@ -2943,8 +2976,6 @@ if (!try_resolving_type) { if (log) { - std::string qualified_name; - type_die.GetQualifiedName(qualified_name); GetObjectFile()->GetModule()->LogMessage( log, "SymbolFileDWARF::" @@ -2952,7 +2983,7 @@ "qualified-name='%s') ignoring die=0x%8.8x (%s)", DW_TAG_value_to_name(dwarf_decl_ctx[0].tag), dwarf_decl_ctx.GetQualifiedName(), type_die.GetOffset(), - qualified_name.c_str()); + type_die.GetName()); } return true; } diff --git a/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.cpp b/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.cpp --- a/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.cpp +++ b/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.cpp @@ -9323,7 +9323,9 @@ const TypeSystemClang::TemplateParameterInfos &template_param_infos) { if (template_param_infos.IsValid()) { std::string template_basename(parent_name); - template_basename.erase(template_basename.find('<')); + auto i = template_basename.find('<'); + if (i != std::string::npos) + template_basename.erase(i); return CreateClassTemplateDecl(decl_ctx, owning_module, access_type, template_basename.c_str(), tag_decl_kind, diff --git a/lldb/test/API/lang/cpp/complete-type-check/TestCppIsTypeComplete.py b/lldb/test/API/lang/cpp/complete-type-check/TestCppIsTypeComplete.py --- a/lldb/test/API/lang/cpp/complete-type-check/TestCppIsTypeComplete.py +++ b/lldb/test/API/lang/cpp/complete-type-check/TestCppIsTypeComplete.py @@ -51,7 +51,7 @@ # Record types without a defining declaration are not complete. self.assertPointeeIncomplete("FwdClass *", "fwd_class") self.assertPointeeIncomplete("FwdClassTypedef *", "fwd_class_typedef") - self.assertPointeeIncomplete("FwdTemplateClass<> *", "fwd_template_class") + self.assertPointeeIncomplete("FwdTemplateClass *", "fwd_template_class") # A pointer type is complete even when it points to an incomplete type. fwd_class_ptr = self.expect_expr("fwd_class", result_type="FwdClass *") diff --git a/lldb/test/API/lang/cpp/unique-types2/Makefile b/lldb/test/API/lang/cpp/unique-types2/Makefile new file mode 100644 --- /dev/null +++ b/lldb/test/API/lang/cpp/unique-types2/Makefile @@ -0,0 +1,3 @@ +CXX_SOURCES := main.cpp + +include Makefile.rules diff --git a/lldb/test/API/lang/cpp/unique-types2/TestUniqueTypes.py b/lldb/test/API/lang/cpp/unique-types2/TestUniqueTypes.py new file mode 100644 --- /dev/null +++ b/lldb/test/API/lang/cpp/unique-types2/TestUniqueTypes.py @@ -0,0 +1,18 @@ +""" +Test that we return only the requested template instantiation. +""" + +import lldb +import lldbsuite.test.lldbutil as lldbutil +from lldbsuite.test.lldbtest import * + +class UniqueTypesTestCase(TestBase): + def test(self): + """Test that we only display the requested Foo instantiation, not all Foo instantiations.""" + self.build() + lldbutil.run_to_source_breakpoint(self, "// Set breakpoint here", lldb.SBFileSpec("main.cpp")) + + self.expect("image lookup -A -t Foo", DATA_TYPES_DISPLAYED_CORRECTLY, substrs=["1 match found"]) + self.expect("image lookup -A -t Foo", DATA_TYPES_DISPLAYED_CORRECTLY, substrs=["1 match found"]) + self.expect("image lookup -A -t 'Foo >'", DATA_TYPES_DISPLAYED_CORRECTLY, substrs=["1 match found"]) + self.expect("image lookup -A -t Foo", DATA_TYPES_DISPLAYED_CORRECTLY, error=True) diff --git a/lldb/test/API/lang/cpp/unique-types2/main.cpp b/lldb/test/API/lang/cpp/unique-types2/main.cpp new file mode 100644 --- /dev/null +++ b/lldb/test/API/lang/cpp/unique-types2/main.cpp @@ -0,0 +1,11 @@ + +template class Foo { + T t; +}; + +int main() { + Foo t1; + Foo t2; + Foo> t3; + // Set breakpoint here +}