diff --git a/lldb/include/lldb/Symbol/SymbolFile.h b/lldb/include/lldb/Symbol/SymbolFile.h --- a/lldb/include/lldb/Symbol/SymbolFile.h +++ b/lldb/include/lldb/Symbol/SymbolFile.h @@ -331,6 +331,12 @@ return CompilerDeclContext(); } + virtual CompilerDeclContext + FindNamespace(ConstString name, const CompilerDeclContext &parent_decl_ctx, + bool only_root_namespaces) { + return CompilerDeclContext(); + } + virtual ObjectFile *GetObjectFile() = 0; virtual const ObjectFile *GetObjectFile() const = 0; virtual ObjectFile *GetMainObjectFile() = 0; diff --git a/lldb/source/Plugins/ExpressionParser/Clang/ClangASTSource.cpp b/lldb/source/Plugins/ExpressionParser/Clang/ClangASTSource.cpp --- a/lldb/source/Plugins/ExpressionParser/Clang/ClangASTSource.cpp +++ b/lldb/source/Plugins/ExpressionParser/Clang/ClangASTSource.cpp @@ -700,7 +700,8 @@ if (!symbol_file) continue; - found_namespace_decl = symbol_file->FindNamespace(name, namespace_decl); + found_namespace_decl = + symbol_file->FindNamespace(name, namespace_decl, true); if (found_namespace_decl) { context.m_namespace_map->push_back( @@ -1674,7 +1675,7 @@ continue; found_namespace_decl = - symbol_file->FindNamespace(name, null_namespace_decl); + symbol_file->FindNamespace(name, null_namespace_decl, true); if (!found_namespace_decl) continue; diff --git a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h --- a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h +++ b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h @@ -218,6 +218,11 @@ lldb_private::ConstString name, const lldb_private::CompilerDeclContext &parent_decl_ctx) override; + lldb_private::CompilerDeclContext + FindNamespace(lldb_private::ConstString name, + const lldb_private::CompilerDeclContext &parent_decl_ctx, + bool only_root_namespaces) override; + void PreloadSymbols() override; std::recursive_mutex &GetModuleMutex() const override; 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 @@ -2633,6 +2633,13 @@ CompilerDeclContext SymbolFileDWARF::FindNamespace(ConstString name, const CompilerDeclContext &parent_decl_ctx) { + return FindNamespace(name, parent_decl_ctx, false); +} + +CompilerDeclContext +SymbolFileDWARF::FindNamespace(ConstString name, + const CompilerDeclContext &parent_decl_ctx, + bool only_root_namespaces) { std::lock_guard guard(GetModuleMutex()); Log *log = GetLog(DWARFLog::Lookups); @@ -2648,6 +2655,11 @@ return namespace_decl_ctx; m_index->GetNamespaces(name, [&](DWARFDIE die) { + // We want only root namespaces. + if (only_root_namespaces && + die.GetParent().Tag() != dwarf::DW_TAG_compile_unit && !parent_decl_ctx) + return true; + if (!DIEInDeclContext(parent_decl_ctx, die)) return true; // The containing decl contexts don't match diff --git a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.h b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.h --- a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.h +++ b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.h @@ -139,6 +139,10 @@ lldb_private::CompilerDeclContext FindNamespace( lldb_private::ConstString name, const lldb_private::CompilerDeclContext &parent_decl_ctx) override; + lldb_private::CompilerDeclContext + FindNamespace(lldb_private::ConstString name, + const lldb_private::CompilerDeclContext &parent_decl_ctx, + bool only_root_namespaces) override; void GetTypes(lldb_private::SymbolContextScope *sc_scope, lldb::TypeClass type_mask, lldb_private::TypeList &type_list) override; diff --git a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.cpp b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.cpp --- a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.cpp +++ b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.cpp @@ -1258,11 +1258,18 @@ CompilerDeclContext SymbolFileDWARFDebugMap::FindNamespace( lldb_private::ConstString name, const CompilerDeclContext &parent_decl_ctx) { + return FindNamespace(name, parent_decl_ctx, false); +} + +CompilerDeclContext SymbolFileDWARFDebugMap::FindNamespace( + lldb_private::ConstString name, const CompilerDeclContext &parent_decl_ctx, + bool only_root_namespaces) { std::lock_guard guard(GetModuleMutex()); CompilerDeclContext matching_namespace; ForEachSymbolFile([&](SymbolFileDWARF *oso_dwarf) -> bool { - matching_namespace = oso_dwarf->FindNamespace(name, parent_decl_ctx); + matching_namespace = + oso_dwarf->FindNamespace(name, parent_decl_ctx, only_root_namespaces); return (bool)matching_namespace; }); diff --git a/lldb/test/API/commands/expression/inline-namespace/TestInlineNamespace.py b/lldb/test/API/commands/expression/inline-namespace/TestInlineNamespace.py --- a/lldb/test/API/commands/expression/inline-namespace/TestInlineNamespace.py +++ b/lldb/test/API/commands/expression/inline-namespace/TestInlineNamespace.py @@ -46,7 +46,7 @@ self.expect("expr A::other_var", error=True, substrs=["no member named 'other_var' in namespace 'A'"]) self.expect("expr A::B::other_var", error=True, substrs=["no member named 'other_var' in namespace 'A::B'"]) - self.expect("expr B::other_var", error=True, substrs=["no member named 'other_var' in namespace 'A::B'"]) + self.expect("expr B::other_var", error=True, substrs=["use of undeclared identifier 'B'"]) # 'frame variable' can correctly distinguish between A::B::global_var and A::global_var gvars = self.target().FindGlobalVariables("A::global_var", 10) diff --git a/lldb/test/API/lang/cpp/namespace/TestNamespace.py b/lldb/test/API/lang/cpp/namespace/TestNamespace.py --- a/lldb/test/API/lang/cpp/namespace/TestNamespace.py +++ b/lldb/test/API/lang/cpp/namespace/TestNamespace.py @@ -23,7 +23,8 @@ "func(int)", "A::B::func()", "A::func()", - "A::func(int)"] + "A::func(int)", + "B::func()"] # Create a target by the debugger. exe = self.getBuildArtifact("a.out") @@ -225,3 +226,6 @@ self.expect("expression variadic_sum", patterns=[ '\(anonymous namespace\)::variadic_sum\(int, ...\)']) + + self.expect_expr("::B::Bar b; b.x()", result_type="int", result_value="42") + self.expect_expr("A::B::Bar b; b.y()", result_type="int", result_value="137") diff --git a/lldb/test/API/lang/cpp/namespace/main.cpp b/lldb/test/API/lang/cpp/namespace/main.cpp --- a/lldb/test/API/lang/cpp/namespace/main.cpp +++ b/lldb/test/API/lang/cpp/namespace/main.cpp @@ -102,6 +102,18 @@ return myfunc2(3) + j + i + a + 2 + anon_uint + a_uint + b_uint + y_uint; // Set break point at this line. } +namespace B { +struct Bar { + int x() { return 42; } +}; +} // namespace B + +namespace A::B { +struct Bar { + int y() { return 137; } +}; +} // namespace A::B + int main (int argc, char const *argv[]) { @@ -112,5 +124,7 @@ A::B::test_lookup_at_nested_ns_scope_after_using(); test_lookup_before_using_directive(); test_lookup_after_using_directive(); - return Foo::myfunc(12); + ::B::Bar bb; + A::B::Bar ab; + return Foo::myfunc(12) + bb.x() + ab.y(); } diff --git a/lldb/test/API/lang/cpp/namespace/ns.cpp b/lldb/test/API/lang/cpp/namespace/ns.cpp --- a/lldb/test/API/lang/cpp/namespace/ns.cpp +++ b/lldb/test/API/lang/cpp/namespace/ns.cpp @@ -21,3 +21,7 @@ std::printf("at global scope: foo() = %d\n", foo()); // eval foo(), exp: 42 std::printf("at global scope: func() = %d\n", func()); // eval func(), exp: 1 } + +namespace B { +int func() { return 4; } +} // namespace B