forked from OSchip/llvm-project
Do not dereference std::unique_ptr by default
Summary: Displaying the object pointed by the unique_ptr can cause an infinite recursion when we have a pointer loop so this change stops that behavior. Additionally it makes the unique_ptr act more like a class containing a pointer (what is the underlying truth) instead of some "magic" class. Reviewers: labath, jingham Differential Revision: https://reviews.llvm.org/D31366 llvm-svn: 299249
This commit is contained in:
parent
885fa12e8a
commit
af8953a025
|
@ -34,13 +34,13 @@ class StdUniquePtrDataFormatterTestCase(TestBase):
|
|||
self.assertTrue(frame.IsValid())
|
||||
|
||||
self.expect("frame variable nup", substrs=['nup = nullptr'])
|
||||
self.expect("frame variable iup", substrs=['iup = 0x', 'object = 123'])
|
||||
self.expect("frame variable sup", substrs=['sup = 0x', 'object = "foobar"'])
|
||||
self.expect("frame variable iup", substrs=['iup = 0x'])
|
||||
self.expect("frame variable sup", substrs=['sup = 0x'])
|
||||
|
||||
self.expect("frame variable ndp", substrs=['ndp = nullptr'])
|
||||
self.expect("frame variable idp", substrs=['idp = 0x', 'object = 456', 'deleter = ', 'a = 1', 'b = 2'])
|
||||
self.expect("frame variable sdp", substrs=['sdp = 0x', 'object = "baz"', 'deleter = ', 'a = 3', 'b = 4'])
|
||||
|
||||
self.expect("frame variable idp", substrs=['idp = 0x', 'deleter = ', 'a = 1', 'b = 2'])
|
||||
self.expect("frame variable sdp", substrs=['sdp = 0x', 'deleter = ', 'a = 3', 'b = 4'])
|
||||
|
||||
self.assertEqual(123, frame.GetValueForVariablePath("iup.object").GetValueAsUnsigned())
|
||||
self.assertFalse(frame.GetValueForVariablePath("iup.deleter").IsValid())
|
||||
|
||||
|
@ -59,3 +59,32 @@ class StdUniquePtrDataFormatterTestCase(TestBase):
|
|||
self.assertTrue(sdp_deleter.IsValid())
|
||||
self.assertEqual(3, sdp_deleter.GetChildMemberWithName("a").GetValueAsUnsigned())
|
||||
self.assertEqual(4, sdp_deleter.GetChildMemberWithName("b").GetValueAsUnsigned())
|
||||
|
||||
@skipIfFreeBSD
|
||||
@skipIfWindows # libstdcpp not ported to Windows
|
||||
@skipIfDarwin # doesn't compile on Darwin
|
||||
def test_recursive_unique_ptr(self):
|
||||
# Tests that LLDB can handle when we have a loop in the unique_ptr
|
||||
# reference chain and that it correctly handles the different options
|
||||
# for the frame variable command in this case.
|
||||
self.build()
|
||||
self.runCmd("file a.out", CURRENT_EXECUTABLE_SET)
|
||||
|
||||
lldbutil.run_break_set_by_source_regexp(
|
||||
self, "Set break point at this line.")
|
||||
self.runCmd("run", RUN_SUCCEEDED)
|
||||
self.expect("thread list", STOPPED_DUE_TO_BREAKPOINT,
|
||||
substrs=['stopped', 'stop reason = breakpoint'])
|
||||
|
||||
self.expect("frame variable f1->fp",
|
||||
substrs=['fp = 0x'])
|
||||
self.expect("frame variable --ptr-depth=1 f1->fp",
|
||||
substrs=['data = 2', 'fp = 0x'])
|
||||
self.expect("frame variable --ptr-depth=2 f1->fp",
|
||||
substrs=['data = 2', 'fp = 0x', 'data = 1'])
|
||||
|
||||
frame = self.frame()
|
||||
self.assertTrue(frame.IsValid())
|
||||
self.assertEqual(2, frame.GetValueForVariablePath("f1->fp.object.data").GetValueAsUnsigned())
|
||||
self.assertEqual(1, frame.GetValueForVariablePath("f1->fp.object.fp.object.data").GetValueAsUnsigned())
|
||||
|
||||
|
|
|
@ -8,6 +8,11 @@ struct Deleter {
|
|||
int b;
|
||||
};
|
||||
|
||||
struct Foo {
|
||||
int data;
|
||||
std::unique_ptr<Foo> fp;
|
||||
};
|
||||
|
||||
int main() {
|
||||
std::unique_ptr<char> nup;
|
||||
std::unique_ptr<int> iup(new int{123});
|
||||
|
@ -18,5 +23,13 @@ int main() {
|
|||
std::unique_ptr<std::string, Deleter> sdp(new std::string("baz"),
|
||||
Deleter{3, 4});
|
||||
|
||||
std::unique_ptr<Foo> fp(new Foo{3});
|
||||
|
||||
// Set up a structure where we have a loop in the unique_ptr chain.
|
||||
Foo* f1 = new Foo{1};
|
||||
Foo* f2 = new Foo{2};
|
||||
f1->fp.reset(f2);
|
||||
f2->fp.reset(f1);
|
||||
|
||||
return 0; // Set break point at this line.
|
||||
}
|
||||
|
|
|
@ -94,29 +94,27 @@ bool LibStdcppUniquePtrSyntheticFrontEnd::MightHaveChildren() { return true; }
|
|||
lldb::ValueObjectSP
|
||||
LibStdcppUniquePtrSyntheticFrontEnd::GetChildAtIndex(size_t idx) {
|
||||
if (idx == 0)
|
||||
return m_obj_obj;
|
||||
return m_ptr_obj;
|
||||
if (idx == 1)
|
||||
return m_del_obj;
|
||||
if (idx == 2)
|
||||
return m_ptr_obj;
|
||||
return m_obj_obj;
|
||||
return lldb::ValueObjectSP();
|
||||
}
|
||||
|
||||
size_t LibStdcppUniquePtrSyntheticFrontEnd::CalculateNumChildren() {
|
||||
if (m_del_obj)
|
||||
return 2;
|
||||
if (m_ptr_obj && m_ptr_obj->GetValueAsUnsigned(0) != 0)
|
||||
return 1;
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
size_t LibStdcppUniquePtrSyntheticFrontEnd::GetIndexOfChildWithName(
|
||||
const ConstString &name) {
|
||||
if (name == ConstString("obj") || name == ConstString("object"))
|
||||
if (name == ConstString("ptr") || name == ConstString("pointer"))
|
||||
return 0;
|
||||
if (name == ConstString("del") || name == ConstString("deleter"))
|
||||
return 1;
|
||||
if (name == ConstString("ptr") || name == ConstString("pointer"))
|
||||
if (name == ConstString("obj") || name == ConstString("object"))
|
||||
return 2;
|
||||
return UINT32_MAX;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue