[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