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 @@ -2501,6 +2501,8 @@ if (!DeclContextMatchesThisSymbolFile(parent_decl_ctx)) return; + const llvm::StringRef name_ref = name.GetStringRef(); + auto name_bracket_index = name_ref.find('<'); m_index->GetTypes(name, [&](DWARFDIE die) { if (!DIEInDeclContext(parent_decl_ctx, die)) return true; // The containing decl contexts don't match @@ -2509,6 +2511,14 @@ if (!matching_type) return true; + // With -gsimple-template-names, a templated type's DW_AT_name will not + // contain the template parameters. Make sure that if the original query + // didn't contain a '<', we filter out entries with template parameters. + const llvm::StringRef base_name = + GetTypeForDIE(die)->GetBaseName().AsCString(); + if (name_bracket_index == llvm::StringRef::npos && base_name.contains('<')) + return true; + // We found a type pointer, now find the shared pointer form our type // list types.InsertUnique(matching_type->shared_from_this()); @@ -2519,11 +2529,11 @@ // contain the template parameters. Try again stripping '<' and anything // after, filtering out entries with template parameters that don't match. if (types.GetSize() < max_matches) { - const llvm::StringRef name_ref = name.GetStringRef(); - auto it = name_ref.find('<'); - if (it != llvm::StringRef::npos) { - const llvm::StringRef name_no_template_params = name_ref.slice(0, it); - const llvm::StringRef template_params = name_ref.slice(it, name_ref.size()); + if (name_bracket_index != llvm::StringRef::npos) { + const llvm::StringRef name_no_template_params = + name_ref.slice(0, name_bracket_index); + const llvm::StringRef template_params = + name_ref.slice(name_bracket_index, name_ref.size()); m_index->GetTypes(ConstString(name_no_template_params), [&](DWARFDIE die) { if (!DIEInDeclContext(parent_decl_ctx, die)) return true; // The containing decl contexts don't match diff --git a/lldb/test/API/lang/cpp/unique-types4/Makefile b/lldb/test/API/lang/cpp/unique-types4/Makefile new file mode 100644 --- /dev/null +++ b/lldb/test/API/lang/cpp/unique-types4/Makefile @@ -0,0 +1,3 @@ +CXX_SOURCES := main.cpp + +include Makefile.rules diff --git a/lldb/test/API/lang/cpp/unique-types4/TestUniqueTypes4.py b/lldb/test/API/lang/cpp/unique-types4/TestUniqueTypes4.py new file mode 100644 --- /dev/null +++ b/lldb/test/API/lang/cpp/unique-types4/TestUniqueTypes4.py @@ -0,0 +1,27 @@ +""" +Test that we return only the requested template instantiation. +""" + +import lldb +import lldbsuite.test.lldbutil as lldbutil +from lldbsuite.test.decorators import * +from lldbsuite.test.lldbtest import * + +class UniqueTypesTestCase4(TestBase): + def do_test(self, debug_flags): + """Test that we display the correct template instantiation.""" + self.build(dictionary=debug_flags) + lldbutil.run_to_source_breakpoint(self, "// Set breakpoint here", lldb.SBFileSpec("main.cpp")) + # FIXME: thes should successfully print the values + self.expect("print ns::Foo::value", "failed to parse", error=True) + self.expect("print ns::Foo::value", "failed to parse", error=True) + + @skipIf(compiler=no_match("clang")) + @skipIf(compiler_version=["<", "15.0"]) + def test_simple_template_names(self): + self.do_test(dict(CFLAGS_EXTRAS="-gsimple-template-names")) + + @skipIf(compiler=no_match("clang")) + @skipIf(compiler_version=["<", "15.0"]) + def test_no_simple_template_names(self): + self.do_test(dict(CFLAGS_EXTRAS="-gno-simple-template-names")) diff --git a/lldb/test/API/lang/cpp/unique-types4/main.cpp b/lldb/test/API/lang/cpp/unique-types4/main.cpp new file mode 100644 --- /dev/null +++ b/lldb/test/API/lang/cpp/unique-types4/main.cpp @@ -0,0 +1,14 @@ +namespace ns { + +template struct Foo { + static T value; +}; + +} // namespace ns + +ns::Foo a; +ns::Foo b; + +int main() { + // Set breakpoint here +}