danilashtefan created this revision.
danilashtefan requested review of this revision.
Herald added a project: LLDB.
Herald added a subscriber: lldb-commits.
Repository:
rG LLVM Github Monorepo
https://reviews.llvm.org/D113362
Files:
lldb/examples/synthetic/gnu_libstdcpp.py
lldb/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.cpp
lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic/forward_list/Makefile
lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic/forward_list/TestDataFormatterStdForwardList.py
lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic/forward_list/main.cpp
Index: lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic/forward_list/main.cpp
===================================================================
--- /dev/null
+++ lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic/forward_list/main.cpp
@@ -0,0 +1,7 @@
+#include <forward_list>
+
+int main() {
+ std::forward_list<int> empty{}, one_elt{47},
+ five_elts{1, 22, 333, 4444, 55555};
+ return 0; // break here
+}
Index: lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic/forward_list/TestDataFormatterStdForwardList.py
===================================================================
--- /dev/null
+++ lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic/forward_list/TestDataFormatterStdForwardList.py
@@ -0,0 +1,51 @@
+"""
+Test lldb data formatter subsystem.
+"""
+
+
+
+import lldb
+from lldbsuite.test.decorators import *
+from lldbsuite.test.lldbtest import *
+from lldbsuite.test import lldbutil
+
+
+class TestDataFormatterLibcxxForwardList(TestBase):
+
+ mydir = TestBase.compute_mydir(__file__)
+
+ def setUp(self):
+ TestBase.setUp(self)
+ self.line = line_number('main.cpp', '// break here')
+ self.namespace = 'std'
+
+ @add_test_categories(["libstdcxx"])
+ def test(self):
+ """Test that std::forward_list is displayed correctly"""
+ self.build()
+ lldbutil.run_to_source_breakpoint(self, '// break here',
+ lldb.SBFileSpec("main.cpp", False))
+
+ forward_list = self.namespace + '::forward_list'
+ self.expect("frame variable empty",
+ substrs=[forward_list,
+ 'size=0',
+ '{}'])
+
+ self.expect("frame variable one_elt",
+ substrs=[forward_list,
+ 'size=1',
+ '{',
+ '[0] = 47',
+ '}'])
+
+ self.expect("frame variable five_elts",
+ substrs=[forward_list,
+ 'size=5',
+ '{',
+ '[0] = 1',
+ '[1] = 22',
+ '[2] = 333',
+ '[3] = 4444',
+ '[4] = 55555',
+ '}'])
Index: lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic/forward_list/Makefile
===================================================================
--- /dev/null
+++ lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic/forward_list/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
@@ -923,6 +923,11 @@
SyntheticChildrenSP(new ScriptedSyntheticChildren(
stl_synth_flags,
"lldb.formatters.cpp.gnu_libstdcpp.StdListSynthProvider")));
+ cpp_category_sp->GetRegexTypeSyntheticsContainer()->Add(
+ RegularExpression("^std::(__cxx11::)?forward_list<.+>(( )?&)?$"),
+ SyntheticChildrenSP(new ScriptedSyntheticChildren(
+ stl_synth_flags,
+ "lldb.formatters.cpp.gnu_libstdcpp.StdForwardListSynthProvider")));
stl_summary_flags.SetDontShowChildren(false);
stl_summary_flags.SetSkipPointers(false);
cpp_category_sp->GetRegexTypeSummariesContainer()->Add(
@@ -953,6 +958,10 @@
RegularExpression("^std::(__cxx11::)?list<.+>(( )?&)?$"),
TypeSummaryImplSP(
new StringSummaryFormat(stl_summary_flags, "size=${svar%#}")));
+ cpp_category_sp->GetRegexTypeSummariesContainer()->Add(
+ RegularExpression("^std::(__cxx11::)?forward_list<.+>(( )?&)?$"),
+ TypeSummaryImplSP(
+ new StringSummaryFormat(stl_summary_flags, "size=${svar%#}")));
AddCXXSynthetic(
cpp_category_sp,
Index: lldb/examples/synthetic/gnu_libstdcpp.py
===================================================================
--- lldb/examples/synthetic/gnu_libstdcpp.py
+++ lldb/examples/synthetic/gnu_libstdcpp.py
@@ -2,15 +2,15 @@
import re
import lldb.formatters.Logger
+FORWARD_LIST = "FORWARD_LIST"
+LIST = "LIST"
+
# C++ STL formatters for LLDB
# These formatters are based upon the version of the GNU libstdc++
# 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 StdListSynthProvider:
-
+class AbstractListSynthProvider:
def __init__(self, valobj, dict):
logger = lldb.formatters.Logger.Logger()
self.valobj = valobj
@@ -18,29 +18,27 @@
logger >> "Providing synthetic children for a list named " + \
str(valobj.GetName())
- def next_node(self, node):
+ def next_node_abstract(self, node):
logger = lldb.formatters.Logger.Logger()
return node.GetChildMemberWithName('_M_next')
- def is_valid(self, node):
+ def is_valid_abstract(self, node, break_condition):
logger = lldb.formatters.Logger.Logger()
- valid = self.value(self.next_node(node)) != self.node_address
+ valid = self.value_abstract(self.next_node_abstract(node)) != break_condition
if valid:
logger >> "%s is valid" % str(self.valobj.GetName())
else:
logger >> "synthetic value is not valid"
return valid
-
- def value(self, node):
+
+ def value_abstract(self, node):
logger = lldb.formatters.Logger.Logger()
value = node.GetValueAsUnsigned()
logger >> "synthetic value for {}: {}".format(
str(self.valobj.GetName()), value)
return value
- # Floyd's cycle-finding algorithm
- # try to detect if this list has a loop
- def has_loop(self):
+ def has_loop_abstract(self, is_valid_break_condition):
global _list_uses_loop_detector
logger = lldb.formatters.Logger.Logger()
if not _list_uses_loop_detector:
@@ -49,17 +47,17 @@
slow = self.next
fast1 = self.next
fast2 = self.next
- while self.is_valid(slow):
- slow_value = self.value(slow)
- fast1 = self.next_node(fast2)
- fast2 = self.next_node(fast1)
- if self.value(fast1) == slow_value or self.value(
+ while self.is_valid_abstract(slow, is_valid_break_condition):
+ slow_value = self.value_abstract(slow)
+ fast1 = self.next_node_abstract(fast2)
+ fast2 = self.next_node_abstract(fast1)
+ if self.value_abstract(fast1) == slow_value or self.value_abstract(
fast2) == slow_value:
return True
- slow = self.next_node(slow)
+ slow = self.next_node_abstract(slow)
return False
- def num_children(self):
+ def num_children_abstract(self, incoming_size, size_correction, is_valid_break_condition, type):
logger = lldb.formatters.Logger.Logger()
if self.count is None:
# libstdc++ 6.0.21 added dedicated count field.
@@ -67,42 +65,46 @@
if count_child and count_child.IsValid():
self.count = count_child.GetValueAsUnsigned(0)
if self.count is None:
- self.count = self.num_children_impl()
- return self.count
+ self.count = self.num_children_impl_abstract(incoming_size,size_correction, is_valid_break_condition, type)
+ return self.count
- def num_children_impl(self):
+ def num_children_impl_abstract(self, incoming_size, size_correction, is_valid_break_condition, type):
logger = lldb.formatters.Logger.Logger()
try:
- next_val = self.next.GetValueAsUnsigned(0)
- prev_val = self.prev.GetValueAsUnsigned(0)
# After a std::list has been initialized, both next and prev will
# be non-NULL
- if next_val == 0 or prev_val == 0:
- return 0
- if next_val == self.node_address:
+ next_val = self.next.GetValueAsUnsigned(0)
+ if next_val == 0:
return 0
- if next_val == prev_val:
- return 1
- if self.has_loop():
+ if self.has_loop_abstract(is_valid_break_condition):
return 0
- size = 2
+ if type == LIST:
+ prev_val = self.prev.GetValueAsUnsigned(0)
+ if prev_val == 0:
+ return 0
+ if next_val == self.node_address:
+ return 0
+ if next_val == prev_val:
+ return 1
+ size = incoming_size
current = self.next
while current.GetChildMemberWithName(
- '_M_next').GetValueAsUnsigned(0) != self.node_address:
+ '_M_next').GetValueAsUnsigned(0) != is_valid_break_condition:
size = size + 1
current = current.GetChildMemberWithName('_M_next')
- return (size - 1)
+ return (size - size_correction)
except:
- return 0
+ logger >> "Error determining the size"
+ return 0
- def get_child_index(self, name):
+ def get_child_index_abstract(self, name):
logger = lldb.formatters.Logger.Logger()
try:
return int(name.lstrip('[').rstrip(']'))
except:
return -1
-
- def get_child_at_index(self, index):
+
+ def get_child_at_index_abstract(self, index, multiplier):
logger = lldb.formatters.Logger.Logger()
logger >> "Fetching child " + str(index)
if index < 0:
@@ -117,12 +119,12 @@
offset = offset - 1
return current.CreateChildAtOffset(
'[' + str(index) + ']',
- 2 * current.GetType().GetByteSize(),
+ multiplier * current.GetType().GetByteSize(),
self.data_type)
except:
return None
- def extract_type(self):
+ def extract_type_abstract(self):
logger = lldb.formatters.Logger.Logger()
list_type = self.valobj.GetType().GetUnqualifiedType()
if list_type.IsReferenceType():
@@ -133,27 +135,65 @@
data_type = None
return data_type
- def update(self):
+ def update_abstract(self):
logger = lldb.formatters.Logger.Logger()
# preemptively setting this to None - we might end up changing our mind
# later
self.count = None
try:
- impl = self.valobj.GetChildMemberWithName('_M_impl')
- self.node = impl.GetChildMemberWithName('_M_node')
- self.node_address = self.valobj.AddressOf().GetValueAsUnsigned(0)
- self.next = self.node.GetChildMemberWithName('_M_next')
- self.prev = self.node.GetChildMemberWithName('_M_prev')
- self.data_type = self.extract_type()
+ self.impl = self.valobj.GetChildMemberWithName('_M_impl')
+ self.data_type = self.extract_type_abstract()
self.data_size = self.data_type.GetByteSize()
except:
pass
return False
- def has_children(self):
+ def has_children_abstract(self):
return True
+class StdForwardListSynthProvider(AbstractListSynthProvider):
+
+ def __init__(self, valobj, dict):
+ super().__init__(valobj, dict)
+
+ def num_children(self):
+ return super().num_children_abstract(incoming_size=1, size_correction=0, is_valid_break_condition=0, type=FORWARD_LIST)
+
+
+ def get_child_at_index(self, index):
+ return super().get_child_at_index_abstract(index=index,multiplier=1)
+
+ def extract_type(self):
+ return super().extract_type_abstract()
+
+ def update(self):
+ super().update_abstract()
+ self.node = self.impl.GetChildMemberWithName('_M_head')
+ self.next = self.node.GetChildMemberWithName('_M_next')
+ return False
+
+
+class StdListSynthProvider(AbstractListSynthProvider):
+
+ def __init__(self, valobj, dict):
+ super().__init__(valobj, dict)
+
+ def num_children(self):
+ return super().num_children_abstract(incoming_size=2, size_correction=1, is_valid_break_condition=self.node_address, type=LIST)
+
+ def get_child_at_index(self, index):
+ return super().get_child_at_index_abstract(index=index,multiplier=2)
+
+ def update(self):
+ self.update_abstract()
+ self.node_address = self.valobj.AddressOf().GetValueAsUnsigned(0)
+ self.node = self.impl.GetChildMemberWithName('_M_node')
+ self.prev = self.node.GetChildMemberWithName('_M_prev')
+ self.next = self.node.GetChildMemberWithName('_M_next')
+ return False
+
+
class StdVectorSynthProvider:
class StdVectorImplementation(object):
_______________________________________________
lldb-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits