[Lldb-commits] [lldb] [lldb] Avoid returning a stale AddressOf (PR #212915)

Igor Kudrin via lldb-commits lldb-commits at lists.llvm.org
Fri Jul 31 00:26:53 PDT 2026


https://github.com/igorkudrin updated https://github.com/llvm/llvm-project/pull/212915

>From 4297ccab6b50e388549cc0556fb50dc7cae4c0e4 Mon Sep 17 00:00:00 2001
From: Igor Kudrin <ikudrin at accesssoftek.com>
Date: Mon, 27 Jul 2026 15:31:52 -0700
Subject: [PATCH 1/4] [lldb] Avoid returning a stale AddressOf

The 'ValueObject::AddressOf()' method assumes that the address of a
value object cannot change, so when it is calculated once, it does not
need to be updated afterwards. However, this is not the case if the
'ValueObject' is a dependent object obtained by calling 'Dereference()'
of another 'ValueObject'. If the latter object is changed, the dependent
value object should return a new address from the 'AddressOf()' method
to reflect the change.
---
 lldb/source/ValueObject/ValueObject.cpp       |  7 +++---
 .../API/python_api/value/change_ptr/Makefile  |  3 +++
 .../value/change_ptr/TestChangePtr.py         | 22 +++++++++++++++++++
 .../API/python_api/value/change_ptr/main.c    |  7 ++++++
 4 files changed, 36 insertions(+), 3 deletions(-)
 create mode 100644 lldb/test/API/python_api/value/change_ptr/Makefile
 create mode 100644 lldb/test/API/python_api/value/change_ptr/TestChangePtr.py
 create mode 100644 lldb/test/API/python_api/value/change_ptr/main.c

diff --git a/lldb/source/ValueObject/ValueObject.cpp b/lldb/source/ValueObject/ValueObject.cpp
index e2bfa02500f2c..b36a020d262c4 100644
--- a/lldb/source/ValueObject/ValueObject.cpp
+++ b/lldb/source/ValueObject/ValueObject.cpp
@@ -2913,9 +2913,6 @@ ValueObjectSP ValueObject::Dereference(Status &error) {
 }
 
 ValueObjectSP ValueObject::AddressOf(Status &error) {
-  if (m_addr_of_valobj_sp)
-    return m_addr_of_valobj_sp;
-
   auto [addr, address_type] = GetAddressOf(/*scalar_is_load_address=*/false);
   error.Clear();
   if (addr != LLDB_INVALID_ADDRESS && address_type != eAddressTypeHost) {
@@ -2929,6 +2926,10 @@ ValueObjectSP ValueObject::AddressOf(Status &error) {
 
     case eAddressTypeFile:
     case eAddressTypeLoad: {
+      if (m_addr_of_valobj_sp &&
+          m_addr_of_valobj_sp->GetValueAsUnsigned(LLDB_INVALID_ADDRESS) == addr)
+        return m_addr_of_valobj_sp;
+      m_addr_of_valobj_sp.reset();
       CompilerType compiler_type = GetCompilerType();
       if (compiler_type) {
         std::string name(1, '&');
diff --git a/lldb/test/API/python_api/value/change_ptr/Makefile b/lldb/test/API/python_api/value/change_ptr/Makefile
new file mode 100644
index 0000000000000..10495940055b6
--- /dev/null
+++ b/lldb/test/API/python_api/value/change_ptr/Makefile
@@ -0,0 +1,3 @@
+C_SOURCES := main.c
+
+include Makefile.rules
diff --git a/lldb/test/API/python_api/value/change_ptr/TestChangePtr.py b/lldb/test/API/python_api/value/change_ptr/TestChangePtr.py
new file mode 100644
index 0000000000000..378332568e097
--- /dev/null
+++ b/lldb/test/API/python_api/value/change_ptr/TestChangePtr.py
@@ -0,0 +1,22 @@
+import lldb
+from lldbsuite.test.decorators import *
+from lldbsuite.test.lldbtest import *
+from lldbsuite.test import lldbutil
+
+
+class ChangePtrTest(TestBase):
+
+    def test(self):
+        self.build()
+
+        _, _, thread, _ = lldbutil.run_to_source_breakpoint(
+            self, "// break here", lldb.SBFileSpec("main.c")
+        )
+        frame = thread.GetFrameAtIndex(0)
+        p = frame.FindVariable("p")
+        deref = p.Dereference()
+        self.assertEqual(deref.GetValueAsUnsigned(), 5)
+        self.assertEqual(deref.AddressOf().GetValueAsUnsigned(), p.GetValueAsUnsigned())
+        thread.StepOver()
+        self.assertEqual(deref.GetValueAsUnsigned(), 7)
+        self.assertEqual(deref.AddressOf().GetValueAsUnsigned(), p.GetValueAsUnsigned())
diff --git a/lldb/test/API/python_api/value/change_ptr/main.c b/lldb/test/API/python_api/value/change_ptr/main.c
new file mode 100644
index 0000000000000..15f223ae2577a
--- /dev/null
+++ b/lldb/test/API/python_api/value/change_ptr/main.c
@@ -0,0 +1,7 @@
+int main() {
+  int a = 5;
+  int b = 7;
+  int *p = &a;
+  p = &b; // break here
+  return 0;
+}

>From 7b30f8055baeff02907814db4f61e74f9535d128 Mon Sep 17 00:00:00 2001
From: Igor Kudrin <ikudrin at accesssoftek.com>
Date: Wed, 29 Jul 2026 19:09:20 -0700
Subject: [PATCH 2/4] fixup! formatting

---
 lldb/test/API/python_api/value/change_ptr/TestChangePtr.py | 1 -
 1 file changed, 1 deletion(-)

diff --git a/lldb/test/API/python_api/value/change_ptr/TestChangePtr.py b/lldb/test/API/python_api/value/change_ptr/TestChangePtr.py
index 378332568e097..ae9cf309ab0dd 100644
--- a/lldb/test/API/python_api/value/change_ptr/TestChangePtr.py
+++ b/lldb/test/API/python_api/value/change_ptr/TestChangePtr.py
@@ -5,7 +5,6 @@
 
 
 class ChangePtrTest(TestBase):
-
     def test(self):
         self.build()
 

>From 7bd061ca17554bba3fdda45e5ab38885ff5c70bf Mon Sep 17 00:00:00 2001
From: Igor Kudrin <ikudrin at accesssoftek.com>
Date: Fri, 31 Jul 2026 00:20:33 -0700
Subject: [PATCH 3/4] fixup! Add more tests

---
 .../value/change_ptr/TestChangePtr.py         | 48 ++++++++++++++++++-
 .../API/python_api/value/change_ptr/main.c    | 25 +++++++++-
 2 files changed, 69 insertions(+), 4 deletions(-)

diff --git a/lldb/test/API/python_api/value/change_ptr/TestChangePtr.py b/lldb/test/API/python_api/value/change_ptr/TestChangePtr.py
index ae9cf309ab0dd..f68eeb8404d70 100644
--- a/lldb/test/API/python_api/value/change_ptr/TestChangePtr.py
+++ b/lldb/test/API/python_api/value/change_ptr/TestChangePtr.py
@@ -8,9 +8,14 @@ class ChangePtrTest(TestBase):
     def test(self):
         self.build()
 
-        _, _, thread, _ = lldbutil.run_to_source_breakpoint(
-            self, "// break here", lldb.SBFileSpec("main.c")
+        src_file = lldb.SBFileSpec("main.c")
+        _, process, thread, _ = lldbutil.run_to_source_breakpoint(
+            self, "// break here 1", src_file
         )
+
+        ## Test 1: The AddressOf of a dereferenced value should change when
+        ## the pointer value is updated.
+
         frame = thread.GetFrameAtIndex(0)
         p = frame.FindVariable("p")
         deref = p.Dereference()
@@ -19,3 +24,42 @@ def test(self):
         thread.StepOver()
         self.assertEqual(deref.GetValueAsUnsigned(), 7)
         self.assertEqual(deref.AddressOf().GetValueAsUnsigned(), p.GetValueAsUnsigned())
+
+        ## Test 2: The AddressOf of a child value of a dereferenced value should
+        ## change when the base pointer updates.
+
+        lldbutil.continue_to_source_breakpoint(
+            self, process, "// break here 2", src_file
+        )
+        frame = thread.GetFrameAtIndex(0)
+        p = frame.FindVariable("p")
+        deref_child = p.Dereference().GetChildMemberWithName("b")
+        self.assertEqual(deref_child.GetValue(), "'b'")
+        self.assertEqual(
+            deref_child.AddressOf().GetValueAsUnsigned(), p.GetValueAsUnsigned() + 1
+        )
+        thread.StepOver()
+        self.assertEqual(deref_child.GetValue(), "'d'")
+        self.assertEqual(
+            deref_child.AddressOf().GetValueAsUnsigned(), p.GetValueAsUnsigned() + 1
+        )
+
+        ## Test 3: Verify AddressOf updates correctly with persistent expression results.
+        lldbutil.continue_to_source_breakpoint(
+            self, process, "// break here 3", src_file
+        )
+        frame = thread.GetFrameAtIndex(0)
+        frame.EvaluateExpression("int *$ptr = &a")
+        ptr = frame.FindValue("$ptr", lldb.eValueTypeConstResult)
+        deref = ptr.Dereference()
+        self.assertEqual(deref.GetValueAsUnsigned(), 5)
+        self.assertEqual(
+            deref.AddressOf().GetValueAsUnsigned(),
+            frame.FindVariable("a").AddressOf().GetValueAsUnsigned(),
+        )
+        frame.EvaluateExpression("$ptr = &b")
+        self.assertEqual(deref.GetValueAsUnsigned(), 7)
+        self.assertEqual(
+            deref.AddressOf().GetValueAsUnsigned(),
+            frame.FindVariable("b").AddressOf().GetValueAsUnsigned(),
+        )
diff --git a/lldb/test/API/python_api/value/change_ptr/main.c b/lldb/test/API/python_api/value/change_ptr/main.c
index 15f223ae2577a..24062fb6db8d0 100644
--- a/lldb/test/API/python_api/value/change_ptr/main.c
+++ b/lldb/test/API/python_api/value/change_ptr/main.c
@@ -1,7 +1,28 @@
-int main() {
+int test1() {
   int a = 5;
   int b = 7;
   int *p = &a;
-  p = &b; // break here
+  p = &b; // break here 1
+  return *p;
+}
+
+char test2() {
+  struct S {char a; char b; };
+  struct S arr[2] = {{'a', 'b'}, {'c', 'd'}};
+  struct S *p = arr;
+  ++p; // break here 2
+  return p->b;
+}
+
+int test3() {
+  int a = 5;
+  int b = 7;
+  return a + b; // break here 3
+}
+
+int main() {
+  test1();
+  test2();
+  test3();
   return 0;
 }

>From c40dac9aa0ed4260940ee53eab8fa9691eb50675 Mon Sep 17 00:00:00 2001
From: Igor Kudrin <ikudrin at accesssoftek.com>
Date: Fri, 31 Jul 2026 00:26:38 -0700
Subject: [PATCH 4/4] fixup! formatting

---
 lldb/test/API/python_api/value/change_ptr/main.c | 5 ++++-
 1 file changed, 4 insertions(+), 1 deletion(-)

diff --git a/lldb/test/API/python_api/value/change_ptr/main.c b/lldb/test/API/python_api/value/change_ptr/main.c
index 24062fb6db8d0..4cce83e61476c 100644
--- a/lldb/test/API/python_api/value/change_ptr/main.c
+++ b/lldb/test/API/python_api/value/change_ptr/main.c
@@ -7,7 +7,10 @@ int test1() {
 }
 
 char test2() {
-  struct S {char a; char b; };
+  struct S {
+    char a;
+    char b;
+  };
   struct S arr[2] = {{'a', 'b'}, {'c', 'd'}};
   struct S *p = arr;
   ++p; // break here 2



More information about the lldb-commits mailing list