diff --git a/lldb/source/Plugins/Language/CPlusPlus/LibCxx.h b/lldb/source/Plugins/Language/CPlusPlus/LibCxx.h --- a/lldb/source/Plugins/Language/CPlusPlus/LibCxx.h +++ b/lldb/source/Plugins/Language/CPlusPlus/LibCxx.h @@ -124,7 +124,7 @@ ~LibcxxUniquePtrSyntheticFrontEnd() override; private: - lldb::ValueObjectSP m_compressed_pair_sp; + lldb::ValueObjectSP m_value_ptr_sp; }; SyntheticChildrenFrontEnd * diff --git a/lldb/source/Plugins/Language/CPlusPlus/LibCxx.cpp b/lldb/source/Plugins/Language/CPlusPlus/LibCxx.cpp --- a/lldb/source/Plugins/Language/CPlusPlus/LibCxx.cpp +++ b/lldb/source/Plugins/Language/CPlusPlus/LibCxx.cpp @@ -463,7 +463,7 @@ lldb_private::formatters::LibcxxUniquePtrSyntheticFrontEnd:: LibcxxUniquePtrSyntheticFrontEnd(lldb::ValueObjectSP valobj_sp) - : SyntheticChildrenFrontEnd(*valobj_sp), m_compressed_pair_sp() { + : SyntheticChildrenFrontEnd(*valobj_sp) { if (valobj_sp) Update(); } @@ -480,19 +480,27 @@ size_t lldb_private::formatters::LibcxxUniquePtrSyntheticFrontEnd:: CalculateNumChildren() { - return (m_compressed_pair_sp ? 1 : 0); + return (m_value_ptr_sp ? 1 : 0); } lldb::ValueObjectSP lldb_private::formatters::LibcxxUniquePtrSyntheticFrontEnd::GetChildAtIndex( size_t idx) { - if (!m_compressed_pair_sp) + if (!m_value_ptr_sp) return lldb::ValueObjectSP(); - if (idx != 0) - return lldb::ValueObjectSP(); + if (idx == 0) + return m_value_ptr_sp; - return m_compressed_pair_sp; + if (idx == 1) { + Status status; + auto value_sp = m_value_ptr_sp->Dereference(status); + if (status.Success()) { + return value_sp; + } + } + + return lldb::ValueObjectSP(); } bool lldb_private::formatters::LibcxxUniquePtrSyntheticFrontEnd::Update() { @@ -505,7 +513,7 @@ if (!ptr_sp) return false; - m_compressed_pair_sp = GetValueOfLibCXXCompressedPair(*ptr_sp); + m_value_ptr_sp = GetValueOfLibCXXCompressedPair(*ptr_sp); return false; } @@ -519,6 +527,8 @@ GetIndexOfChildWithName(ConstString name) { if (name == "__value_") return 0; + if (name == "$$dereference$$") + return 1; return UINT32_MAX; } diff --git a/lldb/test/API/functionalities/data-formatter/data-formatter-stl/libcxx/unique_ptr/TestDataFormatterLibcxxUniquePtr.py b/lldb/test/API/functionalities/data-formatter/data-formatter-stl/libcxx/unique_ptr/TestDataFormatterLibcxxUniquePtr.py --- a/lldb/test/API/functionalities/data-formatter/data-formatter-stl/libcxx/unique_ptr/TestDataFormatterLibcxxUniquePtr.py +++ b/lldb/test/API/functionalities/data-formatter/data-formatter-stl/libcxx/unique_ptr/TestDataFormatterLibcxxUniquePtr.py @@ -3,45 +3,85 @@ """ - import lldb from lldbsuite.test.decorators import * from lldbsuite.test.lldbtest import * from lldbsuite.test import lldbutil -class LibcxUniquePtrDataFormatterTestCase(TestBase): + +class TestCase(TestBase): mydir = TestBase.compute_mydir(__file__) @add_test_categories(["libc++"]) - def test_with_run_command(self): - """Test that that file and class static variables display correctly.""" + def test_unique_ptr_variables(self): + """Test `frame variable` output for `std::unique_ptr` types.""" self.build() - (self.target, self.process, _, bkpt) = lldbutil.run_to_source_breakpoint(self, '// break here', - lldb.SBFileSpec("main.cpp", False)) - - self.expect("frame variable up_empty", - substrs=['(std::unique_ptr >) up_empty = nullptr {', - '__value_ = ', - '}']) - - self.expect("frame variable up_int", - substrs=['(std::unique_ptr >) up_int = 10 {', - '__value_ = ', - '}']) - - self.expect("frame variable up_int_ref", - substrs=['(std::unique_ptr > &) up_int_ref = 10: {', - '__value_ = ', - '}']) - - self.expect("frame variable up_int_ref_ref", - substrs=['(std::unique_ptr > &&) up_int_ref_ref = 10: {', - '__value_ = ', - '}']) - - self.expect("frame variable up_str", - substrs=['up_str = "hello" {', - '__value_ = ', - '}']) + lldbutil.run_to_source_breakpoint( + self, "// break here", lldb.SBFileSpec("main.cpp") + ) + + valobj = self.expect_var_path( + "up_empty", + type="std::unique_ptr >", + summary="nullptr", + children=[ValueCheck(name="__value_")], + ) + self.assertEqual( + valobj.child[0].GetValueAsUnsigned(lldb.LLDB_INVALID_ADDRESS), 0 + ) + + self.expect( + "frame variable *up_empty", substrs=["(int) *up_empty = "] + ) + + valobj = self.expect_var_path( + "up_int", + type="std::unique_ptr >", + summary="10", + children=[ValueCheck(name="__value_")], + ) + self.assertNotEqual(valobj.child[0].unsigned, 0) + + valobj = self.expect_var_path( + "up_int_ref", + type="std::unique_ptr > &", + summary="10", + children=[ValueCheck(name="__value_")], + ) + self.assertNotEqual(valobj.child[0].unsigned, 0) + + valobj = self.expect_var_path( + "up_int_ref_ref", + type="std::unique_ptr > &&", + summary="10", + children=[ValueCheck(name="__value_")], + ) + self.assertNotEqual(valobj.child[0].unsigned, 0) + + valobj = self.expect_var_path( + "up_str", + type="std::unique_ptr, std::allocator >, std::default_delete, std::allocator > > >", + summary='"hello"', + children=[ValueCheck(name="__value_", summary='"hello"')], + ) + + valobj = self.expect_var_path( + "up_user", type="std::unique_ptr >" + ) + self.assertRegex(valobj.summary, "^User @ 0x0*[1-9a-f][0-9a-f]+$") + self.assertNotEqual(valobj.child[0].unsigned, 0) + + valobj = self.expect_var_path( + "*up_user", + type="User", + children=[ + ValueCheck(name="id", value="30"), + ValueCheck(name="name", summary='"steph"'), + ], + ) + self.assertEqual(str(valobj), '(User) *__value_ = (id = 30, name = "steph")') + + self.expect_var_path("up_user->id", type="int", value="30") + self.expect_var_path("up_user->name", type="std::string", summary='"steph"') diff --git a/lldb/test/API/functionalities/data-formatter/data-formatter-stl/libcxx/unique_ptr/main.cpp b/lldb/test/API/functionalities/data-formatter/data-formatter-stl/libcxx/unique_ptr/main.cpp --- a/lldb/test/API/functionalities/data-formatter/data-formatter-stl/libcxx/unique_ptr/main.cpp +++ b/lldb/test/API/functionalities/data-formatter/data-formatter-stl/libcxx/unique_ptr/main.cpp @@ -1,13 +1,18 @@ -#include #include #include +struct User { + int id = 30; + std::string name = "steph"; +}; + int main() { std::unique_ptr up_empty; std::unique_ptr up_int = std::make_unique(10); std::unique_ptr up_str = std::make_unique("hello"); std::unique_ptr &up_int_ref = up_int; std::unique_ptr &&up_int_ref_ref = std::make_unique(10); + std::unique_ptr up_user = std::make_unique(); return 0; // break here }