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
