Author: Leonard Grey
Date: 2026-02-12T09:35:00-05:00
New Revision: 4c08780e7c5b7db8ab8c888fe7f97039b44f3c77

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

LOG: [LLDB][NativePDB] Add local constant support (#180612)

This is mostly to support Swift `let`, but I found a way to get MSVC to
emit a local `S_CONSTANT` (see test).

I saw the note about `MakeConstantLocalExpression` at
https://github.com/llvm/llvm-project/blob/2e34fecf02962e4c8477ca88cc5ac9386a0f76bb/lldb/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.cpp#L2177
but couldn't repro with local or global (emitted as `S_LDATA32` in both
cases).

Added: 
    lldb/test/Shell/SymbolFile/NativePDB/local-constant.test

Modified: 
    lldb/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.cpp
    lldb/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.h

Removed: 
    


################################################################################
diff  --git a/lldb/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.cpp 
b/lldb/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.cpp
index 7e39af7d32e2f..bed15839be1cd 100644
--- a/lldb/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.cpp
+++ b/lldb/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.cpp
@@ -2196,32 +2196,54 @@ 
SymbolFileNativePDB::ParseVariablesForCompileUnit(CompileUnit &comp_unit,
 
 VariableSP SymbolFileNativePDB::CreateLocalVariable(PdbCompilandSymId scope_id,
                                                     PdbCompilandSymId var_id,
-                                                    bool is_param) {
+                                                    bool is_param,
+                                                    bool is_constant) {
   ModuleSP module = GetObjectFile()->GetModule();
   Block *block = GetOrCreateBlock(scope_id);
   if (!block)
     return nullptr;
 
-  // Get function block.
-  Block *func_block = block;
-  while (func_block->GetParent()) {
-    func_block = func_block->GetParent();
-  }
-
-  Address addr;
-  func_block->GetStartAddress(addr);
-  VariableInfo var_info =
-      GetVariableLocationInfo(*m_index, var_id, *func_block, module);
-  Function *func = func_block->CalculateSymbolContextFunction();
-  if (!func)
-    return nullptr;
-  // Use empty dwarf expr if optimized away so that it won't be filtered out
-  // when lookuping local variables in this scope.
-  if (!var_info.location.IsValid())
-    var_info.location = DWARFExpressionList(module, DWARFExpression(), 
nullptr);
-  var_info.location.SetFuncFileAddress(func->GetAddress().GetFileAddress());
   CompilandIndexItem *cii = m_index->compilands().GetCompiland(var_id.modi);
+  if (!cii)
+    return nullptr;
   CompUnitSP comp_unit_sp = GetOrCreateCompileUnit(*cii);
+
+  VariableInfo var_info;
+  bool location_is_constant_data = is_constant;
+
+  if (is_constant) {
+    CVSymbol sym = cii->m_debug_stream.readSymbolAtOffset(var_id.offset);
+    assert(sym.kind() == S_CONSTANT);
+    ConstantSym constant(sym.kind());
+    cantFail(SymbolDeserializer::deserializeAs<ConstantSym>(sym, constant));
+
+    var_info.name = constant.Name;
+    var_info.type = constant.Type;
+    var_info.location = DWARFExpressionList(
+        module,
+        MakeConstantLocationExpression(constant.Type, m_index->tpi(),
+                                       constant.Value, module),
+        nullptr);
+  } else {
+    // Get function block.
+    Block *func_block = block;
+    while (func_block->GetParent())
+      func_block = func_block->GetParent();
+
+    Address addr;
+    func_block->GetStartAddress(addr);
+    var_info = GetVariableLocationInfo(*m_index, var_id, *func_block, module);
+    Function *func = func_block->CalculateSymbolContextFunction();
+    if (!func)
+      return nullptr;
+    // Use empty dwarf expr if optimized away so that it won't be filtered out
+    // when lookuping local variables in this scope.
+    if (!var_info.location.IsValid())
+      var_info.location =
+          DWARFExpressionList(module, DWARFExpression(), nullptr);
+    var_info.location.SetFuncFileAddress(func->GetAddress().GetFileAddress());
+  }
+
   TypeSP type_sp = GetOrCreateType(var_info.type);
   if (!type_sp)
     return nullptr;
@@ -2235,7 +2257,6 @@ VariableSP 
SymbolFileNativePDB::CreateLocalVariable(PdbCompilandSymId scope_id,
       is_param ? eValueTypeVariableArgument : eValueTypeVariableLocal;
   bool external = false;
   bool artificial = false;
-  bool location_is_constant_data = false;
   bool static_member = false;
   Variable::RangeList scope_ranges;
   VariableSP var_sp = std::make_shared<Variable>(
@@ -2256,13 +2277,15 @@ VariableSP 
SymbolFileNativePDB::CreateLocalVariable(PdbCompilandSymId scope_id,
   return var_sp;
 }
 
-VariableSP SymbolFileNativePDB::GetOrCreateLocalVariable(
-    PdbCompilandSymId scope_id, PdbCompilandSymId var_id, bool is_param) {
+VariableSP
+SymbolFileNativePDB::GetOrCreateLocalVariable(PdbCompilandSymId scope_id,
+                                              PdbCompilandSymId var_id,
+                                              bool is_param, bool is_constant) 
{
   auto iter = m_local_variables.find(toOpaqueUid(var_id));
   if (iter != m_local_variables.end())
     return iter->second;
 
-  return CreateLocalVariable(scope_id, var_id, is_param);
+  return CreateLocalVariable(scope_id, var_id, is_param, is_constant);
 }
 
 TypeSP SymbolFileNativePDB::CreateTypedef(PdbGlobalSymId id) {
@@ -2390,6 +2413,13 @@ size_t 
SymbolFileNativePDB::ParseVariablesForBlock(PdbCompilandSymId block_id) {
       if (variable)
         variables->AddVariableIfUnique(variable);
       break;
+    case S_CONSTANT:
+      variable = GetOrCreateLocalVariable(block_id, child_sym_id,
+                                          /*is_param=*/false,
+                                          /*is_constant=*/true);
+      if (variable)
+        variables->AddVariableIfUnique(variable);
+      break;
     default:
       break;
     }

diff  --git a/lldb/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.h 
b/lldb/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.h
index 11b982e6fc67e..4d5d9fb58bcac 100644
--- a/lldb/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.h
+++ b/lldb/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.h
@@ -236,14 +236,16 @@ class SymbolFileNativePDB : public SymbolFileCommon {
   Block *GetOrCreateBlock(PdbCompilandSymId block_id);
   lldb::VariableSP GetOrCreateLocalVariable(PdbCompilandSymId scope_id,
                                             PdbCompilandSymId var_id,
-                                            bool is_param);
+                                            bool is_param,
+                                            bool is_constant = false);
   lldb::TypeSP GetOrCreateTypedef(PdbGlobalSymId id);
 
   lldb::FunctionSP CreateFunction(PdbCompilandSymId func_id,
                                   CompileUnit &comp_unit);
   Block *CreateBlock(PdbCompilandSymId block_id);
   lldb::VariableSP CreateLocalVariable(PdbCompilandSymId scope_id,
-                                       PdbCompilandSymId var_id, bool 
is_param);
+                                       PdbCompilandSymId var_id, bool is_param,
+                                       bool is_constant = false);
   lldb::TypeSP CreateTypedef(PdbGlobalSymId id);
   lldb::CompUnitSP CreateCompileUnit(const CompilandIndexItem &cci);
   lldb::TypeSP CreateType(PdbTypeSymId type_id, CompilerType ct);

diff  --git a/lldb/test/Shell/SymbolFile/NativePDB/local-constant.test 
b/lldb/test/Shell/SymbolFile/NativePDB/local-constant.test
new file mode 100644
index 0000000000000..83d376312a295
--- /dev/null
+++ b/lldb/test/Shell/SymbolFile/NativePDB/local-constant.test
@@ -0,0 +1,24 @@
+# REQUIRES: msvc
+
+# Test that we can display local S_CONSTANT records.
+# MSVC emits S_CONSTANT for static const locals; clang-cl does not.
+# RUN: split-file %s %t
+# RUN: %build --compiler=msvc --nodefaultlib -o %t.exe -- %t/main.cpp
+# RUN: %lldb -f %t.exe -s %t/commands.input 2>&1 | FileCheck %s
+
+#--- main.cpp
+
+int main() {
+  static const int kConstant = 42;
+  return kConstant;
+}
+
+#--- commands.input
+
+settings set stop-line-count-after 0
+break set -n main
+run
+frame variable
+quit
+
+# CHECK: (const int) {{.*}}kConstant = 42


        
_______________________________________________
lldb-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits

Reply via email to