[Lldb-commits] [lldb] fcd288b - [formatters] Add a libstdcpp formatter for for unordered_map, unordered_set, unordered_multimap, unordered_multiset

Walter Erquinigo via lldb-commits lldb-commits at lists.llvm.org
Mon Nov 22 13:08:47 PST 2021


Author: Danil Stefaniuc
Date: 2021-11-22T13:08:36-08:00
New Revision: fcd288b52aa708e061ad633c8efa1183a7e6b926

URL: https://github.com/llvm/llvm-project/commit/fcd288b52aa708e061ad633c8efa1183a7e6b926
DIFF: https://github.com/llvm/llvm-project/commit/fcd288b52aa708e061ad633c8efa1183a7e6b926.diff

LOG: [formatters] Add a libstdcpp formatter for  for unordered_map, unordered_set, unordered_multimap, unordered_multiset

This diff adds a data formatter and tests for libstdcpp's unordered_map, unordered_set, unordered_multimap, unordered_multiset

Reviewed By: wallace

Differential Revision: https://reviews.llvm.org/D113760

Added: 
    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

Modified: 
    lldb/examples/synthetic/gnu_libstdcpp.py
    lldb/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.cpp

Removed: 
    lldb/test/API/functionalities/data-formatter/data-formatter-stl/libcxx/unordered/Makefile
    lldb/test/API/functionalities/data-formatter/data-formatter-stl/libcxx/unordered/TestDataFormatterUnordered.py
    lldb/test/API/functionalities/data-formatter/data-formatter-stl/libcxx/unordered/main.cpp


################################################################################
diff  --git a/lldb/examples/synthetic/gnu_libstdcpp.py b/lldb/examples/synthetic/gnu_libstdcpp.py
index a5b24273489f2..9272b814f78d8 100644
--- a/lldb/examples/synthetic/gnu_libstdcpp.py
+++ b/lldb/examples/synthetic/gnu_libstdcpp.py
@@ -9,6 +9,86 @@
 # before relying on these formatters to do the right thing for your setup
 
 
+"""
+ This formatter can be applied to all
+ unordered map-like structures (unordered_map, unordered_multimap, unordered_set, unordered_multiset)
+"""
+class StdUnorderedMapSynthProvider:
+    def __init__(self, valobj, dict):
+        self.valobj = valobj
+        self.count = None
+        self.kind = self.get_object_kind(valobj)
+
+    def get_object_kind(self, valobj):
+        type_name = valobj.GetTypeName()
+        return "set" if "set" in type_name else "map"
+
+    def extract_type(self):
+        type = self.valobj.GetType()
+        # 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
+        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)
+            return count
+        except:
+            logger >> "Could not determine the size"
+            return 0
+
+
 class AbstractListSynthProvider:
     def __init__(self, valobj, dict, has_prev):
         '''

diff  --git a/lldb/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.cpp b/lldb/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.cpp
index 83e8e52b86f26..3182294abd448 100644
--- a/lldb/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.cpp
+++ b/lldb/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.cpp
@@ -918,6 +918,11 @@ static void LoadLibStdcppFormatters(lldb::TypeCategoryImplSP cpp_category_sp) {
       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(
@@ -954,6 +959,10 @@ static void LoadLibStdcppFormatters(lldb::TypeCategoryImplSP cpp_category_sp) {
       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(

diff  --git a/lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic/unordered/Makefile b/lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic/unordered/Makefile
new file mode 100644
index 0000000000000..99998b20bcb05
--- /dev/null
+++ b/lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic/unordered/Makefile
@@ -0,0 +1,3 @@
+CXX_SOURCES := main.cpp
+
+include Makefile.rules

diff  --git a/lldb/test/API/functionalities/data-formatter/data-formatter-stl/libcxx/unordered/TestDataFormatterUnordered.py b/lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic/unordered/TestDataFormatterGenericUnordered.py
similarity index 85%
rename from lldb/test/API/functionalities/data-formatter/data-formatter-stl/libcxx/unordered/TestDataFormatterUnordered.py
rename to lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic/unordered/TestDataFormatterGenericUnordered.py
index 3519daec6ec41..664ff69211292 100644
--- a/lldb/test/API/functionalities/data-formatter/data-formatter-stl/libcxx/unordered/TestDataFormatterUnordered.py
+++ b/lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic/unordered/TestDataFormatterGenericUnordered.py
@@ -9,18 +9,19 @@
 from lldbsuite.test.lldbtest import *
 from lldbsuite.test import lldbutil
 
+USE_LIBSTDCPP = "USE_LIBSTDCPP"
+USE_LIBCPP = "USE_LIBCPP"
 
-class LibcxxUnorderedDataFormatterTestCase(TestBase):
-
+class GenericUnorderedDataFormatterTestCase(TestBase):
     mydir = TestBase.compute_mydir(__file__)
 
     def setUp(self):
         TestBase.setUp(self)
         self.namespace = 'std'
 
-    @add_test_categories(["libc++"])
-    def test_with_run_command(self):
-        self.build()
+
+    def do_test_with_run_command(self, stdlib_type):
+        self.build(dictionary={stdlib_type: "1"})
         self.runCmd("file " + self.getBuildArtifact("a.out"), CURRENT_EXECUTABLE_SET)
 
         lldbutil.run_break_set_by_source_regexp(
@@ -76,3 +77,11 @@ 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")
+
+    @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)
\ No newline at end of file

diff  --git a/lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic/unordered/main.cpp b/lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic/unordered/main.cpp
new file mode 100644
index 0000000000000..36ebefcd747bc
--- /dev/null
+++ b/lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic/unordered/main.cpp
@@ -0,0 +1,68 @@
+#include <string>
+#include <unordered_map>
+#include <unordered_set>
+
+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() {
+  std::unordered_map<int, std::string> 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.
+
+  std::unordered_multimap<int, std::string> 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.
+
+  std::unordered_set<int> iset;
+  iset.emplace(1);
+  iset.emplace(2);
+  iset.emplace(3);
+  iset.emplace(4);
+  iset.emplace(5);
+  thefoo_rw(); // Set break point at this line.
+
+  std::unordered_set<std::string> sset;
+  sset.emplace("hello");
+  sset.emplace("world");
+  sset.emplace("this");
+  sset.emplace("is");
+  sset.emplace("me");
+  thefoo_rw(); // Set break point at this line.
+
+  std::unordered_multiset<int> 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.
+
+  std::unordered_multiset<std::string> 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;
+}

diff  --git a/lldb/test/API/functionalities/data-formatter/data-formatter-stl/libcxx/unordered/Makefile b/lldb/test/API/functionalities/data-formatter/data-formatter-stl/libcxx/unordered/Makefile
deleted file mode 100644
index 913a52fb191c1..0000000000000
--- a/lldb/test/API/functionalities/data-formatter/data-formatter-stl/libcxx/unordered/Makefile
+++ /dev/null
@@ -1,9 +0,0 @@
-CXX_SOURCES := main.cpp
-
-# Work around "exception specification in declaration does not match previous
-# declaration" errors present in older libc++ releases. This error was fixed in
-# the 3.8 release.
-CFLAGS_EXTRAS := -fno-exceptions
-
-USE_LIBCPP := 1
-include Makefile.rules

diff  --git a/lldb/test/API/functionalities/data-formatter/data-formatter-stl/libcxx/unordered/main.cpp b/lldb/test/API/functionalities/data-formatter/data-formatter-stl/libcxx/unordered/main.cpp
deleted file mode 100644
index 81a5763559d31..0000000000000
--- a/lldb/test/API/functionalities/data-formatter/data-formatter-stl/libcxx/unordered/main.cpp
+++ /dev/null
@@ -1,80 +0,0 @@
-#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;
-}


        


More information about the lldb-commits mailing list