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:
Tamas Berghammer 2017-03-31 20:07:20 +00:00
parent 885fa12e8a
commit af8953a025
3 changed files with 52 additions and 12 deletions

View File

@ -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())

View File

@ -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.
}

View File

@ -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;
}