-
Notifications
You must be signed in to change notification settings - Fork 14.7k
[LLDB][NativePDB] Implement FindNamespace
#151950
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[LLDB][NativePDB] Implement FindNamespace
#151950
Conversation
@llvm/pr-subscribers-lldb Author: nerix (Nerixyz) Changes
This is mostly the same as in SymbolFilePDB as well as PDBAstParser: The AST parser/builder saves the created namespaces in a map to lookup when a namespace is requested. This is working towards making Shell/SymbolFile/PDB/expressions.test pass with the native PDB plugin. Full diff: https://github.com/llvm/llvm-project/pull/151950.diff 4 Files Affected:
diff --git a/lldb/source/Plugins/SymbolFile/NativePDB/PdbAstBuilder.cpp b/lldb/source/Plugins/SymbolFile/NativePDB/PdbAstBuilder.cpp
index 8137622842253..92a102bbc92a8 100644
--- a/lldb/source/Plugins/SymbolFile/NativePDB/PdbAstBuilder.cpp
+++ b/lldb/source/Plugins/SymbolFile/NativePDB/PdbAstBuilder.cpp
@@ -644,9 +644,12 @@ clang::Decl *PdbAstBuilder::TryGetDecl(PdbSymUid uid) const {
clang::NamespaceDecl *
PdbAstBuilder::GetOrCreateNamespaceDecl(const char *name,
clang::DeclContext &context) {
- return m_clang.GetUniqueNamespaceDeclaration(
+ clang::NamespaceDecl *ns = m_clang.GetUniqueNamespaceDeclaration(
IsAnonymousNamespaceName(name) ? nullptr : name, &context,
OptionalClangModuleID());
+ m_known_namespaces.insert(ns);
+ m_parent_to_namespaces[&context].insert(ns);
+ return ns;
}
clang::BlockDecl *
@@ -1452,3 +1455,30 @@ PdbAstBuilder::FromCompilerDeclContext(CompilerDeclContext context) {
void PdbAstBuilder::Dump(Stream &stream, llvm::StringRef filter) {
m_clang.Dump(stream.AsRawOstream(), filter);
}
+
+clang::NamespaceDecl *
+PdbAstBuilder::FindNamespaceDecl(const clang::DeclContext *parent,
+ llvm::StringRef name) {
+ NamespaceSet *set;
+ if (parent) {
+ auto it = m_parent_to_namespaces.find(parent);
+ if (it == m_parent_to_namespaces.end())
+ return nullptr;
+
+ set = &it->second;
+ } else {
+ // In this case, search through all known namespaces
+ set = &m_known_namespaces;
+ }
+ assert(set);
+
+ for (clang::NamespaceDecl *namespace_decl : *set)
+ if (namespace_decl->getName() == name)
+ return namespace_decl;
+
+ for (clang::NamespaceDecl *namespace_decl : *set)
+ if (namespace_decl->isAnonymousNamespace())
+ return FindNamespaceDecl(namespace_decl, name);
+
+ return nullptr;
+}
diff --git a/lldb/source/Plugins/SymbolFile/NativePDB/PdbAstBuilder.h b/lldb/source/Plugins/SymbolFile/NativePDB/PdbAstBuilder.h
index 66a3836fac053..fef65227bc8f5 100644
--- a/lldb/source/Plugins/SymbolFile/NativePDB/PdbAstBuilder.h
+++ b/lldb/source/Plugins/SymbolFile/NativePDB/PdbAstBuilder.h
@@ -89,6 +89,9 @@ class PdbAstBuilder {
void Dump(Stream &stream, llvm::StringRef filter);
+ clang::NamespaceDecl *FindNamespaceDecl(const clang::DeclContext *parent,
+ llvm::StringRef name);
+
private:
clang::Decl *TryGetDecl(PdbSymUid uid) const;
@@ -150,7 +153,15 @@ class PdbAstBuilder {
llvm::DenseMap<lldb::opaque_compiler_type_t,
llvm::SmallSet<std::pair<llvm::StringRef, CompilerType>, 8>>
m_cxx_record_map;
- llvm::DenseSet<clang::NamespaceDecl *> m_parsed_namespaces;
+
+ using NamespaceSet = llvm::DenseSet<clang::NamespaceDecl *>;
+
+ // These namespaces are fully parsed
+ NamespaceSet m_parsed_namespaces;
+
+ // We know about these namespaces, but they might not be completely parsed yet
+ NamespaceSet m_known_namespaces;
+ llvm::DenseMap<clang::DeclContext *, NamespaceSet> m_parent_to_namespaces;
};
} // namespace npdb
diff --git a/lldb/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.cpp b/lldb/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.cpp
index 7af53e16ce9d5..0fe411e598545 100644
--- a/lldb/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.cpp
+++ b/lldb/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.cpp
@@ -2164,9 +2164,36 @@ void SymbolFileNativePDB::GetTypes(lldb_private::SymbolContextScope *sc_scope,
TypeClass type_mask,
lldb_private::TypeList &type_list) {}
-CompilerDeclContext SymbolFileNativePDB::FindNamespace(
- ConstString name, const CompilerDeclContext &parent_decl_ctx, bool) {
- return {};
+CompilerDeclContext
+SymbolFileNativePDB::FindNamespace(ConstString name,
+ const CompilerDeclContext &parent_decl_ctx,
+ bool /* only_root_namespaces */) {
+ std::lock_guard<std::recursive_mutex> guard(GetModuleMutex());
+ auto ts_or_err = GetTypeSystemForLanguage(lldb::eLanguageTypeC_plus_plus);
+ if (auto err = ts_or_err.takeError())
+ return {};
+ auto ts = *ts_or_err;
+ if (!ts)
+ return {};
+ auto *clang = llvm::dyn_cast_or_null<TypeSystemClang>(ts.get());
+ if (!clang)
+ return {};
+
+ PdbAstBuilder *ast_builder = clang->GetNativePDBParser();
+ if (!ast_builder)
+ return {};
+
+ clang::DeclContext *decl_context = nullptr;
+ if (parent_decl_ctx)
+ decl_context = static_cast<clang::DeclContext *>(
+ parent_decl_ctx.GetOpaqueDeclContext());
+
+ auto *namespace_decl =
+ ast_builder->FindNamespaceDecl(decl_context, name.GetStringRef());
+ if (!namespace_decl)
+ return CompilerDeclContext();
+
+ return clang->CreateDeclContext(namespace_decl);
}
llvm::Expected<lldb::TypeSystemSP>
diff --git a/lldb/test/Shell/SymbolFile/NativePDB/namespace-access.test b/lldb/test/Shell/SymbolFile/NativePDB/namespace-access.test
index f6c1ccf22fa18..22ecfa16a11fb 100644
--- a/lldb/test/Shell/SymbolFile/NativePDB/namespace-access.test
+++ b/lldb/test/Shell/SymbolFile/NativePDB/namespace-access.test
@@ -77,8 +77,18 @@ type lookup Outer::Inner2::S
type lookup Outer::A
type lookup A
type lookup ::A
+# Test that Clang can find the namespaces as well
expr sizeof(S)
+expr sizeof(::S)
+expr sizeof(Outer::S)
+expr sizeof(Outer::Inner1::S)
+expr sizeof(Inner1::S)
+expr sizeof(Outer::Inner1::Inner2::S)
+expr sizeof(Inner2::S)
+expr sizeof(Outer::Inner2::S)
+expr sizeof(Outer::A)
expr sizeof(A)
+expr sizeof(::A)
quit
@@ -131,5 +141,23 @@ quit
# CHECK-NEXT: }
# CHECK-NEXT: (lldb) expr sizeof(S)
# CHECK-NEXT: (__size_t) $0 = 1
+# CHECK-NEXT: (lldb) expr sizeof(::S)
+# CHECK-NEXT: (__size_t) $1 = 1
+# CHECK-NEXT: (lldb) expr sizeof(Outer::S)
+# CHECK-NEXT: (__size_t) $2 = 2
+# CHECK-NEXT: (lldb) expr sizeof(Outer::Inner1::S)
+# CHECK-NEXT: (__size_t) $3 = 3
+# CHECK-NEXT: (lldb) expr sizeof(Inner1::S)
+# CHECK-NEXT: (__size_t) $4 = 3
+# CHECK-NEXT: (lldb) expr sizeof(Outer::Inner1::Inner2::S)
+# CHECK-NEXT: (__size_t) $5 = 4
+# CHECK-NEXT: (lldb) expr sizeof(Inner2::S)
+# CHECK-NEXT: (__size_t) $6 = 5
+# CHECK-NEXT: (lldb) expr sizeof(Outer::Inner2::S)
+# CHECK-NEXT: (__size_t) $7 = 5
+# CHECK-NEXT: (lldb) expr sizeof(Outer::A)
+# CHECK-NEXT: (__size_t) $8 = 6
# CHECK-NEXT: (lldb) expr sizeof(A)
-# CHECK-NEXT: (__size_t) $1 = 7
+# CHECK-NEXT: (__size_t) $9 = 7
+# CHECK-NEXT: (lldb) expr sizeof(::A)
+# CHECK-NEXT: (__size_t) $10 = 7
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
SGTM
Would be nice to share code between the PDB plugins, but then again, if we're going to get rid of the PDB plugin, duplicating this bit isn't that big of a deal
FindNamespace
was not implemented forSymbolFileNativePDB
. Without it, it wasn't possible to lookup items through namespaces when evaluating expressions.This is mostly the same as in SymbolFilePDB as well as PDBAstParser: The AST parser/builder saves the created namespaces in a map to lookup when a namespace is requested.
This is working towards making Shell/SymbolFile/PDB/expressions.test pass with the native PDB plugin.