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 @@ -314,19 +314,23 @@ def has_children(self): return True - -class StdMapSynthProvider: + """ + Set and Map have the same underlying data structure, + therefore we can use exactly the same implementation for the formatter. + """ +class StdSetOrMapSynthProvider: def __init__(self, valobj, dict): logger = lldb.formatters.Logger.Logger() self.valobj = valobj self.count = None - logger >> "Providing synthetic children for a map named " + \ + self.kind = "set" if "set" in valobj.GetTypeName() else "map" + logger >> "Providing synthetic children for a " + self.kind + " named " + \ str(valobj.GetName()) # 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 map itself - because we have to make up the + # arguments for _Rep_Type _M_t in the object itself - because we have to make up the # typename and then find it, we may hit the situation were std::string has multiple # names but only one is actually referenced in the debug information. hence, we need # to replace the longer versions of std::string with the shorter one in order to be able @@ -349,7 +353,7 @@ # later self.count = None try: - # we will set this to True if we find out that discovering a node in the map takes more steps than the overall size of the RB tree + # we will set this to True if we find out that discovering a node in the object takes more steps than the overall size of the RB tree # if this gets set to True, then we will merrily return None for # any child from that moment on self.garbage = False 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 @@ -905,6 +905,8 @@ SyntheticChildren::Flags stl_synth_flags; stl_synth_flags.SetCascades(true).SetSkipPointers(false).SetSkipReferences( false); + SyntheticChildren::Flags stl_deref_flags = stl_synth_flags; + stl_deref_flags.SetFrontEndWantsDereference(); cpp_category_sp->GetRegexTypeSyntheticsContainer()->Add( RegularExpression("^std::vector<.+>(( )?&)?$"), @@ -915,14 +917,19 @@ RegularExpression("^std::map<.+> >(( )?&)?$"), SyntheticChildrenSP(new ScriptedSyntheticChildren( stl_synth_flags, - "lldb.formatters.cpp.gnu_libstdcpp.StdMapSynthProvider"))); + "lldb.formatters.cpp.gnu_libstdcpp.StdSetOrMapSynthProvider"))); + cpp_category_sp->GetRegexTypeSyntheticsContainer()->Add( + RegularExpression("^std::set<.+> >(( )?&)?$"), + SyntheticChildrenSP(new ScriptedSyntheticChildren( + stl_deref_flags, + "lldb.formatters.cpp.gnu_libstdcpp.StdSetOrMapSynthProvider"))); cpp_category_sp->GetRegexTypeSyntheticsContainer()->Add( RegularExpression("^std::(__cxx11::)?list<.+>(( )?&)?$"), SyntheticChildrenSP(new ScriptedSyntheticChildren( stl_synth_flags, "lldb.formatters.cpp.gnu_libstdcpp.StdListSynthProvider"))); stl_summary_flags.SetDontShowChildren(false); - stl_summary_flags.SetSkipPointers(true); + stl_summary_flags.SetSkipPointers(false); cpp_category_sp->GetRegexTypeSummariesContainer()->Add( RegularExpression("^std::vector<.+>(( )?&)?$"), TypeSummaryImplSP( @@ -931,6 +938,10 @@ RegularExpression("^std::map<.+> >(( )?&)?$"), TypeSummaryImplSP( new StringSummaryFormat(stl_summary_flags, "size=${svar%#}"))); + cpp_category_sp->GetRegexTypeSummariesContainer()->Add( + RegularExpression("^std::set<.+> >(( )?&)?$"), + 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/set/Makefile b/lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic/set/Makefile rename from lldb/test/API/functionalities/data-formatter/data-formatter-stl/libcxx/set/Makefile rename to lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic/set/Makefile --- a/lldb/test/API/functionalities/data-formatter/data-formatter-stl/libcxx/set/Makefile +++ b/lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic/set/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/set/TestDataFormatterLibcxxSet.py b/lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic/set/TestDataFormatterGenericSet.py rename from lldb/test/API/functionalities/data-formatter/data-formatter-stl/libcxx/set/TestDataFormatterLibcxxSet.py rename to lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic/set/TestDataFormatterGenericSet.py --- a/lldb/test/API/functionalities/data-formatter/data-formatter-stl/libcxx/set/TestDataFormatterLibcxxSet.py +++ b/lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic/set/TestDataFormatterGenericSet.py @@ -9,6 +9,8 @@ from lldbsuite.test.lldbtest import * from lldbsuite.test import lldbutil +USE_LIBSTDCPP = "USE_LIBSTDCPP" +USE_LIBCPP = "USE_LIBCPP" class LibcxxSetDataFormatterTestCase(TestBase): @@ -18,34 +20,29 @@ 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"]) + 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) - @add_test_categories(["libc++"]) - def test_with_run_command(self): + + + 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)) @@ -79,7 +76,7 @@ "[4] = 4", "[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", "{}"]) @@ -120,19 +117,36 @@ '[0] = "a"', '[1] = "a very long string is right here"', '[2] = "c"']) + self.check("ss",3) + + @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_ref_and_ptr(self): + def test_with_run_command_libcpp(self): + self.do_test_with_run_command(USE_LIBCPP) + + + def do_test_ref_and_ptr(self,stdlib_type): """Test that the data formatters work on ref and ptr.""" self.build() (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.check("ptr", 7) self.expect("frame variable ptr", substrs=["ptr =", "size=7"]) self.expect("expr ptr", substrs=["size=7"]) + @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) \ No newline at end of file diff --git a/lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic/set/main.cpp b/lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic/set/main.cpp new file mode 100644 --- /dev/null +++ b/lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic/set/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::set &ref, std::set *ptr) { + // Stop here to check by ref and ptr + return; +} + +int main() { + std::set 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::set 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/libcxx/set/main.cpp b/lldb/test/API/functionalities/data-formatter/data-formatter-stl/libcxx/set/main.cpp deleted file mode 100644 --- a/lldb/test/API/functionalities/data-formatter/data-formatter-stl/libcxx/set/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::set &ref, std::set *ptr) -{ - // Stop here to check by ref and ptr - return; -} - -int main() -{ - std::set 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::set 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; -}