-
Notifications
You must be signed in to change notification settings - Fork 12.3k
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
Fix pointer to reference type #113596
Fix pointer to reference type #113596
Conversation
@llvm/pr-subscribers-lldb Author: None (jeffreytan81) ChangesWe have got customer reporting "v &obj" and "p &obj" reporting different results. This PR fixes this issue by returning the address of the dereferenced object if it is reference type. A new test is added which fails before. Full diff: https://github.com/llvm/llvm-project/pull/113596.diff 3 Files Affected:
diff --git a/lldb/source/Core/ValueObject.cpp b/lldb/source/Core/ValueObject.cpp
index 5b1c171c01f2db..df0393213343fa 100644
--- a/lldb/source/Core/ValueObject.cpp
+++ b/lldb/source/Core/ValueObject.cpp
@@ -2911,6 +2911,16 @@ ValueObjectSP ValueObject::AddressOf(Status &error) {
AddressType address_type = eAddressTypeInvalid;
const bool scalar_is_load_address = false;
+
+ // For reference type we need to get the address of the object that
+ // it refers to.
+ ValueObjectSP deref_obj;
+ if (GetCompilerType().IsReferenceType()) {
+ deref_obj = Dereference(error);
+ if (error.Fail() || !deref_obj)
+ return ValueObjectSP();
+ return deref_obj->AddressOf(error);
+ }
addr_t addr = GetAddressOf(scalar_is_load_address, &address_type);
error.Clear();
if (addr != LLDB_INVALID_ADDRESS && address_type != eAddressTypeHost) {
diff --git a/lldb/test/API/lang/cpp/dereferencing_references/TestCPPDereferencingReferences.py b/lldb/test/API/lang/cpp/dereferencing_references/TestCPPDereferencingReferences.py
index 938fb1a6edf32c..1374d4e1ec67ab 100644
--- a/lldb/test/API/lang/cpp/dereferencing_references/TestCPPDereferencingReferences.py
+++ b/lldb/test/API/lang/cpp/dereferencing_references/TestCPPDereferencingReferences.py
@@ -25,3 +25,24 @@ def test(self):
# Typedef to a reference should dereference to the underlying type.
td_val = self.expect_var_path("td_to_ref_type", type="td_int_ref")
self.assertEqual(td_val.Dereference().GetType().GetName(), "int")
+
+ def test_take_address_of_reference(self):
+ """Tests taking address of lvalue/rvalue references in lldb works correctly."""
+ self.build()
+ lldbutil.run_to_source_breakpoint(
+ self, "// break here", lldb.SBFileSpec("main.cpp")
+ )
+
+ plref_val_from_code = self.expect_var_path("pl_ref", type="TTT *")
+ plref_val_from_expr_path = self.expect_var_path("&l_ref", type="TTT *")
+ self.assertEqual(
+ plref_val_from_code.GetValueAsAddress(),
+ plref_val_from_expr_path.GetValueAsAddress(),
+ )
+
+ prref_val_from_code = self.expect_var_path("pr_ref", type="TTT *")
+ prref_val_from_expr_path = self.expect_var_path("&r_ref", type="TTT *")
+ self.assertEqual(
+ prref_val_from_code.GetValueAsAddress(),
+ prref_val_from_expr_path.GetValueAsAddress(),
+ )
diff --git a/lldb/test/API/lang/cpp/dereferencing_references/main.cpp b/lldb/test/API/lang/cpp/dereferencing_references/main.cpp
index b64978a9029f81..4ddffd167ddeed 100644
--- a/lldb/test/API/lang/cpp/dereferencing_references/main.cpp
+++ b/lldb/test/API/lang/cpp/dereferencing_references/main.cpp
@@ -9,5 +9,7 @@ int main() {
// typedef of a reference
td_int_ref td_to_ref_type = i;
+ TTT *pl_ref = &l_ref;
+ TTT *pr_ref = &r_ref;
return l_ref; // break here
}
|
5e84fcf
to
65b0349
Compare
Let's back up a bit. Before this patch, both the ValueObject class and the "frame var" command treated references essentially as pointers (in the example,
Now, you may or may not agree with that behavior, but at least its consistent: notice how "dereferencing" After this patch, we get this:
I.e. taking the "address of" the reference gives you the same thing as its "value", "dereferencing" the reference still gives you the object that is being referenced (it does not dereference the pointer behind it like you would expect according to the c++ rules), and there's no way to determine the location of the reference. So, either this patch is incorrect (if you believe that the current behavior was intentional) or incomplete (if you believe that we should follow the c++ rules). Either way, I believe we should revert this and discuss the problem in more detail. FWIW, I agree with what you're trying to achieve (making "frame var" follow c++ rules for references). I just think this needs to be handled more wholistically. And I'm not entirely sure that the fix belongs in the ValueObject class.(*) I also believe there should be a way to get the "location" of the reference (but that doesn't have to be exposed through "frame var") (*) I'm not saying it does not belong there either, but I think you could make a stronger case for treating references like "fancy pointers" in the ValueObject class -- i.e. maintaining the status quo there. |
I haven't had time to look into your example in details. But to share high level context about the bug behavior, we have observed cases that, there is real world scenarios using |
I can believe that this behavior is undesirable. Like I said, I totally understand why you did this. It's the how I have a problem with. I don't believe the we've sufficiently considered the bigger picture. Why does If you think about it even the implementation of the patch is a bit strange -- this is the first "address of" operation that's implemented in terms of "dereferencing" (and if we changed "dereference" to be transparent, this implementation would break). Please don't take this personally. I can certainly see how you could have though you're making an obvious bugfix here. But, in light of what I've just said, I think this needs more discussion (and I think this ought to be reverted until that is done). @jimingham, as the own^Wmaintainter of the ValueObject library, what do you think? |
Regarding the vector summary example, it looks like that there's still a lot of room for improvement there. This is what I get before this patch:
And this comes after it:
The output for |
First off, it is not the case that the "ValueObject Path Expression" operators - part of what we're starting to call the DIL (Data Inspection Language) - are supposed to exactly mirror C++ semantics. Since they reflect all the ways that a synthetic child provider might present its children, and since this part of lldb is independent of language - it gets used for C/ObjC/C++/Swift/Rust etc values, not just C++ - I don't think this would be a feasible or particularly useful requirement. So "be the same as C++ semantics" is not a sufficient justification to change how the path expressions get interpreted in lldb. The better motivation is "what is a useful and consistent syntax for static poking at data objects". The question "where does this reference live" isn't a particularly useful question to ask in C++ code, but it does seem like a useful question to ask when poking around in data. And since we're generally treating I agree with Pavel, we should take a step back and actually define what |
Technical these make sense. Please let me know how to revert a PR (or feel free to revert for me if I do not have permission). |
FWIW, codelldb also dereferences pointers and references when displaying values. They provide a user-facing setting for it and implement it in the debug adapter, instead of at the core of LLDB |
We have got customer reporting "v &obj" and "p &obj" reporting different results. Turns out it only happens for obj that is itself a reference type which "v &obj" reports the address of the reference itself instead of the target object the reference points to. This diverged from C++ semantics. This PR fixes this issue by returning the address of the dereferenced object if it is reference type. A new test is added which fails before. Co-authored-by: jeffreytan81 <jeffreytan@fb.com>
This reverts commit 25909b8 due to unresolved questions about the behavior of "frame var" and ValueObject in the presence of references (see the original patch for discussion).
Thanks for your understanding. Here's a revert PR (#114831). I'll submit it after the CI runs. Would you like to create an RFC thread to continue this discussion? |
This reverts commit 25909b8 due to unresolved questions about the behavior of "frame var" and ValueObject in the presence of references (see the original patch for discussion).
We have got customer reporting "v &obj" and "p &obj" reporting different results.
Turns out it only happens for obj that is itself a reference type which "v &obj" reports the address of the reference itself instead of the target object the reference points to. This diverged from C++ semantics.
This PR fixes this issue by returning the address of the dereferenced object if it is reference type.
A new test is added which fails before.