import lldb.formatters.Logger
# 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
+# As there are many versions of the libcstd++, 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
def StdOptionalSummaryProvider(valobj, dict):
has_value = valobj.GetNumChildren() > 0
self.data_type = self.extract_type()
self.skip_size = self.next.GetType().GetByteSize()
self.data_size = self.data_type.GetByteSize()
+ if (not self.data_type.IsValid()) or (not self.next.IsValid()):
+ self.count = 0
except:
- pass
+ self.count = 0
return False
def get_child_index(self, name):
current = self.next
while current.GetChildMemberWithName(
'_M_next').GetValueAsUnsigned(0) != self.get_end_of_list_address():
- size = size + 1
current = current.GetChildMemberWithName('_M_next')
+ if not current.IsValid():
+ break
+ size = size + 1
+
return size
except:
logger >> "Error determining the size"
if list_type.IsReferenceType():
list_type = list_type.GetDereferencedType()
if list_type.GetNumberOfTemplateArguments() > 0:
- data_type = list_type.GetTemplateArgumentType(0)
- else:
- data_type = None
- return data_type
+ return list_type.GetTemplateArgumentType(0)
+ return lldb.SBType()
def update(self):
logger = lldb.formatters.Logger.Logger()
try:
self.impl = self.valobj.GetChildMemberWithName('_M_impl')
self.data_type = self.extract_type()
- self.data_size = self.data_type.GetByteSize()
- self.updateNodes()
+ if (not self.data_type.IsValid()) or (not self.impl.IsValid()):
+ self.count = 0
+ elif not self.updateNodes():
+ self.count = 0
+ else:
+ self.data_size = self.data_type.GetByteSize()
except:
- pass
+ self.count = 0
return False
'''
Method is used to extract the list pointers into the variables (e.g self.node, self.next, and optionally to self.prev)
- and is mandatory to be overriden in each AbstractListSynthProvider subclass
+ and is mandatory to be overriden in each AbstractListSynthProvider subclass.
+ This should return True or False depending on wheter it found valid data.
'''
def updateNodes(self):
raise NotImplementedError
def updateNodes(self):
self.node = self.impl.GetChildMemberWithName('_M_head')
self.next = self.node.GetChildMemberWithName('_M_next')
+ if (not self.node.IsValid()) or (not self.next.IsValid()):
+ return False
+ return True
def get_end_of_list_address(self):
return 0
self.node = self.impl.GetChildMemberWithName('_M_node')
self.prev = self.node.GetChildMemberWithName('_M_prev')
self.next = self.node.GetChildMemberWithName('_M_next')
+ if self.node_address == 0 or (not self.node.IsValid()) or (not self.next.IsValid()) or (not self.prev.IsValid()):
+ return False
+ return True
def get_end_of_list_address(self):
return self.node_address
else:
self.count = 0
except:
- pass
+ self.count = 0
return False
class StdVBoolImplementation(object):
self.start_p = self.m_start.GetChildMemberWithName('_M_p')
self.finish_p = self.m_finish.GetChildMemberWithName('_M_p')
self.offset = self.m_finish.GetChildMemberWithName('_M_offset')
- self.valid = True
+ if self.offset.IsValid() and self.start_p.IsValid() and self.finish_p.IsValid():
+ self.valid = True
+ else:
+ self.valid = False
except:
self.valid = False
return False
self.Mt = self.valobj.GetChildMemberWithName('_M_t')
self.Mimpl = self.Mt.GetChildMemberWithName('_M_impl')
self.Mheader = self.Mimpl.GetChildMemberWithName('_M_header')
-
- map_type = self.valobj.GetType()
- if map_type.IsReferenceType():
- logger >> "Dereferencing type"
- map_type = map_type.GetDereferencedType()
-
- # Get the type of std::pair<key, value>. It is the first template
- # argument type of the 4th template argument to std::map.
- allocator_type = map_type.GetTemplateArgumentType(3)
- self.data_type = allocator_type.GetTemplateArgumentType(0)
- if not self.data_type:
- # GCC does not emit DW_TAG_template_type_parameter for
- # std::allocator<...>. For such a case, get the type of
- # std::pair from a member of std::map.
- rep_type = self.valobj.GetChildMemberWithName('_M_t').GetType()
- self.data_type = rep_type.GetTypedefedType().GetTemplateArgumentType(1)
-
- # from libstdc++ implementation of _M_root for rbtree
- self.Mroot = self.Mheader.GetChildMemberWithName('_M_parent')
- self.data_size = self.data_type.GetByteSize()
- self.skip_size = self.Mheader.GetType().GetByteSize()
+ if not self.Mheader.IsValid():
+ self.count = 0
+ else:
+ map_type = self.valobj.GetType()
+ if map_type.IsReferenceType():
+ logger >> "Dereferencing type"
+ map_type = map_type.GetDereferencedType()
+
+ # Get the type of std::pair<key, value>. It is the first template
+ # argument type of the 4th template argument to std::map.
+ allocator_type = map_type.GetTemplateArgumentType(3)
+ self.data_type = allocator_type.GetTemplateArgumentType(0)
+ if not self.data_type:
+ # GCC does not emit DW_TAG_template_type_parameter for
+ # std::allocator<...>. For such a case, get the type of
+ # std::pair from a member of std::map.
+ rep_type = self.valobj.GetChildMemberWithName('_M_t').GetType()
+ self.data_type = rep_type.GetTypedefedType().GetTemplateArgumentType(1)
+
+ # from libstdc++ implementation of _M_root for rbtree
+ self.Mroot = self.Mheader.GetChildMemberWithName('_M_parent')
+ self.data_size = self.data_type.GetByteSize()
+ self.skip_size = self.Mheader.GetType().GetByteSize()
except:
- pass
+ self.count = 0
return False
def num_children(self):
def setUp(self):
TestBase.setUp(self)
self.namespace = 'std'
-
+
def findVariable(self, name):
var = self.frame().FindVariable(name)
self.assertTrue(var.IsValid())
self.addTearDownHook(cleanup)
multimap = self.namespace + "::multimap"
+
+ self.expect('frame variable ii',
+ substrs=[multimap, 'size=0',
+ '{}'])
+
+ self.expect('frame variable si',
+ substrs=[multimap, 'size=0',
+ '{}'])
+
+ lldbutil.continue_to_breakpoint(self.process(), bkpt)
+
self.expect('frame variable ii',
substrs=[multimap, 'size=0',
'{}'])
'[0] = (first = 0, second = 0)',
'[1] = (first = 1, second = 1)',
])
-
+
self.check("ii", 2)
lldbutil.continue_to_breakpoint(self.process(), bkpt)
'[3] = ',
'first = 3',
'second = 1'])
-
+
self.check("ii", 4)
lldbutil.continue_to_breakpoint(self.process(), bkpt)
@add_test_categories(["libc++"])
def test_with_run_command_libcpp(self):
self.do_test_with_run_command(USE_LIBCPP)
-
#include <string>
#include <map>
-#define intint_map std::multimap<int, int>
-#define strint_map std::multimap<std::string, int>
-#define intstr_map std::multimap<int, std::string>
-#define strstr_map std::multimap<std::string, std::string>
+#define intint_map std::multimap<int, int>
+#define strint_map std::multimap<std::string, int>
+#define intstr_map std::multimap<int, std::string>
+#define strstr_map std::multimap<std::string, std::string>
int g_the_foo = 0;
return g_the_foo;
}
-int main()
+int main() // Set break point at this line.
{
intint_map ii;
-
+
ii.emplace(0,0); // Set break point at this line.
ii.emplace(1,1);
thefoo_rw(1); // Set break point at this line.
ii.emplace(85,1234567);
ii.clear();
-
+
strint_map si;
thefoo_rw(1); // Set break point at this line.
-
+
si.emplace("zero",0);
thefoo_rw(1); // Set break point at this line.
si.emplace("one",1);
si.clear();
thefoo_rw(1); // Set break point at this line.
-
+
intstr_map is;
thefoo_rw(1); // Set break point at this line.
is.emplace(85,"goofy");
is.emplace(2,"smart");
is.emplace(3,"!!!");
thefoo_rw(1); // Set break point at this line.
-
+
is.clear();
thefoo_rw(1); // Set break point at this line.
-
+
strstr_map ss;
thefoo_rw(1); // Set break point at this line.
-
+
ss.emplace("ciao","hello");
ss.emplace("casa","house");
ss.emplace("gatto","cat");
thefoo_rw(1); // Set break point at this line.
ss.emplace("a Mac..","..is always a Mac!");
-
+
ss.clear();
- thefoo_rw(1); // Set break point at this line.
+ thefoo_rw(1); // Set break point at this line.
return 0;
}