[Lldb-commits] [lldb] [lldb][NativePDB] Name global variables like Clang and DWARF do (PR #230563)

Charles Zablit via lldb-commits lldb-commits at lists.llvm.org
Tue Oct 13 06:00:16 PDT 2026


https://github.com/charles-zablit updated https://github.com/llvm/llvm-project/pull/230563

>From ff180473a4768f5e37ab0e0bbefda0bb08566146 Mon Sep 17 00:00:00 2001
From: Charles Zablit <c_zablit at apple.com>
Date: Fri, 9 Oct 2026 16:45:58 +0100
Subject: [PATCH 1/2] [lldb][NativePDB] Name global variables like Clang and
 DWARF do

---
 .../NativePDB/SymbolFileNativePDB.cpp         | 35 ++++++++++++++-----
 .../TestCPPGlobalVariables.py                 |  2 ++
 2 files changed, 29 insertions(+), 8 deletions(-)

diff --git a/lldb/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.cpp b/lldb/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.cpp
index 9ed1d327851fbe..dd27d643101a9d 100644
--- a/lldb/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.cpp
+++ b/lldb/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.cpp
@@ -180,6 +180,25 @@ loadMatchingPDBFile(std::string exe_path, llvm::BumpPtrAllocator &allocator) {
   return pdb;
 }
 
+static std::string GetClangQualifiedName(llvm::StringRef name) {
+  std::string result;
+  while (!name.empty()) {
+    size_t pos = name.find('`');
+    result += name.take_front(pos);
+    if (pos == llvm::StringRef::npos)
+      break;
+    name = name.drop_front(pos);
+    if (name.consume_front("`anonymous namespace'") ||
+        name.consume_front("`anonymous-namespace'")) {
+      result += "(anonymous namespace)";
+    } else {
+      result += name.front();
+      name = name.drop_front();
+    }
+  }
+  return result;
+}
+
 static bool IsFunctionPrologue(const CompilandIndexItem &cci,
                                lldb::addr_t addr) {
   // FIXME: Implement this.
@@ -1139,9 +1158,10 @@ VariableSP SymbolFileNativePDB::CreateGlobalVariable(PdbGlobalSymId var_id) {
   bool location_is_constant_data = false;
   bool static_member = false;
   VariableSP var_sp = std::make_shared<Variable>(
-      toOpaqueUid(var_id), name.str().c_str(), mangled_name.str().c_str(),
-      type_sp, scope, comp_unit.get(), ranges, &decl, location, is_external,
-      artificial, location_is_constant_data, static_member);
+      toOpaqueUid(var_id), GetClangQualifiedName(name).c_str(),
+      mangled_name.str().c_str(), type_sp, scope, comp_unit.get(), ranges,
+      &decl, location, is_external, artificial, location_is_constant_data,
+      static_member);
 
   return var_sp;
 }
@@ -1161,8 +1181,6 @@ SymbolFileNativePDB::CreateConstantSymbol(PdbGlobalSymId var_id,
                    "Failed to deserialize ConstantSym record: {0}");
     return nullptr;
   }
-  std::string global_name("::");
-  global_name += constant.Name;
   PdbTypeSymId tid(constant.Type, false);
   SymbolFileTypeSP type_sp =
       std::make_shared<SymbolFileType>(*this, toOpaqueUid(tid));
@@ -1185,9 +1203,10 @@ SymbolFileNativePDB::CreateConstantSymbol(PdbGlobalSymId var_id,
   bool location_is_constant_data = true;
   bool static_member = false;
   VariableSP var_sp = std::make_shared<Variable>(
-      toOpaqueUid(var_id), constant.Name.str().c_str(), global_name.c_str(),
-      type_sp, eValueTypeVariableGlobal, module.get(), ranges, &decl, location,
-      external, artificial, location_is_constant_data, static_member);
+      toOpaqueUid(var_id), GetClangQualifiedName(constant.Name).c_str(),
+      /*mangled=*/nullptr, type_sp, eValueTypeVariableGlobal, module.get(),
+      ranges, &decl, location, external, artificial, location_is_constant_data,
+      static_member);
   return var_sp;
 }
 
diff --git a/lldb/test/API/lang/cpp/global_variables/TestCPPGlobalVariables.py b/lldb/test/API/lang/cpp/global_variables/TestCPPGlobalVariables.py
index 9d964634adbbd3..83b57d7412ee71 100644
--- a/lldb/test/API/lang/cpp/global_variables/TestCPPGlobalVariables.py
+++ b/lldb/test/API/lang/cpp/global_variables/TestCPPGlobalVariables.py
@@ -7,6 +7,8 @@
 
 
 class GlobalVariablesCppTestCase(TestBase):
+    TEST_WITH_PDB_DEBUG_INFO = True
+
     def setUp(self):
         TestBase.setUp(self)
         self.source = lldb.SBFileSpec("main.cpp")

>From e1653cb5d4837f3c4b4edacfc5aef424db545f3c Mon Sep 17 00:00:00 2001
From: Charles Zablit <c_zablit at apple.com>
Date: Tue, 13 Oct 2026 13:59:59 +0100
Subject: [PATCH 2/2] fixup! [lldb][NativePDB] Name global variables like Clang
 and DWARF do

---
 .../SymbolFile/NativePDB/PdbAstBuilder.h      |  6 +++
 .../NativePDB/PdbAstBuilderClang.cpp          | 19 ++++++++
 .../SymbolFile/NativePDB/PdbAstBuilderClang.h |  2 +
 .../NativePDB/SymbolFileNativePDB.cpp         | 43 ++++++++-----------
 4 files changed, 45 insertions(+), 25 deletions(-)

diff --git a/lldb/source/Plugins/SymbolFile/NativePDB/PdbAstBuilder.h b/lldb/source/Plugins/SymbolFile/NativePDB/PdbAstBuilder.h
index 8356ead4918902..ae80018ac350bc 100644
--- a/lldb/source/Plugins/SymbolFile/NativePDB/PdbAstBuilder.h
+++ b/lldb/source/Plugins/SymbolFile/NativePDB/PdbAstBuilder.h
@@ -17,6 +17,8 @@
 
 #include "PdbSymUid.h"
 
+#include <string>
+
 namespace lldb_private {
 class Stream;
 
@@ -46,6 +48,10 @@ class PdbAstBuilder {
   virtual CompilerDeclContext FindNamespaceDecl(CompilerDeclContext parent_ctx,
                                                 llvm::StringRef name) = 0;
 
+  /// Convert a CodeView qualified name into the spelling used by the
+  /// language of this AST (e.g. anonymous namespaces).
+  virtual std::string GetQualifiedName(llvm::StringRef name) = 0;
+
   virtual void Dump(Stream &stream, llvm::StringRef filter,
                     bool show_color) = 0;
 };
diff --git a/lldb/source/Plugins/SymbolFile/NativePDB/PdbAstBuilderClang.cpp b/lldb/source/Plugins/SymbolFile/NativePDB/PdbAstBuilderClang.cpp
index 66a3990a54f635..1599ddcf42caf5 100644
--- a/lldb/source/Plugins/SymbolFile/NativePDB/PdbAstBuilderClang.cpp
+++ b/lldb/source/Plugins/SymbolFile/NativePDB/PdbAstBuilderClang.cpp
@@ -1756,6 +1756,25 @@ PdbAstBuilderClang::FromCompilerDeclContext(CompilerDeclContext context) {
   return static_cast<clang::DeclContext *>(context.GetOpaqueDeclContext());
 }
 
+std::string PdbAstBuilderClang::GetQualifiedName(llvm::StringRef name) {
+  std::string result;
+  while (!name.empty()) {
+    size_t pos = name.find('`');
+    result += name.take_front(pos);
+    if (pos == llvm::StringRef::npos)
+      break;
+    name = name.drop_front(pos);
+    if (name.consume_front("`anonymous namespace'") ||
+        name.consume_front("`anonymous-namespace'")) {
+      result += "(anonymous namespace)";
+    } else {
+      result += name.front();
+      name = name.drop_front();
+    }
+  }
+  return result;
+}
+
 void PdbAstBuilderClang::Dump(Stream &stream, llvm::StringRef filter,
                               bool show_color) {
   m_clang.Dump(stream.AsRawOstream(), filter, show_color);
diff --git a/lldb/source/Plugins/SymbolFile/NativePDB/PdbAstBuilderClang.h b/lldb/source/Plugins/SymbolFile/NativePDB/PdbAstBuilderClang.h
index 4eae85b37522e6..71f8074d9150bc 100644
--- a/lldb/source/Plugins/SymbolFile/NativePDB/PdbAstBuilderClang.h
+++ b/lldb/source/Plugins/SymbolFile/NativePDB/PdbAstBuilderClang.h
@@ -75,6 +75,8 @@ class PdbAstBuilderClang : public PdbAstBuilder {
   CompilerDeclContext FindNamespaceDecl(CompilerDeclContext parent_ctx,
                                         llvm::StringRef name) override;
 
+  std::string GetQualifiedName(llvm::StringRef name) override;
+
   void Dump(Stream &stream, llvm::StringRef filter, bool show_color) override;
 
   // Clang-specific
diff --git a/lldb/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.cpp b/lldb/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.cpp
index dd27d643101a9d..183a751aabd9ef 100644
--- a/lldb/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.cpp
+++ b/lldb/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.cpp
@@ -180,25 +180,6 @@ loadMatchingPDBFile(std::string exe_path, llvm::BumpPtrAllocator &allocator) {
   return pdb;
 }
 
-static std::string GetClangQualifiedName(llvm::StringRef name) {
-  std::string result;
-  while (!name.empty()) {
-    size_t pos = name.find('`');
-    result += name.take_front(pos);
-    if (pos == llvm::StringRef::npos)
-      break;
-    name = name.drop_front(pos);
-    if (name.consume_front("`anonymous namespace'") ||
-        name.consume_front("`anonymous-namespace'")) {
-      result += "(anonymous namespace)";
-    } else {
-      result += name.front();
-      name = name.drop_front();
-    }
-  }
-  return result;
-}
-
 static bool IsFunctionPrologue(const CompilandIndexItem &cci,
                                lldb::addr_t addr) {
   // FIXME: Implement this.
@@ -1144,9 +1125,12 @@ VariableSP SymbolFileNativePDB::CreateGlobalVariable(PdbGlobalSymId var_id) {
   if (auto err = ts_or_err.takeError())
     return nullptr;
   auto ts = *ts_or_err;
+  std::string var_name = name.str();
   if (ts) {
-    if (PdbAstBuilder *ast_builder = ts->GetNativePDBParser())
+    if (PdbAstBuilder *ast_builder = ts->GetNativePDBParser()) {
       ast_builder->EnsureVariable(var_id);
+      var_name = ast_builder->GetQualifiedName(name);
+    }
   }
 
   DWARFExpressionList location(module_sp, location_expr, nullptr);
@@ -1158,10 +1142,9 @@ VariableSP SymbolFileNativePDB::CreateGlobalVariable(PdbGlobalSymId var_id) {
   bool location_is_constant_data = false;
   bool static_member = false;
   VariableSP var_sp = std::make_shared<Variable>(
-      toOpaqueUid(var_id), GetClangQualifiedName(name).c_str(),
-      mangled_name.str().c_str(), type_sp, scope, comp_unit.get(), ranges,
-      &decl, location, is_external, artificial, location_is_constant_data,
-      static_member);
+      toOpaqueUid(var_id), var_name.c_str(), mangled_name.str().c_str(),
+      type_sp, scope, comp_unit.get(), ranges, &decl, location, is_external,
+      artificial, location_is_constant_data, static_member);
 
   return var_sp;
 }
@@ -1198,12 +1181,22 @@ SymbolFileNativePDB::CreateConstantSymbol(PdbGlobalSymId var_id,
   }
   DWARFExpressionList location(module, std::move(*location_or_err), nullptr);
 
+  std::string var_name = constant.Name.str();
+  auto ts_or_err = GetTypeSystemForLanguage(lldb::eLanguageTypeC_plus_plus);
+  if (auto err = ts_or_err.takeError()) {
+    LLDB_LOG_ERROR(GetLog(LLDBLog::Symbols), std::move(err),
+                   "Failed to get type system for {1}: {0}", constant.Name);
+  } else if (auto ts = *ts_or_err) {
+    if (PdbAstBuilder *ast_builder = ts->GetNativePDBParser())
+      var_name = ast_builder->GetQualifiedName(constant.Name);
+  }
+
   bool external = false;
   bool artificial = false;
   bool location_is_constant_data = true;
   bool static_member = false;
   VariableSP var_sp = std::make_shared<Variable>(
-      toOpaqueUid(var_id), GetClangQualifiedName(constant.Name).c_str(),
+      toOpaqueUid(var_id), var_name.c_str(),
       /*mangled=*/nullptr, type_sp, eValueTypeVariableGlobal, module.get(),
       ranges, &decl, location, external, artificial, location_is_constant_data,
       static_member);



More information about the lldb-commits mailing list