[Lldb-commits] [lldb] [lldb] Limit DIL globals to only current file (PR #192592)

Dave Lee via lldb-commits lldb-commits at lists.llvm.org
Thu Apr 16 21:48:34 PDT 2026


https://github.com/kastiglione created https://github.com/llvm/llvm-project/pull/192592

DIL has supported unlimited global lookup, which is in contrast with legacy
`frame variable` behavior, which supports only globals in the current file.

This is semantically incorrect for `frame variable`, and has shown to produce
bugs in `dwim-print`. For these reasons, this change proposes limiting DIL
globals to only globals from the current compilation unit.

For `dwim-print`, the bug manifests as when a global shadows a computed
property of the instance variable (`self`). As an example, if a global named
`text` exists, and a property named `text` exists (ie `self.text`), then
running `dwim-print text` will unexpectedly print the global, not `self.text`.

Assisted-by: claude


>From 3c5f71d6c496dfb48b15067a314f6ba2f0817c9f Mon Sep 17 00:00:00 2001
From: Dave Lee <davelee.com at gmail.com>
Date: Thu, 16 Apr 2026 21:39:51 -0700
Subject: [PATCH] [lldb] Limit DIL globals to only current file

DIL has supported unlimited global lookup, which is in contrast with legacy
`frame variable` behavior, which supports only globals in the current file.

This is semantically incorrect for `frame variable`, and has shown to produce
bugs in `dwim-print`. For these reasons, this change proposes limiting DIL
globals to only globals from the current compilation unit.

For `dwim-print`, the bug manifests as when a global shadows a computed
property of the instance variable (`self`). As an example, if a global named
`text` exists, and a property named `text` exists (ie `self.text`), then
running `dwim-print text` will unexpectedly print the global, not `self.text`.

Assisted-by: claude
---
 lldb/include/lldb/ValueObject/DILEval.h       |  7 +++---
 lldb/source/ValueObject/DILEval.cpp           | 25 +++----------------
 lldb/source/ValueObject/DILParser.cpp         |  3 +--
 .../TestFrameVarDILGlobalVariableLookup.py    | 23 ++++++++++++-----
 4 files changed, 24 insertions(+), 34 deletions(-)

diff --git a/lldb/include/lldb/ValueObject/DILEval.h b/lldb/include/lldb/ValueObject/DILEval.h
index c5f41b5a0bc76..ec495b4ea9061 100644
--- a/lldb/include/lldb/ValueObject/DILEval.h
+++ b/lldb/include/lldb/ValueObject/DILEval.h
@@ -28,12 +28,11 @@ lldb::ValueObjectSP LookupIdentifier(llvm::StringRef name_ref,
                                      lldb::DynamicValueType use_dynamic);
 
 /// Given the name of an identifier, check to see if it matches the name of a
-/// global variable. If so, find the ValueObject for that global variable, and
-/// create and return an IdentifierInfo object containing all the relevant
-/// informatin about it.
+/// global variable in the current compile unit. If so, find the ValueObject for
+/// that global variable, and create and return an IdentifierInfo object
+/// containing all the relevant information about it.
 lldb::ValueObjectSP LookupGlobalIdentifier(llvm::StringRef name_ref,
                                            std::shared_ptr<StackFrame> frame_sp,
-                                           lldb::TargetSP target_sp,
                                            lldb::DynamicValueType use_dynamic);
 
 class Interpreter : Visitor {
diff --git a/lldb/source/ValueObject/DILEval.cpp b/lldb/source/ValueObject/DILEval.cpp
index 7801b9225f19e..228524b00256d 100644
--- a/lldb/source/ValueObject/DILEval.cpp
+++ b/lldb/source/ValueObject/DILEval.cpp
@@ -16,7 +16,6 @@
 #include "lldb/ValueObject/DILParser.h"
 #include "lldb/ValueObject/ValueObject.h"
 #include "lldb/ValueObject/ValueObjectRegister.h"
-#include "lldb/ValueObject/ValueObjectVariable.h"
 #include "llvm/Support/FormatAdapters.h"
 #include <memory>
 
@@ -293,7 +292,7 @@ static lldb::VariableSP DILFindVariable(ConstString name,
 
 lldb::ValueObjectSP LookupGlobalIdentifier(
     llvm::StringRef name_ref, std::shared_ptr<StackFrame> stack_frame,
-    lldb::TargetSP target_sp, lldb::DynamicValueType use_dynamic) {
+    lldb::DynamicValueType use_dynamic) {
   // Get a global variables list without the locals from the current frame
   SymbolContext symbol_context =
       stack_frame->GetSymbolContext(lldb::eSymbolContextCompUnit);
@@ -311,25 +310,7 @@ lldb::ValueObjectSP LookupGlobalIdentifier(
           stack_frame->GetValueObjectForFrameVariable(var_sp, use_dynamic);
   }
 
-  if (value_sp)
-    return value_sp;
-
-  // Check for match in modules global variables.
-  VariableList modules_var_list;
-  target_sp->GetImages().FindGlobalVariables(
-      ConstString(name_ref), std::numeric_limits<uint32_t>::max(),
-      modules_var_list);
-
-  if (!modules_var_list.Empty()) {
-    lldb::VariableSP var_sp =
-        DILFindVariable(ConstString(name_ref), modules_var_list);
-    if (var_sp)
-      value_sp = ValueObjectVariable::Create(stack_frame.get(), var_sp);
-
-    if (value_sp)
-      return value_sp;
-  }
-  return nullptr;
+  return value_sp;
 }
 
 lldb::ValueObjectSP LookupIdentifier(llvm::StringRef name_ref,
@@ -438,7 +419,7 @@ Interpreter::Visit(const IdentifierNode &node) {
 
   if (!identifier)
     identifier = LookupGlobalIdentifier(node.GetName(), m_exe_ctx_scope,
-                                        m_target, use_dynamic);
+                                        use_dynamic);
   if (!identifier) {
     std::string errMsg =
         llvm::formatv("use of undeclared identifier '{0}'", node.GetName());
diff --git a/lldb/source/ValueObject/DILParser.cpp b/lldb/source/ValueObject/DILParser.cpp
index 51bdffd5087ca..9fb7206429555 100644
--- a/lldb/source/ValueObject/DILParser.cpp
+++ b/lldb/source/ValueObject/DILParser.cpp
@@ -479,8 +479,7 @@ std::optional<CompilerType> DILParser::ParseTypeId() {
       return {};
 
     // Same-name identifiers should be preferred over typenames.
-    if (LookupGlobalIdentifier(type_name, m_ctx_scope,
-                               m_ctx_scope->CalculateTarget(), m_use_dynamic))
+    if (LookupGlobalIdentifier(type_name, m_ctx_scope, m_use_dynamic))
       // TODO: Make type accessible with 'class', 'struct' and 'union' keywords
       return {};
   }
diff --git a/lldb/test/API/commands/frame/var-dil/basics/GlobalVariableLookup/TestFrameVarDILGlobalVariableLookup.py b/lldb/test/API/commands/frame/var-dil/basics/GlobalVariableLookup/TestFrameVarDILGlobalVariableLookup.py
index 5c91755ed0db6..0a59e565d976f 100644
--- a/lldb/test/API/commands/frame/var-dil/basics/GlobalVariableLookup/TestFrameVarDILGlobalVariableLookup.py
+++ b/lldb/test/API/commands/frame/var-dil/basics/GlobalVariableLookup/TestFrameVarDILGlobalVariableLookup.py
@@ -49,12 +49,23 @@ def test_frame_var(self):
         self.expect_var_path("::ns::globalPtr", type="int *")
         self.expect_var_path("::ns::globalRef", type="int &")
 
-        self.expect_var_path("externGlobalVar", value="2")
-        self.expect_var_path("::externGlobalVar", value="2")
-        self.expect_var_path("ext::externGlobalVar", value="4")
-        self.expect_var_path("::ext::externGlobalVar", value="4")
-
-        self.expect_var_path("ExtStruct::static_inline", value="16")
+        # Globals from other compile units are not accessible (matching legacy
+        # frame var behavior).
+        self.expect(
+            "frame var externGlobalVar",
+            error=True,
+            substrs=["use of undeclared identifier"],
+        )
+        self.expect(
+            "frame var ext::externGlobalVar",
+            error=True,
+            substrs=["use of undeclared identifier"],
+        )
+        self.expect(
+            "frame var ExtStruct::static_inline",
+            error=True,
+            substrs=["use of undeclared identifier"],
+        )
 
         # Test local variable priority over global
         self.expect_var_path("foo", value="1")



More information about the lldb-commits mailing list