diff --git a/lldb/examples/synthetic/gnu_libstdcpp.py b/lldb/examples/synthetic/gnu_libstdcpp.py --- a/lldb/examples/synthetic/gnu_libstdcpp.py +++ b/lldb/examples/synthetic/gnu_libstdcpp.py @@ -324,10 +324,17 @@ logger = lldb.formatters.Logger.Logger() self.valobj = valobj self.count = None - self.kind = "set" if "set" in valobj.GetTypeName() else "map" + self.kind = self.get_object_kind(valobj) logger >> "Providing synthetic children for a " + self.kind + " named " + \ str(valobj.GetName()) + def get_object_kind(self, valobj): + type_name = valobj.GetTypeName() + for kind in ["multiset", "multimap", "set", "map"]: + if kind in type_name: + return kind + return type_name + # we need this function as a temporary workaround for rdar://problem/10801549 # which prevents us from extracting the std::pair SBType out of the template # arguments for _Rep_Type _M_t in the object itself - because we have to make up the diff --git a/lldb/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.cpp b/lldb/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.cpp --- a/lldb/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.cpp +++ b/lldb/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.cpp @@ -913,6 +913,11 @@ SyntheticChildrenSP(new ScriptedSyntheticChildren( stl_deref_flags, "lldb.formatters.cpp.gnu_libstdcpp.StdMapLikeSynthProvider"))); + cpp_category_sp->GetRegexTypeSyntheticsContainer()->Add( + RegularExpression("^std::multiset<.+> >(( )?&)?$"), + SyntheticChildrenSP(new ScriptedSyntheticChildren( + stl_deref_flags, + "lldb.formatters.cpp.gnu_libstdcpp.StdMapLikeSynthProvider"))); cpp_category_sp->GetRegexTypeSyntheticsContainer()->Add( RegularExpression("^std::(__cxx11::)?list<.+>(( )?&)?$"), SyntheticChildrenSP(new ScriptedSyntheticChildren( @@ -940,6 +945,10 @@ RegularExpression("^std::multimap<.+> >(( )?&)?$"), TypeSummaryImplSP( new StringSummaryFormat(stl_summary_flags, "size=${svar%#}"))); + cpp_category_sp->GetRegexTypeSummariesContainer()->Add( + RegularExpression("^std::multiset<.+> >(( )?&)?$"), + TypeSummaryImplSP( + new StringSummaryFormat(stl_summary_flags, "size=${svar%#}"))); cpp_category_sp->GetRegexTypeSummariesContainer()->Add( RegularExpression("^std::(__cxx11::)?list<.+>(( )?&)?$"), TypeSummaryImplSP( diff --git a/lldb/test/API/functionalities/data-formatter/data-formatter-stl/libcxx/multiset/Makefile b/lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic/multiset/Makefile rename from lldb/test/API/functionalities/data-formatter/data-formatter-stl/libcxx/multiset/Makefile rename to lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic/multiset/Makefile --- a/lldb/test/API/functionalities/data-formatter/data-formatter-stl/libcxx/multiset/Makefile +++ b/lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic/multiset/Makefile @@ -1,6 +1,3 @@ CXX_SOURCES := main.cpp -USE_LIBCPP := 1 - -CXXFLAGS_EXTRAS := -O0 include Makefile.rules diff --git a/lldb/test/API/functionalities/data-formatter/data-formatter-stl/libcxx/multiset/TestDataFormatterLibcxxMultiSet.py b/lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic/multiset/TestDataFormatterGenericMultiSet.py rename from lldb/test/API/functionalities/data-formatter/data-formatter-stl/libcxx/multiset/TestDataFormatterLibcxxMultiSet.py rename to lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic/multiset/TestDataFormatterGenericMultiSet.py --- a/lldb/test/API/functionalities/data-formatter/data-formatter-stl/libcxx/multiset/TestDataFormatterLibcxxMultiSet.py +++ b/lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic/multiset/TestDataFormatterGenericMultiSet.py @@ -9,8 +9,10 @@ from lldbsuite.test.lldbtest import * from lldbsuite.test import lldbutil +USE_LIBSTDCPP = "USE_LIBSTDCPP" +USE_LIBCPP = "USE_LIBCPP" -class LibcxxMultiSetDataFormatterTestCase(TestBase): +class GenericMultiSetDataFormatterTestCase(TestBase): mydir = TestBase.compute_mydir(__file__) @@ -18,34 +20,28 @@ TestBase.setUp(self) self.namespace = 'std' - def getVariableType(self, name): + def findVariable(self, name): var = self.frame().FindVariable(name) self.assertTrue(var.IsValid()) + return var + + def getVariableType(self, name): + var = self.findVariable(name) return var.GetType().GetDisplayTypeName() - def check_ii(self, var_name): - """ This checks the value of the bitset stored in ii at the call to by_ref_and_ptr. - We use this to make sure we get the same values for ii when we look at the object - directly, and when we look at a reference to the object. """ - self.expect( - "frame variable " + var_name, - substrs=["size=7", - "[2] = 2", - "[3] = 3", - "[6] = 6"]) - self.expect("frame variable " + var_name + "[2]", substrs=[" = 2"]) - self.expect( - "p " + var_name, - substrs=[ - "size=7", - "[2] = 2", - "[3] = 3", - "[6] = 6"]) - @add_test_categories(["libc++"]) - def test_with_run_command(self): + def check(self, var_name, size): + var = self.findVariable(var_name) + self.assertEqual(var.GetNumChildren(), size) + children = [] + for i in range(size): + child = var.GetChildAtIndex(i) + children.append(ValueCheck(value=child.GetValue())) + self.expect_var_path(var_name, type=self.getVariableType(var_name), children=children) + + def do_test_with_run_command(self, stdlib_type): """Test that that file and class static variables display correctly.""" - self.build() + self.build(dictionary={stdlib_type: "1"}) (self.target, process, _, bkpt) = lldbutil.run_to_source_breakpoint( self, "Set break point at this line.", lldb.SBFileSpec("main.cpp", False)) @@ -81,16 +77,18 @@ "[5] = 5"]) lldbutil.continue_to_breakpoint(process, bkpt) - self.check_ii("ii") + self.check("ii", 7) lldbutil.continue_to_breakpoint(process, bkpt) self.expect("frame variable ii", substrs=["size=0", "{}"]) + self.check("ii", 0) lldbutil.continue_to_breakpoint(process, bkpt) self.expect("frame variable ii", substrs=["size=0", "{}"]) ss_type = self.getVariableType("ss") self.assertTrue(ss_type.startswith(self.namespace + "::multiset"), "Type: " + ss_type) self.expect("frame variable ss", substrs=["size=0", "{}"]) + self.check("ss", 0) lldbutil.continue_to_breakpoint(process, bkpt) self.expect( "frame variable ss", @@ -98,6 +96,7 @@ "size=2", '[0] = "a"', '[1] = "a very long string is right here"']) + self.check("ss", 2) lldbutil.continue_to_breakpoint(process, bkpt) self.expect( "frame variable ss", @@ -108,6 +107,7 @@ '[2] = "b"', '[3] = "c"', ]) + self.check("ss", 4) self.expect( "p ss", substrs=[ @@ -127,17 +127,32 @@ '[1] = "a very long string is right here"', '[2] = "c"']) - @add_test_categories(["libc++"]) - def test_ref_and_ptr(self): + def do_test_ref_and_ptr(self, stdlib_type): """Test that the data formatters work on ref and ptr.""" - self.build() + self.build(dictionary={stdlib_type: "1"}) (self.target, process, _, bkpt) = lldbutil.run_to_source_breakpoint( self, "Stop here to check by ref and ptr.", lldb.SBFileSpec("main.cpp", False)) # The reference should print just like the value: - self.check_ii("ref") + self.check("ref", 7) self.expect("frame variable ptr", substrs=["ptr =", "size=7"]) self.expect("expr ptr", substrs=["size=7"]) + + @add_test_categories(["libstdcxx"]) + def test_with_run_command_libstdcpp(self): + self.do_test_with_run_command(USE_LIBSTDCPP) + + @add_test_categories(["libc++"]) + def test_with_run_command_libcpp(self): + self.do_test_with_run_command(USE_LIBCPP) + + @add_test_categories(["libstdcxx"]) + def test_ref_and_ptr_libstdcpp(self): + self.do_test_ref_and_ptr(USE_LIBSTDCPP) + + @add_test_categories(["libc++"]) + def test_ref_and_ptr_libcpp(self): + self.do_test_ref_and_ptr(USE_LIBCPP) diff --git a/lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic/multiset/main.cpp b/lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic/multiset/main.cpp new file mode 100644 --- /dev/null +++ b/lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic/multiset/main.cpp @@ -0,0 +1,55 @@ +#include +#include + +int g_the_foo = 0; + +int thefoo_rw(int arg = 1) { + if (arg < 0) + arg = 0; + if (!arg) + arg = 1; + g_the_foo += arg; + return g_the_foo; +} + +void by_ref_and_ptr(std::multiset &ref, std::multiset *ptr) { + // Stop here to check by ref and ptr + return; +} + +int main() { + std::multiset ii; + thefoo_rw(1); // Set break point at this line. + + ii.insert(0); + ii.insert(1); + ii.insert(2); + ii.insert(3); + ii.insert(4); + ii.insert(5); + thefoo_rw(1); // Set break point at this line. + + ii.insert(6); + thefoo_rw(1); // Set break point at this line. + + by_ref_and_ptr(ii, &ii); + + ii.clear(); + thefoo_rw(1); // Set break point at this line. + + std::multiset ss; + thefoo_rw(1); // Set break point at this line. + + ss.insert("a"); + ss.insert("a very long string is right here"); + thefoo_rw(1); // Set break point at this line. + + ss.insert("b"); + ss.insert("c"); + thefoo_rw(1); // Set break point at this line. + + ss.erase("b"); + thefoo_rw(1); // Set break point at this line. + + return 0; +} diff --git a/lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic/set/TestDataFormatterGenericSet.py b/lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic/set/TestDataFormatterGenericSet.py --- a/lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic/set/TestDataFormatterGenericSet.py +++ b/lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic/set/TestDataFormatterGenericSet.py @@ -12,7 +12,7 @@ USE_LIBSTDCPP = "USE_LIBSTDCPP" USE_LIBCPP = "USE_LIBCPP" -class LibcxxSetDataFormatterTestCase(TestBase): +class GenericSetDataFormatterTestCase(TestBase): mydir = TestBase.compute_mydir(__file__) diff --git a/lldb/test/API/functionalities/data-formatter/data-formatter-stl/libcxx/multiset/main.cpp b/lldb/test/API/functionalities/data-formatter/data-formatter-stl/libcxx/multiset/main.cpp deleted file mode 100644 --- a/lldb/test/API/functionalities/data-formatter/data-formatter-stl/libcxx/multiset/main.cpp +++ /dev/null @@ -1,58 +0,0 @@ -#include -#include - -int g_the_foo = 0; - -int thefoo_rw(int arg = 1) -{ - if (arg < 0) - arg = 0; - if (!arg) - arg = 1; - g_the_foo += arg; - return g_the_foo; -} - -void by_ref_and_ptr(std::multiset &ref, std::multiset *ptr) -{ - // Stop here to check by ref and ptr - return; -} - -int main() -{ - std::multiset ii; - thefoo_rw(1); // Set break point at this line. - - ii.insert(0); - ii.insert(1); - ii.insert(2); - ii.insert(3); - ii.insert(4); - ii.insert(5); - thefoo_rw(1); // Set break point at this line. - - ii.insert(6); - thefoo_rw(1); // Set break point at this line. - - by_ref_and_ptr(ii, &ii); - - ii.clear(); - thefoo_rw(1); // Set break point at this line. - - std::multiset ss; - thefoo_rw(1); // Set break point at this line. - - ss.insert("a"); - ss.insert("a very long string is right here"); - thefoo_rw(1); // Set break point at this line. - - ss.insert("b"); - ss.insert("c"); - thefoo_rw(1); // Set break point at this line. - - ss.erase("b"); - thefoo_rw(1); // Set break point at this line. - - return 0; -}