https://github.com/Michael137 created https://github.com/llvm/llvm-project/pull/147031
The libc++ test was a subset of the tests in libstdc++. This test moves the libc++ test into `generic` and somne additional test-cases from `libstdc++` (specifically the recursive unique_ptr case). It turns out the libstdc++ formatter supports dereferencing using the "object" or "obj" names. We could either drop those from the tests or support the same for libc++. I took the latter approach but don't have strong opinions on this. Split out from https://github.com/llvm/llvm-project/pull/146740 >From afa00be16641075f71bb7ce15e568ecb3b126719 Mon Sep 17 00:00:00 2001 From: Michael Buch <michaelbuc...@gmail.com> Date: Thu, 3 Jul 2025 15:41:44 +0100 Subject: [PATCH] [lldb][Formatter] Consolidate libstdc++ and libc++ unique_ptr formatter tests into generic test The libc++ test was a subset of the tests in libstdc++. This test moves the libc++ test into `generic` and somne additional test-cases from `libstdc++` (specifically the recursive unique_ptr case). It turns out the libstdc++ formatter supports dereferencing using the "object" or "obj" names. We could either drop those from the tests or support the same for libc++. I took the latter approach but don't have strong opinions on this. Split out from https://github.com/llvm/llvm-project/pull/146740 --- .../Plugins/Language/CPlusPlus/LibCxx.cpp | 2 +- .../{libcxx => generic}/unique_ptr/Makefile | 2 - .../TestDataFormatterStdUniquePtr.py} | 71 +++++++++- .../{libcxx => generic}/unique_ptr/main.cpp | 17 ++- .../libstdcpp/unique_ptr/Makefile | 5 - .../TestDataFormatterStdUniquePtr.py | 134 ------------------ .../TestDataFormatterInvalidStdUniquePtr.py | 4 - .../libstdcpp/unique_ptr/invalid/main.cpp | 11 -- .../libstdcpp/unique_ptr/main.cpp | 35 ----- 9 files changed, 82 insertions(+), 199 deletions(-) rename lldb/test/API/functionalities/data-formatter/data-formatter-stl/{libcxx => generic}/unique_ptr/Makefile (92%) rename lldb/test/API/functionalities/data-formatter/data-formatter-stl/{libcxx/unique_ptr/TestDataFormatterLibcxxUniquePtr.py => generic/unique_ptr/TestDataFormatterStdUniquePtr.py} (64%) rename lldb/test/API/functionalities/data-formatter/data-formatter-stl/{libcxx => generic}/unique_ptr/main.cpp (74%) delete mode 100644 lldb/test/API/functionalities/data-formatter/data-formatter-stl/libstdcpp/unique_ptr/Makefile delete mode 100644 lldb/test/API/functionalities/data-formatter/data-formatter-stl/libstdcpp/unique_ptr/TestDataFormatterStdUniquePtr.py delete mode 100644 lldb/test/API/functionalities/data-formatter/data-formatter-stl/libstdcpp/unique_ptr/invalid/TestDataFormatterInvalidStdUniquePtr.py delete mode 100644 lldb/test/API/functionalities/data-formatter/data-formatter-stl/libstdcpp/unique_ptr/invalid/main.cpp delete mode 100644 lldb/test/API/functionalities/data-formatter/data-formatter-stl/libstdcpp/unique_ptr/main.cpp diff --git a/lldb/source/Plugins/Language/CPlusPlus/LibCxx.cpp b/lldb/source/Plugins/Language/CPlusPlus/LibCxx.cpp index 009586f525282..51e43b2f62a1e 100644 --- a/lldb/source/Plugins/Language/CPlusPlus/LibCxx.cpp +++ b/lldb/source/Plugins/Language/CPlusPlus/LibCxx.cpp @@ -399,7 +399,7 @@ lldb_private::formatters::LibcxxUniquePtrSyntheticFrontEnd:: return 0; if (name == "deleter") return 1; - if (name == "$$dereference$$") + if (name == "obj" || name == "object" || name == "$$dereference$$") return 2; return llvm::createStringError("Type has no child named '%s'", name.AsCString()); diff --git a/lldb/test/API/functionalities/data-formatter/data-formatter-stl/libcxx/unique_ptr/Makefile b/lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic/unique_ptr/Makefile similarity index 92% rename from lldb/test/API/functionalities/data-formatter/data-formatter-stl/libcxx/unique_ptr/Makefile rename to lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic/unique_ptr/Makefile index c1c8b4a2a0a53..ece665a0fd5b7 100644 --- a/lldb/test/API/functionalities/data-formatter/data-formatter-stl/libcxx/unique_ptr/Makefile +++ b/lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic/unique_ptr/Makefile @@ -1,7 +1,5 @@ CXX_SOURCES := main.cpp -USE_LIBCPP := 1 - # We need debug info tuning for lldb in order to emit the preferred name for # std::string. See https://reviews.llvm.org/D145803. CXXFLAGS_EXTRAS := -std=c++14 -glldb 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/generic/unique_ptr/TestDataFormatterStdUniquePtr.py similarity index 64% rename from lldb/test/API/functionalities/data-formatter/data-formatter-stl/libcxx/unique_ptr/TestDataFormatterLibcxxUniquePtr.py rename to lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic/unique_ptr/TestDataFormatterStdUniquePtr.py index 25a1cd82a4baa..57e1ea9f234f8 100644 --- 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/generic/unique_ptr/TestDataFormatterStdUniquePtr.py @@ -1,8 +1,7 @@ """ -Test lldb data formatter for libc++ std::unique_ptr. +Test lldb data formatter for std::unique_ptr. """ - import lldb from lldbsuite.test.decorators import * from lldbsuite.test.lldbtest import * @@ -32,10 +31,8 @@ def make_expected_basic_string_ptr(self) -> str: "std::default_delete<std::basic_string<char, std::char_traits<char>, std::allocator<char> > > >" ) - @add_test_categories(["libc++"]) - def test_unique_ptr_variables(self): + def do_test(self): """Test `frame variable` output for `std::unique_ptr` types.""" - self.build() lldbutil.run_to_source_breakpoint( self, "// break here", lldb.SBFileSpec("main.cpp") @@ -121,3 +118,67 @@ def test_unique_ptr_variables(self): self.expect_var_path("ptr_node->next->value", value="2") self.expect_var_path("(*ptr_node).value", value="1") self.expect_var_path("(*(*ptr_node).next).value", value="2") + + @add_test_categories(["libstdcxx"]) + def test_libstdcxx(self): + self.build(dictionary={"USE_LIBSTDCPP": 1}) + self.do_test() + + @add_test_categories(["libc++"]) + def test_libcxx(self): + self.build(dictionary={"USE_LIBCPP": 1}) + self.do_test() + + def do_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.runCmd("file " + self.getBuildArtifact("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->next", substrs=["next = NodeU @"]) + self.expect( + "frame variable --ptr-depth=1 f1->next", + substrs=["next = NodeU @", "value = 2"], + ) + self.expect( + "frame variable --ptr-depth=2 f1->next", + substrs=["next = NodeU @", "value = 1", "value = 2"], + ) + + frame = self.frame() + self.assertTrue(frame.IsValid()) + self.assertEqual( + 2, + frame.GetValueForVariablePath("f1->next.object.value").GetValueAsUnsigned(), + ) + self.assertEqual( + 2, frame.GetValueForVariablePath("f1->next->value").GetValueAsUnsigned() + ) + self.assertEqual( + 1, + frame.GetValueForVariablePath( + "f1->next.object.next.obj.value" + ).GetValueAsUnsigned(), + ) + self.assertEqual( + 1, + frame.GetValueForVariablePath("f1->next->next->value").GetValueAsUnsigned(), + ) + + @add_test_categories(["libstdcxx"]) + def test_recursive_unique_ptr_libstdcxx(self): + self.build(dictionary={"USE_LIBSTDCPP": 1}) + self.do_test_recursive_unique_ptr() + + @add_test_categories(["libc++"]) + def test_recursive_unique_ptr_libcxx(self): + self.build(dictionary={"USE_LIBCPP": 1}) + self.do_test_recursive_unique_ptr() 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/generic/unique_ptr/main.cpp similarity index 74% rename from lldb/test/API/functionalities/data-formatter/data-formatter-stl/libcxx/unique_ptr/main.cpp rename to lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic/unique_ptr/main.cpp index afdddf0bbaf16..15e9f70dbd6aa 100644 --- 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/generic/unique_ptr/main.cpp @@ -15,11 +15,20 @@ struct NodeU { // representation when the type of the second element is an empty class. So // we need a deleter class with a dummy data member to trigger the other path. struct NonEmptyIntDeleter { - void operator()(int* ptr) { delete ptr; } + void operator()(int *ptr) { delete ptr; } int dummy_ = 9999; }; +static void recursive() { + // Set up a structure where we have a loop in the unique_ptr chain. + NodeU *f1 = new NodeU{nullptr, 1}; + NodeU *f2 = new NodeU{nullptr, 2}; + f1->next.reset(f2); + f2->next.reset(f1); + std::puts("Set break point at this line."); +} + int main() { std::unique_ptr<int> up_empty; std::unique_ptr<int> up_int = std::make_unique<int>(10); @@ -33,5 +42,9 @@ int main() { std::unique_ptr<NodeU>(new NodeU{nullptr, 2}); ptr_node = std::unique_ptr<NodeU>(new NodeU{std::move(ptr_node), 1}); - return 0; // break here + std::puts("// break here"); + + recursive(); + + return 0; } diff --git a/lldb/test/API/functionalities/data-formatter/data-formatter-stl/libstdcpp/unique_ptr/Makefile b/lldb/test/API/functionalities/data-formatter/data-formatter-stl/libstdcpp/unique_ptr/Makefile deleted file mode 100644 index bf8e6b8703f36..0000000000000 --- a/lldb/test/API/functionalities/data-formatter/data-formatter-stl/libstdcpp/unique_ptr/Makefile +++ /dev/null @@ -1,5 +0,0 @@ -CXX_SOURCES := main.cpp - -USE_LIBSTDCPP := 1 - -include Makefile.rules diff --git a/lldb/test/API/functionalities/data-formatter/data-formatter-stl/libstdcpp/unique_ptr/TestDataFormatterStdUniquePtr.py b/lldb/test/API/functionalities/data-formatter/data-formatter-stl/libstdcpp/unique_ptr/TestDataFormatterStdUniquePtr.py deleted file mode 100644 index 8f57dc88f3187..0000000000000 --- a/lldb/test/API/functionalities/data-formatter/data-formatter-stl/libstdcpp/unique_ptr/TestDataFormatterStdUniquePtr.py +++ /dev/null @@ -1,134 +0,0 @@ -""" -Test lldb data formatter subsystem. -""" - -import lldb -from lldbsuite.test.decorators import * -from lldbsuite.test.lldbtest import * -from lldbsuite.test import lldbutil - - -class StdUniquePtrDataFormatterTestCase(TestBase): - @add_test_categories(["libstdcxx"]) - @expectedFailureAll(bugnumber="llvm.org/pr50861", compiler="gcc") - @skipIf(oslist=["linux"], archs=["arm$", "aarch64"]) - def test_with_run_command(self): - self.build() - self.runCmd("file " + self.getBuildArtifact("a.out"), CURRENT_EXECUTABLE_SET) - - lldbutil.run_break_set_by_source_regexp(self, "Set break point at this line.") - self.runCmd("run", RUN_SUCCEEDED) - - # The stop reason of the thread should be breakpoint. - self.expect( - "thread list", - STOPPED_DUE_TO_BREAKPOINT, - substrs=["stopped", "stop reason = breakpoint"], - ) - - frame = self.frame() - self.assertTrue(frame.IsValid()) - - self.expect("frame variable nup", substrs=["nup = nullptr"]) - self.expect("frame variable iup", substrs=["iup = 123"]) - self.expect("frame variable sup", substrs=['sup = "foobar"']) - - self.expect("frame variable ndp", substrs=["ndp = nullptr"]) - self.expect( - "frame variable idp", substrs=["idp = 456", "deleter = ", "a = 1", "b = 2"] - ) - self.expect( - "frame variable sdp", - substrs=['sdp = "baz"', "deleter = ", "a = 3", "b = 4"], - ) - - self.assertEqual( - 123, frame.GetValueForVariablePath("iup.object").GetValueAsUnsigned() - ) - self.assertEqual( - 123, frame.GetValueForVariablePath("*iup").GetValueAsUnsigned() - ) - self.assertFalse(frame.GetValueForVariablePath("iup.deleter").IsValid()) - - self.assertEqual( - '"foobar"', frame.GetValueForVariablePath("sup.object").GetSummary() - ) - self.assertEqual('"foobar"', frame.GetValueForVariablePath("*sup").GetSummary()) - self.assertFalse(frame.GetValueForVariablePath("sup.deleter").IsValid()) - - self.assertEqual( - 456, frame.GetValueForVariablePath("idp.object").GetValueAsUnsigned() - ) - self.assertEqual( - 456, frame.GetValueForVariablePath("*idp").GetValueAsUnsigned() - ) - self.assertEqual( - '"baz"', frame.GetValueForVariablePath("sdp.object").GetSummary() - ) - self.assertEqual('"baz"', frame.GetValueForVariablePath("*sdp").GetSummary()) - - idp_deleter = frame.GetValueForVariablePath("idp.deleter") - self.assertTrue(idp_deleter.IsValid()) - self.assertEqual( - 1, idp_deleter.GetChildMemberWithName("a").GetValueAsUnsigned() - ) - self.assertEqual( - 2, idp_deleter.GetChildMemberWithName("b").GetValueAsUnsigned() - ) - - sdp_deleter = frame.GetValueForVariablePath("sdp.deleter") - 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 - @skipIfwatchOS # libstdcpp not ported to watchos - @skipIf(oslist=["linux"], archs=["arm$", "aarch64"]) - @add_test_categories(["libstdcxx"]) - 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 " + self.getBuildArtifact("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 = Foo @ 0x"]) - self.expect( - "frame variable --ptr-depth=1 f1->fp", substrs=["data = 2", "fp = Foo @ 0x"] - ) - self.expect( - "frame variable --ptr-depth=2 f1->fp", - substrs=["data = 2", "fp = Foo @ 0x", "data = 1"], - ) - - frame = self.frame() - self.assertTrue(frame.IsValid()) - self.assertEqual( - 2, frame.GetValueForVariablePath("f1->fp.object.data").GetValueAsUnsigned() - ) - self.assertEqual( - 2, frame.GetValueForVariablePath("f1->fp->data").GetValueAsUnsigned() - ) - self.assertEqual( - 1, - frame.GetValueForVariablePath( - "f1->fp.object.fp.object.data" - ).GetValueAsUnsigned(), - ) - self.assertEqual( - 1, frame.GetValueForVariablePath("f1->fp->fp->data").GetValueAsUnsigned() - ) diff --git a/lldb/test/API/functionalities/data-formatter/data-formatter-stl/libstdcpp/unique_ptr/invalid/TestDataFormatterInvalidStdUniquePtr.py b/lldb/test/API/functionalities/data-formatter/data-formatter-stl/libstdcpp/unique_ptr/invalid/TestDataFormatterInvalidStdUniquePtr.py deleted file mode 100644 index 9cacfce989769..0000000000000 --- a/lldb/test/API/functionalities/data-formatter/data-formatter-stl/libstdcpp/unique_ptr/invalid/TestDataFormatterInvalidStdUniquePtr.py +++ /dev/null @@ -1,4 +0,0 @@ -import lldbsuite.test.lldbinline as lldbinline -from lldbsuite.test.decorators import * - -lldbinline.MakeInlineTest(__file__, globals(), [no_debug_info_test]) diff --git a/lldb/test/API/functionalities/data-formatter/data-formatter-stl/libstdcpp/unique_ptr/invalid/main.cpp b/lldb/test/API/functionalities/data-formatter/data-formatter-stl/libstdcpp/unique_ptr/invalid/main.cpp deleted file mode 100644 index b12cab231695b..0000000000000 --- a/lldb/test/API/functionalities/data-formatter/data-formatter-stl/libstdcpp/unique_ptr/invalid/main.cpp +++ /dev/null @@ -1,11 +0,0 @@ -// Test that we don't crash when trying to pretty-print structures that don't -// have the layout our data formatters expect. -namespace std { -template<typename T, typename Deleter = void> -class unique_ptr {}; -} - -int main() { - std::unique_ptr<int> U; - return 0; //% self.expect("frame variable U", substrs=["unique_ptr", "{}"]) -} diff --git a/lldb/test/API/functionalities/data-formatter/data-formatter-stl/libstdcpp/unique_ptr/main.cpp b/lldb/test/API/functionalities/data-formatter/data-formatter-stl/libstdcpp/unique_ptr/main.cpp deleted file mode 100644 index dd0072764d4e6..0000000000000 --- a/lldb/test/API/functionalities/data-formatter/data-formatter-stl/libstdcpp/unique_ptr/main.cpp +++ /dev/null @@ -1,35 +0,0 @@ -#include <memory> -#include <string> - -struct Deleter { - void operator()(void *) {} - - int a; - 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}); - std::unique_ptr<std::string> sup(new std::string("foobar")); - - std::unique_ptr<char, Deleter> ndp; - std::unique_ptr<int, Deleter> idp(new int{456}, Deleter{1, 2}); - 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. -} _______________________________________________ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits