-
Notifications
You must be signed in to change notification settings - Fork 15.4k
[lldb] fix a problem in the ValueObject::GetExpressionPath method #171521
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
[lldb] fix a problem in the ValueObject::GetExpressionPath method #171521
Conversation
|
@llvm/pr-subscribers-lldb Author: Matej Košík (sedymrak) ChangesConsider the following program: If we:
will produce the following output: What we were expecting:
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. Full diff: https://github.com/llvm/llvm-project/pull/171521.diff 4 Files Affected:
diff --git a/lldb/source/ValueObject/ValueObject.cpp b/lldb/source/ValueObject/ValueObject.cpp
index aeea32f19ee2c..3bbb917e51976 100644
--- a/lldb/source/ValueObject/ValueObject.cpp
+++ b/lldb/source/ValueObject/ValueObject.cpp
@@ -2138,6 +2138,20 @@ void ValueObject::GetExpressionPath(Stream &s,
ValueObject *parent = GetParent();
+ if (parent) {
+ lldb_private::CompilerType parentType = parent->GetCompilerType();
+ const bool parentTypeIsPointer = parentType.IsPointerType();
+ const bool pointeeOfParentTypeIsArray =
+ parentType.GetPointeeType().IsArrayType(nullptr, nullptr, nullptr);
+ if (parentTypeIsPointer && pointeeOfParentTypeIsArray) {
+ s.PutCString("(*");
+ parent->GetExpressionPath(s, epformat);
+ s.PutCString(")");
+ s.PutCString(GetName().GetCString());
+ return;
+ }
+ }
+
if (parent)
parent->GetExpressionPath(s, epformat);
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..227588c412587
--- /dev/null
+++ b/lldb/test/API/python_api/value/get_expr_path/TestValueAPIGetExpressionPath.py
@@ -0,0 +1,50 @@
+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)[{j}]"
+ )
+ for k in range(4):
+ self.assertEqual(
+ frame.FindVariable("bar")
+ .GetChildAtIndex(j)
+ .GetChildAtIndex(k)
+ .get_expr_path(),
+ f"(*bar)[{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
+}
|
|
✅ With the latest revision this PR passed the Python code formatter. |
|
This is more a meta-point, but get_expression_path's job is not to produce a "valid expression in the C programming language". It produces a valid expression in lldb's DIL (Data Inspection Language). That is the C-like lldb invention for inspecting data as produced by the ValueObject system (including the naming that Synthetic Child Providers allow) - which often isn't exactly what the language implementing the type would use. The difference is that these expressions are expected to round-trip through "ValueObject::GetValueForExpressionPath". They are NOT guaranteed to round-trip through EvaluateExpression. This is only a side-comment, however, because bar->[0] is not a valid expression in the DIL either: |
|
But it is germane to the solution, however. Since the expression path in this case is just "[0][0]": whereas: |
…ided for my pull-request
|
@jimingham Thank you for your help. I have pushed a commit that tries to address the feedback you have given me so far. Hopefully, I haven't misunderstood you. I was not aware of the DIL concept. |
jimingham
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Might be worth putting a comment in the code you added to GetExpressionPath, saying that it is avoiding adding a spurious -> as an aid to people reading this code in the future.
Otherwise, LGTM.
Consider the following program:
If we:
return 0;statementthen the following LLDB command:
will produce the following output:
What we were expecting:
mainfunction) 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.