Author: Matej Košík
Date: 2026-01-09T14:53:56-06:00
New Revision: 42368f919463de02311f7d15191b330f6b8ac2f2

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

LOG: [lldb] fix a problem in the ValueObject::GetExpressionPath method (#171521)

Consider the following program:
```
int main() {
  int foo[2][3][4];
  int (*bar)[3][4] = foo;
  return 0;
}
```
If we:
- compile this program
- launch an LLDB debugging session
- launch the process and let it stop at the `return 0;` statement
then the following LLDB command:
```
(lldb) script lldb.frame.FindVariable("bar").GetChildAtIndex(0).get_expr_path()
```
will produce the following output:
```
bar->[0]
```
What we were expecting:
- a valid expression in the C programming language
- that would allow us (in the scope of the `main` function) access the
appropriate object.

What we've got is a string that does not represent a valid expression in
the C programming language.

This pull-request proposes a fix to this problem.

---------

Co-authored-by: Matej Košík <[email protected]>

Added: 
    lldb/test/API/python_api/value/get_expr_path/Makefile
    
lldb/test/API/python_api/value/get_expr_path/TestValueAPIGetExpressionPath.py
    lldb/test/API/python_api/value/get_expr_path/main.c

Modified: 
    lldb/source/ValueObject/ValueObject.cpp

Removed: 
    


################################################################################
diff  --git a/lldb/source/ValueObject/ValueObject.cpp 
b/lldb/source/ValueObject/ValueObject.cpp
index aeea32f19ee2c..121054e3e92ed 100644
--- a/lldb/source/ValueObject/ValueObject.cpp
+++ b/lldb/source/ValueObject/ValueObject.cpp
@@ -2138,8 +2138,22 @@ void ValueObject::GetExpressionPath(Stream &s,
 
   ValueObject *parent = GetParent();
 
-  if (parent)
+  if (parent) {
     parent->GetExpressionPath(s, epformat);
+    const CompilerType parentType = parent->GetCompilerType();
+    if (parentType.IsPointerType() &&
+        parentType.GetPointeeType().IsArrayType(nullptr, nullptr, nullptr)) {
+      // When the parent is a pointer to an array, then we have to:
+      // - follow the expression path of the parent with "[0]"
+      //   (that will indicate dereferencing the pointer to the array)
+      // - and then follow that with this ValueObject's name
+      //   (which will be something like "[i]" to indicate
+      //    the i-th element of the array)
+      s.PutCString("[0]");
+      s.PutCString(GetName().GetCString());
+      return;
+    }
+  }
 
   // if we are a deref_of_parent just because we are synthetic array members
   // made up to allow ptr[%d] syntax to work in variable printing, then add our

diff  --git a/lldb/test/API/python_api/value/get_expr_path/Makefile 
b/lldb/test/API/python_api/value/get_expr_path/Makefile
new file mode 100644
index 0000000000000..10495940055b6
--- /dev/null
+++ b/lldb/test/API/python_api/value/get_expr_path/Makefile
@@ -0,0 +1,3 @@
+C_SOURCES := main.c
+
+include Makefile.rules

diff  --git 
a/lldb/test/API/python_api/value/get_expr_path/TestValueAPIGetExpressionPath.py 
b/lldb/test/API/python_api/value/get_expr_path/TestValueAPIGetExpressionPath.py
new file mode 100644
index 0000000000000..96eb0dfa2ebc8
--- /dev/null
+++ 
b/lldb/test/API/python_api/value/get_expr_path/TestValueAPIGetExpressionPath.py
@@ -0,0 +1,51 @@
+import lldb
+from lldbsuite.test.lldbtest import *
+from lldbsuite.test import lldbutil
+
+
+class ValueAPIGetExpressionPath(TestBase):
+    def test(self):
+        self.build()
+
+        _, _, thread, _ = lldbutil.run_to_source_breakpoint(
+            self, "Break at this line", lldb.SBFileSpec("main.c")
+        )
+        frame = thread.GetFrameAtIndex(0)
+
+        self.assertEqual(frame.FindVariable("foo").get_expr_path(), "foo")
+        for i in range(2):
+            self.assertEqual(
+                frame.FindVariable("foo").GetChildAtIndex(i).get_expr_path(),
+                f"foo[{i}]",
+            )
+            for j in range(3):
+                self.assertEqual(
+                    frame.FindVariable("foo")
+                    .GetChildAtIndex(i)
+                    .GetChildAtIndex(j)
+                    .get_expr_path(),
+                    f"foo[{i}][{j}]",
+                )
+                for k in range(4):
+                    self.assertEqual(
+                        frame.FindVariable("foo")
+                        .GetChildAtIndex(i)
+                        .GetChildAtIndex(j)
+                        .GetChildAtIndex(k)
+                        .get_expr_path(),
+                        f"foo[{i}][{j}][{k}]",
+                    )
+        self.assertEqual(frame.FindVariable("bar").get_expr_path(), "bar")
+        for j in range(3):
+            self.assertEqual(
+                frame.FindVariable("bar").GetChildAtIndex(j).get_expr_path(),
+                f"bar[0][{j}]",
+            )
+            for k in range(4):
+                self.assertEqual(
+                    frame.FindVariable("bar")
+                    .GetChildAtIndex(j)
+                    .GetChildAtIndex(k)
+                    .get_expr_path(),
+                    f"bar[0][{j}][{k}]",
+                )

diff  --git a/lldb/test/API/python_api/value/get_expr_path/main.c 
b/lldb/test/API/python_api/value/get_expr_path/main.c
new file mode 100644
index 0000000000000..f6fcb11e36835
--- /dev/null
+++ b/lldb/test/API/python_api/value/get_expr_path/main.c
@@ -0,0 +1,5 @@
+int main() {
+  int foo[2][3][4];
+  int (*bar)[3][4] = foo;
+  return 0; // Break at this line
+}


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

Reply via email to