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

via lldb-commits lldb-commits at lists.llvm.org
Mon Oct 19 07:50:40 PDT 2026


Author: Charles Zablit
Date: 2026-10-19T16:50:34+02:00
New Revision: fab2b6ae29cbf1ad6cb73bf0b03c51ebdbe1f3d8

URL: https://github.com/llvm/llvm-project/commit/fab2b6ae29cbf1ad6cb73bf0b03c51ebdbe1f3d8
DIFF: https://github.com/llvm/llvm-project/commit/fab2b6ae29cbf1ad6cb73bf0b03c51ebdbe1f3d8.diff

LOG: [lldb][NativePDB] Name global variables like Clang and DWARF do (#230563)

CodeView spells anonymous namespaces `'anonymous namespace'`, and
`CreateGlobalVariable` and `CreateConstantSymbol` use the CodeView name
as is, while the Clang AST, type names and `SymbolFileDWARF` all say
`(anonymous namespace)`. A qualified lookup like
`FindFirstGlobalVariable("abc::(anonymous
namespace)::g_anon_namespace_const_int")` finds nothing.

This patch replaces the CodeView spelling in the names of global
variables and constants, and stops giving `S_CONSTANT` the `"::" + name`
mangled name (they have no public symbol).

Fixes `TestCPPGlobalVariables` with PDB debug info.

rdar://190423349

Added: 
    

Modified: 
    lldb/source/Plugins/SymbolFile/NativePDB/PdbAstBuilder.h
    lldb/source/Plugins/SymbolFile/NativePDB/PdbAstBuilderClang.cpp
    lldb/source/Plugins/SymbolFile/NativePDB/PdbAstBuilderClang.h
    lldb/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.cpp
    lldb/test/API/lang/cpp/global_variables/TestCPPGlobalVariables.py

Removed: 
    


################################################################################
diff  --git a/lldb/source/Plugins/SymbolFile/NativePDB/PdbAstBuilder.h b/lldb/source/Plugins/SymbolFile/NativePDB/PdbAstBuilder.h
index 8356ead491890..ae80018ac350b 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 66a3990a54f63..1599ddcf42caf 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 4eae85b37522e..71f8074d9150b 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 9ed1d327851fb..400de172baa37 100644
--- a/lldb/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.cpp
+++ b/lldb/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.cpp
@@ -1125,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);
@@ -1139,7 +1142,7 @@ 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(),
+      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);
 
@@ -1161,8 +1164,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));
@@ -1180,14 +1181,25 @@ 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), 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), var_name.c_str(),
+      /*mangled=*/nullptr, type_sp, eValueTypeVariableGlobal, module.get(),
+      ranges, &decl, location, external, artificial, location_is_constant_data,
+      static_member);
   return var_sp;
 }
 
@@ -2224,11 +2236,16 @@ void SymbolFileNativePDB::FindGlobalVariables(
 
   CacheGlobalBaseNames();
 
+  // A leading "::" requests a variable from the global namespace.
+  llvm::StringRef lookup_name = name.GetStringRef();
+  bool is_rooted = lookup_name.consume_front("::");
+
   llvm::StringRef context;
   llvm::StringRef basename;
-  if (!CPlusPlusLanguage::ExtractContextAndIdentifier(name.GetStringRef(),
-                                                      context, basename))
-    basename = name.GetStringRef();
+  if (!CPlusPlusLanguage::ExtractContextAndIdentifier(lookup_name, context,
+                                                      basename))
+    basename = lookup_name;
+  std::string scoped_suffix = ("::" + lookup_name).str();
 
   std::vector<uint32_t> results;
   m_global_variable_base_names.GetValues(ConstString(basename), results);
@@ -2244,9 +2261,12 @@ void SymbolFileNativePDB::FindGlobalVariables(
     VariableSP var = GetOrCreateGlobalVariable(global);
     if (!var)
       continue;
-    if (!context.empty() &&
-        !var->GetName().GetStringRef().contains(name.GetStringRef()))
-      continue;
+    if (is_rooted || !context.empty()) {
+      llvm::StringRef var_name = var->GetName().GetStringRef();
+      if (var_name != lookup_name &&
+          (is_rooted || !var_name.ends_with(scoped_suffix)))
+        continue;
+    }
     variables.AddVariable(var);
 
     if (++n_matches >= max_matches)

diff  --git a/lldb/test/API/lang/cpp/global_variables/TestCPPGlobalVariables.py b/lldb/test/API/lang/cpp/global_variables/TestCPPGlobalVariables.py
index d9189651bd42a..9d964634adbbd 100644
--- a/lldb/test/API/lang/cpp/global_variables/TestCPPGlobalVariables.py
+++ b/lldb/test/API/lang/cpp/global_variables/TestCPPGlobalVariables.py
@@ -11,7 +11,6 @@ def setUp(self):
         TestBase.setUp(self)
         self.source = lldb.SBFileSpec("main.cpp")
 
-    @expectedFailureAll(debug_info=["pdb"], bugnumber="llvm.org/pr149498")
     def test(self):
         self.build()
 


        


More information about the lldb-commits mailing list