virtual llvm::Expected<lldb::TypeSystemSP>
GetTypeSystemForLanguage(lldb::LanguageType language) = 0;
+ /// Finds a namespace of name \ref name and whose parent
+ /// context is \ref parent_decl_ctx.
+ ///
+ /// If \code{.cpp} !parent_decl_ctx.IsValid() \endcode
+ /// then this function will consider all namespaces that
+ /// match the name. If \ref only_root_namespaces is
+ /// true, only consider in the search those DIEs that
+ /// represent top-level namespaces.
virtual CompilerDeclContext
- FindNamespace(ConstString name, const CompilerDeclContext &parent_decl_ctx) {
+ FindNamespace(ConstString name, const CompilerDeclContext &parent_decl_ctx,
+ bool only_root_namespaces = false) {
return CompilerDeclContext();
}
llvm::Expected<lldb::TypeSystemSP>
GetTypeSystemForLanguage(lldb::LanguageType language) override;
- 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;
std::vector<std::unique_ptr<lldb_private::CallEdge>>
ParseCallEdgesInFunction(UserID func_id) override;
if (!symbol_file)
continue;
- found_namespace_decl = symbol_file->FindNamespace(name, namespace_decl);
+ // If namespace_decl is not valid, 'FindNamespace' would look for
+ // any namespace called 'name' (ignoring parent contexts) and return
+ // the first one it finds. Thus if we're doing a qualified lookup only
+ // consider root namespaces. E.g., in an expression ::A::B::Foo, the
+ // lookup of ::A will result in a qualified lookup. Note, namespace
+ // disambiguation for function calls are handled separately in
+ // SearchFunctionsInSymbolContexts.
+ const bool find_root_namespaces =
+ context.m_decl_context &&
+ context.m_decl_context->shouldUseQualifiedLookup();
+ found_namespace_decl = symbol_file->FindNamespace(
+ name, namespace_decl, /* only root namespaces */ find_root_namespaces);
if (found_namespace_decl) {
context.m_namespace_map->push_back(
llvm::inconvertibleErrorCode());
}
- CompilerDeclContext
- FindNamespace(ConstString name,
- const CompilerDeclContext &parent_decl_ctx) override {
+ CompilerDeclContext FindNamespace(ConstString name,
+ const CompilerDeclContext &parent_decl_ctx,
+ bool only_root_namespaces) override {
return CompilerDeclContext();
}
}
bool SymbolFileDWARF::DIEInDeclContext(const CompilerDeclContext &decl_ctx,
- const DWARFDIE &die) {
+ const DWARFDIE &die,
+ bool only_root_namespaces) {
// If we have no parent decl context to match this DIE matches, and if the
// parent decl context isn't valid, we aren't trying to look for any
// particular decl context so any die matches.
- if (!decl_ctx.IsValid())
+ if (!decl_ctx.IsValid()) {
+ // ...But if we are only checking root decl contexts, confirm that the
+ // 'die' is a top-level context.
+ if (only_root_namespaces)
+ return die.GetParent().Tag() == dwarf::DW_TAG_compile_unit;
+
return true;
+ }
if (die) {
if (DWARFASTParser *dwarf_ast = GetDWARFParser(*die.GetCU())) {
CompilerDeclContext
SymbolFileDWARF::FindNamespace(ConstString name,
- const CompilerDeclContext &parent_decl_ctx) {
+ const CompilerDeclContext &parent_decl_ctx,
+ bool only_root_namespaces) {
std::lock_guard<std::recursive_mutex> guard(GetModuleMutex());
Log *log = GetLog(DWARFLog::Lookups);
return namespace_decl_ctx;
m_index->GetNamespaces(name, [&](DWARFDIE die) {
- if (!DIEInDeclContext(parent_decl_ctx, die))
+ if (!DIEInDeclContext(parent_decl_ctx, die, only_root_namespaces))
return true; // The containing decl contexts don't match
DWARFASTParser *dwarf_ast = GetDWARFParser(*die.GetCU());
llvm::Expected<lldb::TypeSystemSP>
GetTypeSystemForLanguage(lldb::LanguageType language) override;
- 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 PreloadSymbols() override;
static bool
DIEInDeclContext(const lldb_private::CompilerDeclContext &parent_decl_ctx,
- const DWARFDIE &die);
+ const DWARFDIE &die, bool only_root_namespaces = false);
std::vector<std::unique_ptr<lldb_private::CallEdge>>
ParseCallEdgesInFunction(lldb_private::UserID func_id) override;
}
CompilerDeclContext SymbolFileDWARFDebugMap::FindNamespace(
- lldb_private::ConstString name,
- const CompilerDeclContext &parent_decl_ctx) {
+ lldb_private::ConstString name, const CompilerDeclContext &parent_decl_ctx,
+ bool only_root_namespaces) {
std::lock_guard<std::recursive_mutex> 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;
});
lldb_private::LanguageSet languages,
llvm::DenseSet<lldb_private::SymbolFile *> &searched_symbol_files,
lldb_private::TypeMap &types) override;
- 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;
TypeClass type_mask,
lldb_private::TypeList &type_list) {}
-CompilerDeclContext
-SymbolFileNativePDB::FindNamespace(ConstString name,
- const CompilerDeclContext &parent_decl_ctx) {
+CompilerDeclContext SymbolFileNativePDB::FindNamespace(
+ ConstString name, const CompilerDeclContext &parent_decl_ctx, bool) {
return {};
}
llvm::Expected<lldb::TypeSystemSP>
GetTypeSystemForLanguage(lldb::LanguageType language) override;
- CompilerDeclContext
- FindNamespace(ConstString name,
- const CompilerDeclContext &parent_decl_ctx) override;
+ CompilerDeclContext FindNamespace(ConstString name,
+ const CompilerDeclContext &parent_decl_ctx,
+ bool only_root_namespaces) override;
llvm::StringRef GetPluginName() override { return GetPluginNameStatic(); }
lldb_private::CompilerDeclContext
SymbolFilePDB::FindNamespace(lldb_private::ConstString name,
- const CompilerDeclContext &parent_decl_ctx) {
+ const CompilerDeclContext &parent_decl_ctx, bool) {
std::lock_guard<std::recursive_mutex> guard(GetModuleMutex());
auto type_system_or_err =
GetTypeSystemForLanguage(lldb::eLanguageTypeC_plus_plus);
llvm::Expected<lldb::TypeSystemSP>
GetTypeSystemForLanguage(lldb::LanguageType language) override;
- 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;
llvm::StringRef GetPluginName() override { return GetPluginNameStatic(); }
CompilerDeclContext
SymbolFileOnDemand::FindNamespace(ConstString name,
- const CompilerDeclContext &parent_decl_ctx) {
+ const CompilerDeclContext &parent_decl_ctx,
+ bool only_root_namespaces) {
if (!m_debug_info_enabled) {
LLDB_LOG(GetLog(), "[{0}] {1}({2}) is skipped", GetSymbolFileName(),
__FUNCTION__, name);
- return SymbolFile::FindNamespace(name, parent_decl_ctx);
+ return SymbolFile::FindNamespace(name, parent_decl_ctx,
+ only_root_namespaces);
}
- return m_sym_file_impl->FindNamespace(name, parent_decl_ctx);
+ return m_sym_file_impl->FindNamespace(name, parent_decl_ctx,
+ only_root_namespaces);
}
std::vector<std::unique_ptr<lldb_private::CallEdge>>
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")
+ self.expect_expr("::NS1::NS2::Foo{}.bar() == -2 && ::NS2::Foo{}.bar() == -3",
+ result_type="bool", result_value="true")
+ # FIXME: C++ unqualified namespace lookups currently not supported when instantiating types.
+ self.expect_expr("NS2::Foo{}.bar() == -3", result_type="bool", result_value="false")
+ self.expect_expr("((::B::Bar*)&::B::bar)->x()", result_type="int", result_value="42")
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; }
+};
+Bar bar;
+} // namespace B
+
+namespace A::B {
+struct Bar {
+ int y() { return 137; }
+};
+} // namespace A::B
+
+namespace NS1::NS2 {
+struct Foo {
+ int bar() { return -2; }
+};
+} // namespace NS1::NS2
+
+namespace NS2 {
+struct Foo {
+ int bar() { return -3; }
+};
+} // namespace NS2
+
int
main (int argc, char const *argv[])
{
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() + NS1::NS2::Foo{}.bar() +
+ NS2::Foo{}.bar();
}