danilashtefan updated this revision to Diff 387084.
danilashtefan added a comment.

Some naming corrections


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D113760/new/

https://reviews.llvm.org/D113760

Files:
  lldb/examples/synthetic/gnu_libstdcpp.py
  lldb/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.cpp
  
lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic/unordered/Makefile
  
lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic/unordered/TestDataFormatterGenericUnordered.py
  
lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic/unordered/main.cpp

Index: lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic/unordered/main.cpp
===================================================================
--- /dev/null
+++ lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic/unordered/main.cpp
@@ -0,0 +1,78 @@
+#include <string>
+#include <unordered_map>
+#include <unordered_set>
+
+using std::string;
+
+#define intstr_map std::unordered_map<int, string>
+#define intstr_mmap std::unordered_multimap<int, string>
+
+#define int_set std::unordered_set<int>
+#define str_set std::unordered_set<string>
+#define int_mset std::unordered_multiset<int>
+#define str_mset std::unordered_multiset<string>
+
+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;
+}
+
+int main() {
+  intstr_map map;
+  map.emplace(1, "hello");
+  map.emplace(2, "world");
+  map.emplace(3, "this");
+  map.emplace(4, "is");
+  map.emplace(5, "me");
+  thefoo_rw(); // Set break point at this line.
+
+  intstr_mmap mmap;
+  mmap.emplace(1, "hello");
+  mmap.emplace(2, "hello");
+  mmap.emplace(2, "world");
+  mmap.emplace(3, "this");
+  mmap.emplace(3, "this");
+  mmap.emplace(3, "this");
+  thefoo_rw(); // Set break point at this line.
+
+  int_set iset;
+  iset.emplace(1);
+  iset.emplace(2);
+  iset.emplace(3);
+  iset.emplace(4);
+  iset.emplace(5);
+  thefoo_rw(); // Set break point at this line.
+
+  str_set sset;
+  sset.emplace("hello");
+  sset.emplace("world");
+  sset.emplace("this");
+  sset.emplace("is");
+  sset.emplace("me");
+  thefoo_rw(); // Set break point at this line.
+
+  int_mset imset;
+  imset.emplace(1);
+  imset.emplace(2);
+  imset.emplace(2);
+  imset.emplace(3);
+  imset.emplace(3);
+  imset.emplace(3);
+  thefoo_rw(); // Set break point at this line.
+
+  str_mset smset;
+  smset.emplace("hello");
+  smset.emplace("world");
+  smset.emplace("world");
+  smset.emplace("is");
+  smset.emplace("is");
+  thefoo_rw(); // Set break point at this line.
+
+  return 0;
+}
Index: lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic/unordered/TestDataFormatterGenericUnordered.py
===================================================================
--- /dev/null
+++ lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic/unordered/TestDataFormatterGenericUnordered.py
@@ -0,0 +1,78 @@
+"""
+Test lldb data formatter subsystem.
+"""
+
+
+
+import lldb
+from lldbsuite.test.decorators import *
+from lldbsuite.test.lldbtest import *
+from lldbsuite.test import lldbutil
+
+
+class GenericUnorderedDataFormatterTestCase(TestBase):
+
+    mydir = TestBase.compute_mydir(__file__)
+
+    def setUp(self):
+        TestBase.setUp(self)
+        self.namespace = 'std'
+
+    @add_test_categories(["libstdcxx"])
+    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'])
+
+        # This is the function to remove the custom formats in order to have a
+        # clean slate for the next test case.
+        def cleanup():
+            self.runCmd('type format clear', check=False)
+            self.runCmd('type summary clear', check=False)
+            self.runCmd('type filter clear', check=False)
+            self.runCmd('type synth clear', check=False)
+            self.runCmd(
+                "settings set target.max-children-count 256",
+                check=False)
+
+        # Execute the cleanup function during test case tear down.
+        self.addTearDownHook(cleanup)
+
+        ns = self.namespace
+        self.look_for_content_and_continue(
+            "map", ['%s::unordered_map' %
+                    ns, 'size=5 {', 'hello', 'world', 'this', 'is', 'me'])
+
+        self.look_for_content_and_continue(
+            "mmap", ['%s::unordered_multimap' % ns, 'size=6 {', 'first = 3', 'second = "this"',
+                     'first = 2', 'second = "hello"'])
+
+        self.look_for_content_and_continue(
+            "iset", ['%s::unordered_set' %
+                     ns, 'size=5 {', '\[\d\] = 5', '\[\d\] = 3', '\[\d\] = 2'])
+
+        self.look_for_content_and_continue(
+            "sset", ['%s::unordered_set' % ns, 'size=5 {', '\[\d\] = "is"', '\[\d\] = "world"',
+                     '\[\d\] = "hello"'])
+
+        self.look_for_content_and_continue(
+            "imset", ['%s::unordered_multiset' % ns, 'size=6 {', '(\[\d\] = 3(\\n|.)+){3}',
+                      '\[\d\] = 2', '\[\d\] = 1'])
+
+        self.look_for_content_and_continue(
+            "smset", ['%s::unordered_multiset' % ns, 'size=5 {', '(\[\d\] = "is"(\\n|.)+){2}',
+                      '(\[\d\] = "world"(\\n|.)+){2}'])
+
+    def look_for_content_and_continue(self, var_name, patterns):
+        self.expect(("frame variable %s" % var_name), patterns=patterns)
+        self.expect(("frame variable %s" % var_name), patterns=patterns)
+        self.runCmd("continue")
Index: lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic/unordered/Makefile
===================================================================
--- /dev/null
+++ lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic/unordered/Makefile
@@ -0,0 +1,4 @@
+CXX_SOURCES := main.cpp
+
+USE_LIBSTDCPP := 1
+include Makefile.rules
Index: lldb/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.cpp
===================================================================
--- lldb/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.cpp
+++ lldb/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.cpp
@@ -918,6 +918,11 @@
       SyntheticChildrenSP(new ScriptedSyntheticChildren(
           stl_deref_flags,
           "lldb.formatters.cpp.gnu_libstdcpp.StdMapLikeSynthProvider")));
+  cpp_category_sp->GetRegexTypeSyntheticsContainer()->Add(
+      RegularExpression("^std::unordered_(multi)?(map|set)<.+> >$"),
+      SyntheticChildrenSP(new ScriptedSyntheticChildren(
+          stl_deref_flags,
+          "lldb.formatters.cpp.gnu_libstdcpp.StdUnorderedMapSynthProvider")));
   cpp_category_sp->GetRegexTypeSyntheticsContainer()->Add(
       RegularExpression("^std::(__cxx11::)?list<.+>(( )?&)?$"),
       SyntheticChildrenSP(new ScriptedSyntheticChildren(
@@ -949,6 +954,10 @@
       RegularExpression("^std::multiset<.+> >(( )?&)?$"),
       TypeSummaryImplSP(
           new StringSummaryFormat(stl_summary_flags, "size=${svar%#}")));
+  cpp_category_sp->GetRegexTypeSummariesContainer()->Add(
+      RegularExpression("^std::unordered_(multi)?(map|set)<.+> >$"),
+      TypeSummaryImplSP(
+          new StringSummaryFormat(stl_summary_flags, "size=${svar%#}")));
   cpp_category_sp->GetRegexTypeSummariesContainer()->Add(
       RegularExpression("^std::(__cxx11::)?list<.+>(( )?&)?$"),
       TypeSummaryImplSP(
Index: lldb/examples/synthetic/gnu_libstdcpp.py
===================================================================
--- lldb/examples/synthetic/gnu_libstdcpp.py
+++ lldb/examples/synthetic/gnu_libstdcpp.py
@@ -7,6 +7,84 @@
 # as it ships with Mac OS X 10.6.8 thru 10.8.0
 # You are encouraged to look at the STL implementation for your platform
 # before relying on these formatters to do the right thing for your setup
+class StdUnorderedMapSynthProvider:
+    def __init__(self, valobj, dict):
+        self.valobj = valobj
+        self.count = None
+        # type of std::pair<key, value> is the first template
+        # argument type of the 4th template argument to std::map and 
+        # 3rd template argument for std::set. That's why 
+        # we need to know kind of the object
+        self.kind = self.get_object_kind(valobj)
+
+    def get_object_kind(self, valobj):
+        type_name = valobj.GetTypeName()
+        for kind in ["set", "map"]:
+           if kind in type_name:
+              return kind
+        return Exception
+
+    def extract_type(self):
+        type = self.valobj.GetType()
+        template_arg_num = 4 if self.kind == "map" else 3
+        allocator_type = type.GetTemplateArgumentType(template_arg_num)
+        data_type = allocator_type.GetTemplateArgumentType(0)
+        return data_type
+
+    def update(self): 
+        # preemptively setting this to None - we might end up changing our mind
+        # later
+        self.count = None
+        try:
+            self.head = self.valobj.GetChildMemberWithName('_M_h')
+            self.before_begin = self.head.GetChildMemberWithName('_M_before_begin')
+            self.next = self.before_begin.GetChildMemberWithName('_M_nxt')
+            self.data_type = self.extract_type()
+            self.skip_size = self.next.GetType().GetByteSize()
+            self.data_size = self.data_type.GetByteSize()
+        except:
+            pass
+        return False
+
+    def get_child_index(self, name):
+        try:
+            return int(name.lstrip('[').rstrip(']'))
+        except:
+            return -1
+
+    def get_child_at_index(self, index):
+        logger = lldb.formatters.Logger.Logger()
+        logger >> "Being asked to fetch child[" + str(index) + "]"
+        if index < 0:
+            return None
+        if index >= self.num_children():
+            return None
+        try:
+            offset = index
+            current = self.next     
+            while offset > 0:
+                current = current.GetChildMemberWithName('_M_nxt')
+                offset = offset - 1
+            return current.CreateChildAtOffset( '[' + str(index) + ']', self.skip_size, self.data_type)
+        
+        except:
+            logger >> "Cannot get child"
+            return None
+
+    def num_children(self):
+        if self.count is None:
+            self.count = self.num_children_impl()
+        return self.count
+
+    def num_children_impl(self):
+        logger = lldb.formatters.Logger.Logger()
+        try:
+            count = self.head.GetChildMemberWithName('_M_element_count').GetValueAsUnsigned(0)
+            logger >> "I have " + str(count) + " children available"
+            return count
+        except:
+            logger >> "Could not determine the size"
+            return 0
 
 
 class StdListSynthProvider:
_______________________________________________
lldb-commits mailing list
lldb-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits

Reply via email to