[Lldb-commits] [lldb] r152570 - in /lldb/trunk: examples/synthetic/ include/lldb/Core/ scripts/Python/ source/Core/ source/Interpreter/ test/functionalities/data-formatter/data-formatter-stl/libcxx/ test/functionalities/data-formatter/data-formatter-stl/libcxx/list/ test/functionalities/data-formatter/data-formatter-stl/libcxx/map/ test/functionalities/data-formatter/data-formatter-stl/libcxx/vector/ test/functionalities/data-formatter/data-formatter-stl/libstdcpp/ test/functionalities/data-formatter/data-formatter-stl...
Enrico Granata
egranata at apple.com
Mon Mar 12 12:47:17 PDT 2012
Author: enrico
Date: Mon Mar 12 14:47:17 2012
New Revision: 152570
URL: http://llvm.org/viewvc/llvm-project?rev=152570&view=rev
Log:
Added formatters for libc++ (http://libcxx.llvm.org):
std::string has a summary provider
std::vector std::list and std::map have both a summary and a synthetic children provider
Given the usage of a custom namespace (std::__1::classname) for the implementation of libc++, we keep both libstdcpp and libc++ formatters enabled at the same time since that raises no conflicts and enabled for seamless transition between the two
The formatters for libc++ reside in a libcxx category, and are loaded from libcxx.py (to be found in examples/synthetic)
The formatters-stl test cases have been divided to be separate for libcxx and libstdcpp. This separation is necessary because
(a) we need different compiler flags for libc++ than for libstdcpp
(b) libc++ inlines a lot more than libstdcpp and some code changes were required to accommodate this difference
Added:
lldb/trunk/examples/synthetic/libcxx.py
lldb/trunk/test/functionalities/data-formatter/data-formatter-stl/libcxx/
lldb/trunk/test/functionalities/data-formatter/data-formatter-stl/libcxx/list/
lldb/trunk/test/functionalities/data-formatter/data-formatter-stl/libcxx/list/Makefile
lldb/trunk/test/functionalities/data-formatter/data-formatter-stl/libcxx/list/TestDataFormatterLibcxxList.py
lldb/trunk/test/functionalities/data-formatter/data-formatter-stl/libcxx/list/main.cpp
lldb/trunk/test/functionalities/data-formatter/data-formatter-stl/libcxx/map/
lldb/trunk/test/functionalities/data-formatter/data-formatter-stl/libcxx/map/Makefile
lldb/trunk/test/functionalities/data-formatter/data-formatter-stl/libcxx/map/TestDataFormatterLibccMap.py
lldb/trunk/test/functionalities/data-formatter/data-formatter-stl/libcxx/map/main.cpp
lldb/trunk/test/functionalities/data-formatter/data-formatter-stl/libcxx/vector/
lldb/trunk/test/functionalities/data-formatter/data-formatter-stl/libcxx/vector/Makefile
lldb/trunk/test/functionalities/data-formatter/data-formatter-stl/libcxx/vector/TestDataFormatterLibcxxVector.py
lldb/trunk/test/functionalities/data-formatter/data-formatter-stl/libcxx/vector/main.cpp
lldb/trunk/test/functionalities/data-formatter/data-formatter-stl/libstdcpp/
lldb/trunk/test/functionalities/data-formatter/data-formatter-stl/libstdcpp/list/
- copied from r152325, lldb/trunk/test/functionalities/data-formatter/data-formatter-stl/list/
lldb/trunk/test/functionalities/data-formatter/data-formatter-stl/libstdcpp/map/
- copied from r152325, lldb/trunk/test/functionalities/data-formatter/data-formatter-stl/map/
lldb/trunk/test/functionalities/data-formatter/data-formatter-stl/libstdcpp/vector/
- copied from r152325, lldb/trunk/test/functionalities/data-formatter/data-formatter-stl/vector/
Removed:
lldb/trunk/test/functionalities/data-formatter/data-formatter-stl/list/
lldb/trunk/test/functionalities/data-formatter/data-formatter-stl/map/
lldb/trunk/test/functionalities/data-formatter/data-formatter-stl/vector/
Modified:
lldb/trunk/include/lldb/Core/FormatManager.h
lldb/trunk/scripts/Python/finish-swig-Python-LLDB.sh
lldb/trunk/source/Core/FormatManager.cpp
lldb/trunk/source/Interpreter/ScriptInterpreterPython.cpp
lldb/trunk/test/functionalities/data-formatter/data-formatter-stl/libstdcpp/list/Makefile
lldb/trunk/test/functionalities/data-formatter/data-formatter-stl/libstdcpp/list/TestDataFormatterStdList.py
lldb/trunk/test/functionalities/data-formatter/data-formatter-stl/libstdcpp/map/Makefile
lldb/trunk/test/functionalities/data-formatter/data-formatter-stl/libstdcpp/map/TestDataFormatterStdMap.py
lldb/trunk/test/functionalities/data-formatter/data-formatter-stl/libstdcpp/vector/Makefile
lldb/trunk/test/functionalities/data-formatter/data-formatter-stl/libstdcpp/vector/TestDataFormatterStdVector.py
Added: lldb/trunk/examples/synthetic/libcxx.py
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/examples/synthetic/libcxx.py?rev=152570&view=auto
==============================================================================
--- lldb/trunk/examples/synthetic/libcxx.py (added)
+++ lldb/trunk/examples/synthetic/libcxx.py Mon Mar 12 14:47:17 2012
@@ -0,0 +1,481 @@
+import lldb
+
+# libcxx STL formatters for LLDB
+# These formatters are based upon the implementation of libc++ that
+# ships with current releases of OS X - They will not work for other implementations
+# of the standard C++ library - and they are bound to use the libc++-specific namespace
+
+# this could probably be made more efficient but since it only reads a handful of bytes at a time
+# we probably don't need to worry too much about this for the time being
+def make_string(F,L):
+ strval = ''
+ G = F.GetData().uint8
+ for X in range(L):
+ V = G[X]
+ if V == 0:
+ break
+ strval = strval + chr(V % 256)
+ return '"' + strval + '"'
+
+# if we ever care about big-endian, these two functions might need to change
+def is_short_string(value):
+ return True if (value & 1) == 0 else False
+def extract_short_size(value):
+ return ((value >> 1) % 256)
+
+# some of the members of libc++ std::string are anonymous or have internal names that convey
+# no external significance - we access them by index since this saves a name lookup that would add
+# no information for readers of the code, but when possible try to use meaningful variable names
+def stdstring_SummaryProvider(valobj,dict):
+ r = valobj.GetChildAtIndex(0)
+ B = r.GetChildAtIndex(0)
+ first = B.GetChildAtIndex(0)
+ D = first.GetChildAtIndex(0)
+ l = D.GetChildAtIndex(0)
+ s = D.GetChildAtIndex(1)
+ D20 = s.GetChildAtIndex(0)
+ size_mode = D20.GetChildAtIndex(0).GetValueAsUnsigned(0)
+ if is_short_string(size_mode):
+ size = extract_short_size(size_mode)
+ return make_string(s.GetChildAtIndex(1),size)
+ else:
+ data_ptr = l.GetChildAtIndex(2)
+ size_vo = l.GetChildAtIndex(1)
+ size = size_vo.GetValueAsUnsigned(0)+1 # the NULL terminator must be accounted for
+ if size <= 1: # should never be the case
+ return '""'
+ data = data_ptr.GetPointeeData(0,size)
+ error = lldb.SBError()
+ strval = data.GetString(error,0)
+ if error.Fail():
+ return '<error:' + error.GetCString() + '>'
+ else:
+ return '"' + strval + '"'
+
+class stdvector_SynthProvider:
+
+ def __init__(self, valobj, dict):
+ self.valobj = valobj;
+ self.update()
+
+ def num_children(self):
+ try:
+ start_val = self.start.GetValueAsUnsigned(0)
+ finish_val = self.finish.GetValueAsUnsigned(0)
+ # Before a vector has been constructed, it will contain bad values
+ # so we really need to be careful about the length we return since
+ # unitialized data can cause us to return a huge number. We need
+ # to also check for any of the start, finish or end of storage values
+ # being zero (NULL). If any are, then this vector has not been
+ # initialized yet and we should return zero
+
+ # Make sure nothing is NULL
+ if start_val == 0 or finish_val == 0:
+ return 0
+ # Make sure start is less than finish
+ if start_val >= finish_val:
+ return 0
+
+ num_children = (finish_val-start_val)
+ if (num_children % self.data_size) != 0:
+ return 0
+ else:
+ num_children = num_children/self.data_size
+ return num_children
+ except:
+ return 0;
+
+ def get_child_index(self,name):
+ try:
+ return int(name.lstrip('[').rstrip(']'))
+ except:
+ return -1
+
+ def get_child_at_index(self,index):
+ if index < 0:
+ return None;
+ if index >= self.num_children():
+ return None;
+ try:
+ offset = index * self.data_size
+ return self.start.CreateChildAtOffset('['+str(index)+']',offset,self.data_type)
+ except:
+ return None
+
+ def update(self):
+ try:
+ self.start = self.valobj.GetChildMemberWithName('__begin_')
+ self.finish = self.valobj.GetChildMemberWithName('__end_')
+ # the purpose of this field is unclear, but it is the only field whose type is clearly T* for a vector<T>
+ # if this ends up not being correct, we can use the APIs to get at template arguments
+ data_type_finder = self.valobj.GetChildMemberWithName('__end_cap_').GetChildMemberWithName('__first_')
+ self.data_type = data_type_finder.GetType().GetPointeeType()
+ self.data_size = self.data_type.GetByteSize()
+ except:
+ pass
+
+def stdvector_SummaryProvider(valobj,dict):
+ prov = stdvector_SynthProvider(valobj,None)
+ return 'size=' + str(prov.num_children())
+
+class stdlist_entry:
+
+ def __init__(self,entry):
+ self.entry = entry
+
+ def _next_impl(self):
+ return stdlist_entry(self.entry.GetChildMemberWithName('__next_'))
+
+ def _prev_impl(self):
+ return stdlist_entry(self.entry.GetChildMemberWithName('__prev_'))
+
+ def _value_impl(self):
+ return self.entry.GetValueAsUnsigned(0)
+
+ def _isnull_impl(self):
+ return self._value_impl() == 0
+
+ def _sbvalue_impl(self):
+ return self.entry
+
+ next = property(_next_impl,None)
+ value = property(_value_impl,None)
+ is_null = property(_isnull_impl,None)
+ sbvalue = property(_sbvalue_impl,None)
+
+class stdlist_iterator:
+
+ def increment_node(self,node):
+ if node.is_null:
+ return None
+ return node.next
+
+ def __init__(self,node):
+ self.node = stdlist_entry(node) # we convert the SBValue to an internal node object on entry
+
+ def value(self):
+ return self.node.sbvalue # and return the SBValue back on exit
+
+ def next(self):
+ node = self.increment_node(self.node)
+ if node != None and node.sbvalue.IsValid() and not(node.is_null):
+ self.node = node
+ return self.value()
+ else:
+ return None
+
+ def advance(self,N):
+ if N < 0:
+ return None
+ if N == 0:
+ return self.value()
+ if N == 1:
+ return self.next()
+ while N > 0:
+ self.next()
+ N = N - 1
+ return self.value()
+
+
+class stdlist_SynthProvider:
+ def __init__(self, valobj, dict):
+ self.valobj = valobj
+ self.update()
+
+ def next_node(self,node):
+ return node.GetChildMemberWithName('__next_')
+
+ def value(self,node):
+ return node.GetValueAsUnsigned()
+
+ # Floyd's cyle-finding algorithm
+ # try to detect if this list has a loop
+ def has_loop(self):
+ slow = stdlist_entry(self.head)
+ fast1 = stdlist_entry(self.head)
+ fast2 = stdlist_entry(self.head)
+ while slow.next.value != self.node_address:
+ slow_value = slow.value
+ fast1 = fast2.next
+ fast2 = fast1.next
+ if fast1.value == slow_value or fast2.value == slow_value:
+ return True
+ slow = slow.next
+ return False
+
+ def num_children(self):
+ if self.count == None:
+ self.count = self.num_children_impl()
+ return self.count
+
+ def num_children_impl(self):
+ try:
+ next_val = self.head.GetValueAsUnsigned(0)
+ prev_val = self.tail.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:
+ return 0
+ if next_val == prev_val:
+ return 1
+ if self.has_loop():
+ return 0
+ size = 2
+ current = stdlist_entry(self.head)
+ while current.next.value != self.node_address:
+ size = size + 1
+ current = current.next
+ return (size - 1)
+ except:
+ return 0;
+
+ def get_child_index(self,name):
+ try:
+ return int(name.lstrip('[').rstrip(']'))
+ except:
+ return -1
+
+ def get_child_at_index(self,index):
+ if index < 0:
+ return None;
+ if index >= self.num_children():
+ return None;
+ try:
+ current = stdlist_iterator(self.head)
+ current = current.advance(index)
+ # we do not return __value_ because then all our children would be named __value_
+ # we need to make a copy of __value__ with the right name - unfortunate
+ obj = current.GetChildMemberWithName('__value_')
+ obj_data = obj.GetData()
+ return self.valobj.CreateValueFromData('[' + str(index) + ']',obj_data,self.data_type)
+ except:
+ return None
+
+ def extract_type(self):
+ list_type = self.valobj.GetType().GetUnqualifiedType()
+ if list_type.GetNumberOfTemplateArguments() > 0:
+ data_type = list_type.GetTemplateArgumentType(0)
+ else:
+ data_type = None
+ return data_type
+
+ def update(self):
+ try:
+ impl = self.valobj.GetChildMemberWithName('__end_')
+ self.node_address = self.valobj.AddressOf().GetValueAsUnsigned(0)
+ self.head = impl.GetChildMemberWithName('__next_')
+ self.tail = impl.GetChildMemberWithName('__prev_')
+ self.data_type = self.extract_type()
+ self.data_size = self.data_type.GetByteSize()
+ self.count = None
+ except:
+ pass
+
+def stdlist_SummaryProvider(valobj,dict):
+ prov = stdlist_SynthProvider(valobj,None)
+ return 'size=' + str(prov.num_children())
+
+# a tree node - this class makes the syntax in the actual iterator nicer to read and maintain
+class stdmap_iterator_node:
+ def _left_impl(self):
+ return stdmap_iterator_node(self.node.GetChildMemberWithName("__left_"))
+
+ def _right_impl(self):
+ return stdmap_iterator_node(self.node.GetChildMemberWithName("__right_"))
+
+ def _parent_impl(self):
+ return stdmap_iterator_node(self.node.GetChildMemberWithName("__parent_"))
+
+ def _value_impl(self):
+ return self.node.GetValueAsUnsigned(0)
+
+ def _sbvalue_impl(self):
+ return self.node
+
+ def _null_impl(self):
+ return self.value == 0
+
+ def __init__(self,node):
+ self.node = node
+
+ left = property(_left_impl,None)
+ right = property(_right_impl,None)
+ parent = property(_parent_impl,None)
+ value = property(_value_impl,None)
+ is_null = property(_null_impl,None)
+ sbvalue = property(_sbvalue_impl,None)
+
+# a Python implementation of the tree iterator used by libc++
+class stdmap_iterator:
+
+ def tree_min(self,x):
+ if x.is_null:
+ return None
+ while (not x.left.is_null):
+ x = x.left
+ return x
+
+ def tree_max(self,x):
+ if x.is_null:
+ return None
+ while (not x.right.is_null):
+ x = x.right
+ return x
+
+ def tree_is_left_child(self,x):
+ if x.is_null:
+ return None
+ return True if x.value == x.parent.left.value else False
+
+ def increment_node(self,node):
+ if node.is_null:
+ return None
+ if not node.right.is_null:
+ return self.tree_min(node.right)
+ while (not self.tree_is_left_child(node)):
+ node = node.parent
+ return node.parent
+
+ def __init__(self,node):
+ self.node = stdmap_iterator_node(node) # we convert the SBValue to an internal node object on entry
+
+ def value(self):
+ return self.node.sbvalue # and return the SBValue back on exit
+
+ def next(self):
+ node = self.increment_node(self.node)
+ if node != None and node.sbvalue.IsValid() and not(node.is_null):
+ self.node = node
+ return self.value()
+ else:
+ return None
+
+ def advance(self,N):
+ if N < 0:
+ return None
+ if N == 0:
+ return self.value()
+ if N == 1:
+ return self.next()
+ while N > 0:
+ self.next()
+ N = N - 1
+ return self.value()
+
+class stdmap_SynthProvider:
+
+ def __init__(self, valobj, dict):
+ self.valobj = valobj;
+ self.pointer_size = self.valobj.GetProcess().GetAddressByteSize()
+ self.update()
+
+ def update(self):
+ try:
+ self.tree = self.valobj.GetChildMemberWithName('__tree_')
+ self.root_node = self.tree.GetChildMemberWithName('__begin_node_')
+ # this data is either lazily-calculated, or cannot be inferred at this moment
+ # we still need to mark it as None, meaning "please set me ASAP"
+ self.data_type = None
+ self.data_size = None
+ self.skip_size = None
+ self.count = None
+ except:
+ pass
+
+ def num_children(self):
+ if self.count == None:
+ self.count = self.num_children_impl()
+ return self.count
+
+ def num_children_impl(self):
+ try:
+ return self.valobj.GetChildMemberWithName('__tree_').GetChildMemberWithName('__pair3_').GetChildMemberWithName('__first_').GetValueAsUnsigned()
+ except:
+ return 0;
+
+ def get_data_type(self):
+ if self.data_type == None or self.data_size == None:
+ if self.num_children() == 0:
+ return False
+ deref = self.root_node.Dereference()
+ if not(deref.IsValid()):
+ return False
+ value = deref.GetChildMemberWithName('__value_')
+ if not(value.IsValid()):
+ return False
+ self.data_type = value.GetType()
+ self.data_size = self.data_type.GetByteSize()
+ self.skip_size = None
+ return True
+ else:
+ return True
+
+ def get_value_offset(self,node):
+ if self.skip_size == None:
+ node_type = node.GetType()
+ fields_count = node_type.GetNumberOfFields()
+ for i in range(fields_count):
+ field = node_type.GetFieldAtIndex(i)
+ if field.GetName() == '__value_':
+ self.skip_size = field.GetOffsetInBytes()
+ break
+ return (self.skip_size != None)
+
+ def get_child_index(self,name):
+ try:
+ return int(name.lstrip('[').rstrip(']'))
+ except:
+ return -1
+
+ def get_child_at_index(self,index):
+ if index < 0:
+ return None
+ if index >= self.num_children():
+ return None;
+ try:
+ iterator = stdmap_iterator(self.root_node)
+ # the debug info for libc++ std::map is such that __begin_node_ has a very nice and useful type
+ # out of which we can grab the information we need - every other node has a less informative
+ # type which omits all value information and only contains housekeeping information for the RB tree
+ # hence, we need to know if we are at a node != 0, so that we can still get at the data
+ need_to_skip = (index > 0)
+ current = iterator.advance(index)
+ if self.get_data_type():
+ if not(need_to_skip):
+ current = current.Dereference()
+ obj = current.GetChildMemberWithName('__value_')
+ obj_data = obj.GetData()
+ self.get_value_offset(current) # make sure we have a valid offset for the next items
+ # we do not return __value_ because then we would end up with a child named
+ # __value_ instead of [0]
+ return self.valobj.CreateValueFromData('[' + str(index) + ']',obj_data,self.data_type)
+ else:
+ # FIXME we need to have accessed item 0 before accessing any other item!
+ if self.skip_size == None:
+ return None
+ return current.CreateChildAtOffset('[' + str(index) + ']',self.skip_size,self.data_type)
+ else:
+ print "foo"
+ return None
+ except Exception as err:
+ print err
+ return None
+
+def stdmap_SummaryProvider(valobj,dict):
+ prov = stdmap_SynthProvider(valobj,None)
+ return 'size=' + str(prov.num_children())
+
+
+# we can use two different categories for old and new formatters - type names are different enough that we should make no confusion
+# talking with libc++ developer: "std::__1::class_name is set in stone until we decide to change the ABI. That shouldn't happen within a 5 year time frame"
+def __lldb_init_module(debugger,dict):
+ debugger.HandleCommand('type summary add -F libcxx.stdstring_SummaryProvider "std::__1::string" -w libcxx')
+ debugger.HandleCommand('type summary add -F libcxx.stdstring_SummaryProvider "std::__1::basic_string<char, class std::__1::char_traits<char>, class std::__1::allocator<char> >" -w libcxx')
+ debugger.HandleCommand('type synthetic add -l libcxx.stdvector_SynthProvider -x "^(std::__1::)vector<.+>$" -w libcxx')
+ debugger.HandleCommand('type summary add -F libcxx.stdvector_SummaryProvider -e -x "^(std::__1::)vector<.+>$" -w libcxx')
+ debugger.HandleCommand('type synthetic add -l libcxx.stdlist_SynthProvider -x "^(std::__1::)list<.+>$" -w libcxx')
+ debugger.HandleCommand('type summary add -F libcxx.stdlist_SummaryProvider -e -x "^(std::__1::)list<.+>$" -w libcxx')
+ debugger.HandleCommand('type synthetic add -l libcxx.stdmap_SynthProvider -x "^(std::__1::)map<.+> >$" -w libcxx')
+ debugger.HandleCommand('type summary add -F libcxx.stdmap_SummaryProvider -e -x "^(std::__1::)map<.+> >$" -w libcxx')
+ debugger.HandleCommand("type category enable libcxx")
Modified: lldb/trunk/include/lldb/Core/FormatManager.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Core/FormatManager.h?rev=152570&r1=152569&r2=152570&view=diff
==============================================================================
--- lldb/trunk/include/lldb/Core/FormatManager.h (original)
+++ lldb/trunk/include/lldb/Core/FormatManager.h Mon Mar 12 14:47:17 2012
@@ -670,6 +670,7 @@
ConstString m_default_category_name;
ConstString m_system_category_name;
ConstString m_gnu_cpp_category_name;
+ ConstString m_libcxx_category_name;
ConstString m_objc_category_name;
ConstString m_corefoundation_category_name;
ConstString m_coregraphics_category_name;
@@ -691,6 +692,9 @@
LoadSTLFormatters();
void
+ LoadLibcxxFormatters();
+
+ void
LoadSystemFormatters();
#ifndef LLDB_DISABLE_PYTHON
Modified: lldb/trunk/scripts/Python/finish-swig-Python-LLDB.sh
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/scripts/Python/finish-swig-Python-LLDB.sh?rev=152570&r1=152569&r2=152570&view=diff
==============================================================================
--- lldb/trunk/scripts/Python/finish-swig-Python-LLDB.sh (original)
+++ lldb/trunk/scripts/Python/finish-swig-Python-LLDB.sh Mon Mar 12 14:47:17 2012
@@ -184,6 +184,20 @@
fi
fi
+if [ -f "${SRC_ROOT}/examples/synthetic/libcxx.py" ]
+then
+ if [ $Debug == 1 ]
+ then
+ echo "Copying libcxx.py to ${framework_python_dir}"
+ fi
+ cp "${SRC_ROOT}/examples/synthetic/libcxx.py" "${framework_python_dir}"
+else
+ if [ $Debug == 1 ]
+ then
+ echo "Unable to find ${SRC_ROOT}/examples/synthetic/libcxx.py"
+ fi
+fi
+
# Copy the ObjC formatters over to the framework Python directory
if [ -f "${SRC_ROOT}/examples/summaries/objc.py" ]
then
Modified: lldb/trunk/source/Core/FormatManager.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Core/FormatManager.cpp?rev=152570&r1=152569&r2=152570&view=diff
==============================================================================
--- lldb/trunk/source/Core/FormatManager.cpp (original)
+++ lldb/trunk/source/Core/FormatManager.cpp Mon Mar 12 14:47:17 2012
@@ -580,6 +580,7 @@
m_default_category_name(ConstString("default")),
m_system_category_name(ConstString("system")),
m_gnu_cpp_category_name(ConstString("gnu-libstdc++")),
+ m_libcxx_category_name(ConstString("libcxx")),
m_objc_category_name(ConstString("objc")),
m_corefoundation_category_name(ConstString("CoreFoundation")),
m_coregraphics_category_name(ConstString("CoreGraphics")),
@@ -590,6 +591,7 @@
LoadSystemFormatters();
LoadSTLFormatters();
+ LoadLibcxxFormatters();
#ifndef LLDB_DISABLE_PYTHON
LoadObjCFormatters();
#endif
@@ -600,6 +602,7 @@
//EnableCategory(m_coreservices_category_name,CategoryMap::Last);
//EnableCategory(m_coregraphics_category_name,CategoryMap::Last);
EnableCategory(m_gnu_cpp_category_name,CategoryMap::Last);
+ EnableCategory(m_libcxx_category_name,CategoryMap::Last);
//EnableCategory(m_vectortypes_category_name,CategoryMap::Last);
EnableCategory(m_system_category_name,CategoryMap::Last);
}
@@ -654,6 +657,57 @@
}
void
+FormatManager::LoadLibcxxFormatters()
+{
+ TypeSummaryImpl::Flags stl_summary_flags;
+ stl_summary_flags.SetCascades(true)
+ .SetSkipPointers(false)
+ .SetSkipReferences(false)
+ .SetDontShowChildren(true)
+ .SetDontShowValue(true)
+ .SetShowMembersOneLiner(false)
+ .SetHideItemNames(false);
+
+ std::string code(" libcxx.stdstring_SummaryProvider(valobj,dict)");
+ lldb::TypeSummaryImplSP std_string_summary_sp(new ScriptSummaryFormat(stl_summary_flags, "libcxx.stdstring_SummaryProvider",code.c_str()));
+
+ TypeCategoryImpl::SharedPointer libcxx_category_sp = GetCategory(m_libcxx_category_name);
+
+ libcxx_category_sp->GetSummaryNavigator()->Add(ConstString("std::__1::string"),
+ std_string_summary_sp);
+ libcxx_category_sp->GetSummaryNavigator()->Add(ConstString("std::__1::basic_string<char, class std::__1::char_traits<char>, class std::__1::allocator<char> >"),
+ std_string_summary_sp);
+
+
+#ifndef LLDB_DISABLE_PYTHON
+
+ SyntheticChildren::Flags stl_synth_flags;
+ stl_synth_flags.SetCascades(true).SetSkipPointers(false).SetSkipReferences(false);
+
+ libcxx_category_sp->GetRegexSyntheticNavigator()->Add(RegularExpressionSP(new RegularExpression("^(std::__1::)vector<.+>$")),
+ SyntheticChildrenSP(new TypeSyntheticImpl(stl_synth_flags,
+ "libcxx.stdvector_SynthProvider")));
+ libcxx_category_sp->GetRegexSyntheticNavigator()->Add(RegularExpressionSP(new RegularExpression("^(std::__1::)list<.+>$")),
+ SyntheticChildrenSP(new TypeSyntheticImpl(stl_synth_flags,
+ "libcxx.stdlist_SynthProvider")));
+ libcxx_category_sp->GetRegexSyntheticNavigator()->Add(RegularExpressionSP(new RegularExpression("^(std::__1::)map<.+> >$")),
+ SyntheticChildrenSP(new TypeSyntheticImpl(stl_synth_flags,
+ "libcxx.stdmap_SynthProvider")));
+
+ stl_summary_flags.SetDontShowChildren(false);
+ code.assign(" libcxx.stdvector_SummaryProvider(valobj,dict)");
+ libcxx_category_sp->GetRegexSummaryNavigator()->Add(RegularExpressionSP(new RegularExpression("^(std::__1::)vector<.+>$")),
+ TypeSummaryImplSP(new ScriptSummaryFormat(stl_summary_flags, "libcxx.stdvector_SummaryProvider",code.c_str())));
+ code.assign(" libcxx.stdlist_SummaryProvider(valobj,dict)");
+ libcxx_category_sp->GetRegexSummaryNavigator()->Add(RegularExpressionSP(new RegularExpression("^(std::__1::)list<.+>$")),
+ TypeSummaryImplSP(new ScriptSummaryFormat(stl_summary_flags, "libcxx.stdlist_SummaryProvider",code.c_str())));
+ code.assign(" libcxx.stdmap_SummaryProvider(valobj,dict)");
+ libcxx_category_sp->GetRegexSummaryNavigator()->Add(RegularExpressionSP(new RegularExpression("^(std::__1::)map<.+> >$")),
+ TypeSummaryImplSP(new ScriptSummaryFormat(stl_summary_flags, "libcxx.stdmap_SummaryProvider",code.c_str())));
+#endif
+}
+
+void
FormatManager::LoadSystemFormatters()
{
lldb::TypeSummaryImplSP string_format(new StringSummaryFormat(TypeSummaryImpl::Flags().SetCascades(false)
Modified: lldb/trunk/source/Interpreter/ScriptInterpreterPython.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Interpreter/ScriptInterpreterPython.cpp?rev=152570&r1=152569&r2=152570&view=diff
==============================================================================
--- lldb/trunk/source/Interpreter/ScriptInterpreterPython.cpp (original)
+++ lldb/trunk/source/Interpreter/ScriptInterpreterPython.cpp Mon Mar 12 14:47:17 2012
@@ -279,7 +279,7 @@
int old_count = Debugger::TestDebuggerRefCount();
- run_string.Printf ("run_one_line (%s, 'import copy, os, re, sys, uuid, lldb, gnu_libstdcpp, objc')", m_dictionary_name.c_str());
+ run_string.Printf ("run_one_line (%s, 'import copy, os, re, sys, uuid, lldb, gnu_libstdcpp, libcxx, objc')", m_dictionary_name.c_str());
PyRun_SimpleString (run_string.GetData());
// WARNING: temporary code that loads Cocoa formatters - this should be done on a per-platform basis rather than loading the whole set
Added: lldb/trunk/test/functionalities/data-formatter/data-formatter-stl/libcxx/list/Makefile
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/test/functionalities/data-formatter/data-formatter-stl/libcxx/list/Makefile?rev=152570&view=auto
==============================================================================
--- lldb/trunk/test/functionalities/data-formatter/data-formatter-stl/libcxx/list/Makefile (added)
+++ lldb/trunk/test/functionalities/data-formatter/data-formatter-stl/libcxx/list/Makefile Mon Mar 12 14:47:17 2012
@@ -0,0 +1,8 @@
+LEVEL = ../../../../../make
+
+CXX_SOURCES := main.cpp
+
+include $(LEVEL)/Makefile.rules
+
+CXXFLAGS += -stdlib=libc++ -O0
+LDFLAGS += -stdlib=libc++
\ No newline at end of file
Added: lldb/trunk/test/functionalities/data-formatter/data-formatter-stl/libcxx/list/TestDataFormatterLibcxxList.py
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/test/functionalities/data-formatter/data-formatter-stl/libcxx/list/TestDataFormatterLibcxxList.py?rev=152570&view=auto
==============================================================================
--- lldb/trunk/test/functionalities/data-formatter/data-formatter-stl/libcxx/list/TestDataFormatterLibcxxList.py (added)
+++ lldb/trunk/test/functionalities/data-formatter/data-formatter-stl/libcxx/list/TestDataFormatterLibcxxList.py Mon Mar 12 14:47:17 2012
@@ -0,0 +1,175 @@
+"""
+Test lldb data formatter subsystem.
+"""
+
+import os, time
+import unittest2
+import lldb
+from lldbtest import *
+
+class LibcxxListDataFormatterTestCase(TestBase):
+
+ mydir = os.path.join("functionalities", "data-formatter", "data-formatter-stl", "libcxx", "list")
+
+ @unittest2.skipUnless(sys.platform.startswith("darwin"), "requires Darwin")
+ def test_with_dsym_and_run_command(self):
+ """Test data formatter commands."""
+ self.buildDsym()
+ self.data_formatter_commands()
+
+ def test_with_dwarf_and_run_command(self):
+ """Test data formatter commands."""
+ self.buildDwarf()
+ self.data_formatter_commands()
+
+ def setUp(self):
+ # Call super's setUp().
+ TestBase.setUp(self)
+ # Find the line number to break at.
+ self.line = line_number('main.cpp', '// Set break point at this line.')
+ self.line2 = line_number('main.cpp', '// Set second break point at this line.')
+
+ def data_formatter_commands(self):
+ """Test that that file and class static variables display correctly."""
+ self.runCmd("file a.out", CURRENT_EXECUTABLE_SET)
+
+ self.expect("breakpoint set -f main.cpp -l %d" % self.line,
+ BREAKPOINT_CREATED,
+ startstr = "Breakpoint created: 1: file ='main.cpp', line = %d" %
+ self.line)
+ self.expect("breakpoint set -f main.cpp -l %d" % self.line2,
+ BREAKPOINT_CREATED,
+ startstr = "Breakpoint created: 2: file ='main.cpp', line = %d" %
+ self.line2)
+
+ 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)
+
+ self.runCmd("frame variable numbers_list -T")
+ self.runCmd("type summary add std::int_list std::string_list int_list string_list --summary-string \"list has ${svar%#} items\" -e")
+ self.runCmd("type format add -f hex int")
+
+ self.expect("frame variable numbers_list --raw", matching=False,
+ substrs = ['list has 0 items',
+ '{}'])
+
+ self.expect("frame variable numbers_list",
+ substrs = ['list has 0 items',
+ '{}'])
+
+ self.expect("p numbers_list",
+ substrs = ['list has 0 items',
+ '{}'])
+
+ self.runCmd("n")
+
+ self.expect("frame variable numbers_list",
+ substrs = ['list has 1 items',
+ '[0] = ',
+ '0x12345678'])
+
+ self.runCmd("n");self.runCmd("n");self.runCmd("n");
+
+ self.expect("frame variable numbers_list",
+ substrs = ['list has 4 items',
+ '[0] = ',
+ '0x12345678',
+ '[1] =',
+ '0x11223344',
+ '[2] =',
+ '0xbeeffeed',
+ '[3] =',
+ '0x00abba00'])
+
+ self.runCmd("n");self.runCmd("n");
+
+ self.expect("frame variable numbers_list",
+ substrs = ['list has 6 items',
+ '[0] = ',
+ '0x12345678',
+ '0x11223344',
+ '0xbeeffeed',
+ '0x00abba00',
+ '[4] =',
+ '0x0abcdef0',
+ '[5] =',
+ '0x0cab0cab'])
+
+ self.expect("p numbers_list",
+ substrs = ['list has 6 items',
+ '[0] = ',
+ '0x12345678',
+ '0x11223344',
+ '0xbeeffeed',
+ '0x00abba00',
+ '[4] =',
+ '0x0abcdef0',
+ '[5] =',
+ '0x0cab0cab'])
+
+ # check access-by-index
+ self.expect("frame variable numbers_list[0]",
+ substrs = ['0x12345678']);
+ self.expect("frame variable numbers_list[1]",
+ substrs = ['0x11223344']);
+
+ self.runCmd("n")
+
+ self.expect("frame variable numbers_list",
+ substrs = ['list has 0 items',
+ '{}'])
+
+ self.runCmd("n");self.runCmd("n");self.runCmd("n");self.runCmd("n");
+
+ self.expect("frame variable numbers_list",
+ substrs = ['list has 4 items',
+ '[0] = ', '1',
+ '[1] = ', '2',
+ '[2] = ', '3',
+ '[3] = ', '4'])
+
+ self.runCmd("type format delete int")
+
+ self.runCmd("c")
+
+ self.expect("frame variable text_list",
+ substrs = ['list has 3 items',
+ '[0]', 'goofy',
+ '[1]', 'is',
+ '[2]', 'smart'])
+
+ self.expect("p text_list",
+ substrs = ['list has 3 items',
+ '\"goofy\"',
+ '\"is\"',
+ '\"smart\"'])
+
+ self.runCmd("n")
+
+ # check access-by-index
+ self.expect("frame variable text_list[0]",
+ substrs = ['goofy']);
+ self.expect("frame variable text_list[3]",
+ substrs = ['!!!']);
+
+if __name__ == '__main__':
+ import atexit
+ lldb.SBDebugger.Initialize()
+ atexit.register(lambda: lldb.SBDebugger.Terminate())
+ unittest2.main()
Added: lldb/trunk/test/functionalities/data-formatter/data-formatter-stl/libcxx/list/main.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/test/functionalities/data-formatter/data-formatter-stl/libcxx/list/main.cpp?rev=152570&view=auto
==============================================================================
--- lldb/trunk/test/functionalities/data-formatter/data-formatter-stl/libcxx/list/main.cpp (added)
+++ lldb/trunk/test/functionalities/data-formatter/data-formatter-stl/libcxx/list/main.cpp Mon Mar 12 14:47:17 2012
@@ -0,0 +1,35 @@
+#include <string>
+#define _LIBCPP_INLINE_VISIBILITY
+#include <list>
+
+
+typedef std::list<int> int_list;
+typedef std::list<std::string> string_list;
+
+int main()
+{
+ int_list numbers_list;
+
+ (numbers_list.push_back(0x12345678)); // Set break point at this line.
+ (numbers_list.push_back(0x11223344));
+ (numbers_list.push_back(0xBEEFFEED));
+ (numbers_list.push_back(0x00ABBA00));
+ (numbers_list.push_back(0x0ABCDEF0));
+ (numbers_list.push_back(0x0CAB0CAB));
+
+ numbers_list.clear();
+
+ (numbers_list.push_back(1));
+ (numbers_list.push_back(2));
+ (numbers_list.push_back(3));
+ (numbers_list.push_back(4));
+
+ string_list text_list;
+ (text_list.push_back(std::string("goofy")));
+ (text_list.push_back(std::string("is")));
+ (text_list.push_back(std::string("smart")));
+
+ (text_list.push_back(std::string("!!!"))); // Set second break point at this line.
+
+ return 0;
+}
\ No newline at end of file
Added: lldb/trunk/test/functionalities/data-formatter/data-formatter-stl/libcxx/map/Makefile
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/test/functionalities/data-formatter/data-formatter-stl/libcxx/map/Makefile?rev=152570&view=auto
==============================================================================
--- lldb/trunk/test/functionalities/data-formatter/data-formatter-stl/libcxx/map/Makefile (added)
+++ lldb/trunk/test/functionalities/data-formatter/data-formatter-stl/libcxx/map/Makefile Mon Mar 12 14:47:17 2012
@@ -0,0 +1,8 @@
+LEVEL = ../../../../../make
+
+CXX_SOURCES := main.cpp
+
+include $(LEVEL)/Makefile.rules
+
+CXXFLAGS += -stdlib=libc++ -O0
+LDFLAGS += -stdlib=libc++
\ No newline at end of file
Added: lldb/trunk/test/functionalities/data-formatter/data-formatter-stl/libcxx/map/TestDataFormatterLibccMap.py
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/test/functionalities/data-formatter/data-formatter-stl/libcxx/map/TestDataFormatterLibccMap.py?rev=152570&view=auto
==============================================================================
--- lldb/trunk/test/functionalities/data-formatter/data-formatter-stl/libcxx/map/TestDataFormatterLibccMap.py (added)
+++ lldb/trunk/test/functionalities/data-formatter/data-formatter-stl/libcxx/map/TestDataFormatterLibccMap.py Mon Mar 12 14:47:17 2012
@@ -0,0 +1,332 @@
+"""
+Test lldb data formatter subsystem.
+"""
+
+import os, time
+import unittest2
+import lldb
+from lldbtest import *
+
+class LibcxxMapDataFormatterTestCase(TestBase):
+
+ mydir = os.path.join("functionalities", "data-formatter", "data-formatter-stl", "libstdcpp", "map")
+
+ @unittest2.skipUnless(sys.platform.startswith("darwin"), "requires Darwin")
+ def test_with_dsym_and_run_command(self):
+ """Test data formatter commands."""
+ self.buildDsym()
+ self.data_formatter_commands()
+
+ def test_with_dwarf_and_run_command(self):
+ """Test data formatter commands."""
+ self.buildDwarf()
+ self.data_formatter_commands()
+
+ def setUp(self):
+ # Call super's setUp().
+ TestBase.setUp(self)
+ # Find the line number to break at.
+ self.line = line_number('main.cpp', '// Set break point at this line.')
+
+ def data_formatter_commands(self):
+ """Test that that file and class static variables display correctly."""
+ self.runCmd("file a.out", CURRENT_EXECUTABLE_SET)
+
+ self.expect("breakpoint set -f main.cpp -l %d" % self.line,
+ BREAKPOINT_CREATED,
+ startstr = "Breakpoint created: 1: file ='main.cpp', line = %d" %
+ self.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)
+
+ self.runCmd("frame variable ii -T")
+
+ self.runCmd("type summary add -x \"std::map<\" --summary-string \"map has ${svar%#} items\" -e")
+
+ self.expect('frame variable ii',
+ substrs = ['map has 0 items',
+ '{}'])
+
+ self.runCmd("n");self.runCmd("n");
+
+ self.expect('frame variable ii',
+ substrs = ['map has 2 items',
+ '[0] = {',
+ 'first = 0',
+ 'second = 0',
+ '[1] = {',
+ 'first = 1',
+ 'second = 1'])
+
+ self.runCmd("n");self.runCmd("n");
+
+ self.expect('frame variable ii',
+ substrs = ['map has 4 items',
+ '[2] = {',
+ 'first = 2',
+ 'second = 0',
+ '[3] = {',
+ 'first = 3',
+ 'second = 1'])
+
+ self.runCmd("n");self.runCmd("n");
+ self.runCmd("n");self.runCmd("n");self.runCmd("n");
+
+ self.expect("frame variable ii",
+ substrs = ['map has 9 items',
+ '[5] = {',
+ 'first = 5',
+ 'second = 0',
+ '[7] = {',
+ 'first = 7',
+ 'second = 1'])
+
+ self.expect("p ii",
+ substrs = ['map has 9 items',
+ '[5] = {',
+ 'first = 5',
+ 'second = 0',
+ '[7] = {',
+ 'first = 7',
+ 'second = 1'])
+
+ # check access-by-index
+ self.expect("frame variable ii[0]",
+ substrs = ['first = 0',
+ 'second = 0']);
+ self.expect("frame variable ii[3]",
+ substrs = ['first =',
+ 'second =']);
+
+ self.expect("frame variable ii[8]", matching=True,
+ substrs = ['1234567'])
+
+ # check that the expression parser does not make use of
+ # synthetic children instead of running code
+ # TOT clang has a fix for this, which makes the expression command here succeed
+ # since this would make the test fail or succeed depending on clang version in use
+ # this is safer commented for the time being
+ #self.expect("expression ii[8]", matching=False, error=True,
+ # substrs = ['1234567'])
+
+ self.runCmd("n")
+
+ self.expect('frame variable ii',
+ substrs = ['map has 0 items',
+ '{}'])
+
+ self.runCmd("n")
+ self.runCmd("frame variable si -T")
+
+ #self.runCmd("type summary add std::strint_map strint_map --summary-string \"map has ${svar%#} items\" -e")
+ #self.runCmd("type synth add std::strint_map strint_map -l StdMapSynthProvider")
+
+ self.expect('frame variable si',
+ substrs = ['map has 0 items',
+ '{}'])
+
+ self.runCmd("n")
+
+ self.expect('frame variable si',
+ substrs = ['map has 1 items',
+ '[0] = ',
+ 'first = \"zero\"',
+ 'second = 0'])
+
+ self.runCmd("n");self.runCmd("n");self.runCmd("n");self.runCmd("n");
+
+ self.expect("frame variable si",
+ substrs = ['map has 5 items',
+ '[0] = ',
+ 'first = \"zero\"',
+ 'second = 0',
+ '[1] = ',
+ 'first = \"one\"',
+ 'second = 1',
+ '[2] = ',
+ 'first = \"two\"',
+ 'second = 2',
+ '[3] = ',
+ 'first = \"three\"',
+ 'second = 3',
+ '[4] = ',
+ 'first = \"four\"',
+ 'second = 4'])
+
+ self.expect("p si",
+ substrs = ['map has 5 items',
+ '[0] = ',
+ 'first = \"zero\"',
+ 'second = 0',
+ '[1] = ',
+ 'first = \"one\"',
+ 'second = 1',
+ '[2] = ',
+ 'first = \"two\"',
+ 'second = 2',
+ '[3] = ',
+ 'first = \"three\"',
+ 'second = 3',
+ '[4] = ',
+ 'first = \"four\"',
+ 'second = 4'])
+
+ # check access-by-index
+ self.expect("frame variable si[0]",
+ substrs = ['first = ', 'four',
+ 'second = 4']);
+
+ # check that the expression parser does not make use of
+ # synthetic children instead of running code
+ # TOT clang has a fix for this, which makes the expression command here succeed
+ # since this would make the test fail or succeed depending on clang version in use
+ # this is safer commented for the time being
+ #self.expect("expression si[0]", matching=False, error=True,
+ # substrs = ['first = ', 'zero'])
+
+ self.runCmd("n")
+
+ self.expect('frame variable si',
+ substrs = ['map has 0 items',
+ '{}'])
+
+ self.runCmd("n")
+ self.runCmd("frame variable is -T")
+
+ #self.runCmd("type summary add std::intstr_map intstr_map --summary-string \"map has ${svar%#} items\" -e")
+ #self.runCmd("type synth add std::intstr_map intstr_map -l StdMapSynthProvider")
+
+ self.expect('frame variable is',
+ substrs = ['map has 0 items',
+ '{}'])
+
+ self.runCmd("n");self.runCmd("n");self.runCmd("n");self.runCmd("n");
+
+ self.expect("frame variable is",
+ substrs = ['map has 4 items',
+ '[0] = ',
+ 'second = \"goofy\"',
+ 'first = 85',
+ '[1] = ',
+ 'second = \"is\"',
+ 'first = 1',
+ '[2] = ',
+ 'second = \"smart\"',
+ 'first = 2',
+ '[3] = ',
+ 'second = \"!!!\"',
+ 'first = 3'])
+
+ self.expect("p is",
+ substrs = ['map has 4 items',
+ '[0] = ',
+ 'second = \"goofy\"',
+ 'first = 85',
+ '[1] = ',
+ 'second = \"is\"',
+ 'first = 1',
+ '[2] = ',
+ 'second = \"smart\"',
+ 'first = 2',
+ '[3] = ',
+ 'second = \"!!!\"',
+ 'first = 3'])
+
+ # check access-by-index
+ self.expect("frame variable is[0]",
+ substrs = ['first = ',
+ 'second =']);
+
+ # check that the expression parser does not make use of
+ # synthetic children instead of running code
+ # TOT clang has a fix for this, which makes the expression command here succeed
+ # since this would make the test fail or succeed depending on clang version in use
+ # this is safer commented for the time being
+ #self.expect("expression is[0]", matching=False, error=True,
+ # substrs = ['first = ', 'goofy'])
+
+ self.runCmd("n")
+
+ self.expect('frame variable is',
+ substrs = ['map has 0 items',
+ '{}'])
+
+ self.runCmd("n")
+ self.runCmd("frame variable ss -T")
+
+ self.expect('frame variable ss',
+ substrs = ['map has 0 items',
+ '{}'])
+
+ self.runCmd("n");self.runCmd("n");self.runCmd("n");self.runCmd("n");
+
+ self.expect("frame variable ss",
+ substrs = ['map has 4 items',
+ '[0] = ',
+ 'second = \"hello\"',
+ 'first = \"ciao\"',
+ '[1] = ',
+ 'second = \"house\"',
+ 'first = \"casa\"',
+ '[2] = ',
+ 'second = \"cat\"',
+ 'first = \"gatto\"',
+ '[3] = ',
+ 'second = \"..is always a Mac!\"',
+ 'first = \"a Mac..\"'])
+
+ self.expect("p ss",
+ substrs = ['map has 4 items',
+ '[0] = ',
+ 'second = \"hello\"',
+ 'first = \"ciao\"',
+ '[1] = ',
+ 'second = \"house\"',
+ 'first = \"casa\"',
+ '[2] = ',
+ 'second = \"cat\"',
+ 'first = \"gatto\"',
+ '[3] = ',
+ 'second = \"..is always a Mac!\"',
+ 'first = \"a Mac..\"'])
+
+ # check access-by-index
+ self.expect("frame variable ss[3]",
+ substrs = ['gatto', 'cat']);
+
+ # check that the expression parser does not make use of
+ # synthetic children instead of running code
+ # TOT clang has a fix for this, which makes the expression command here succeed
+ # since this would make the test fail or succeed depending on clang version in use
+ # this is safer commented for the time being
+ #self.expect("expression ss[3]", matching=False, error=True,
+ # substrs = ['gatto'])
+
+ self.runCmd("n")
+
+ self.expect('frame variable ss',
+ substrs = ['map has 0 items',
+ '{}'])
+
+if __name__ == '__main__':
+ import atexit
+ lldb.SBDebugger.Initialize()
+ atexit.register(lambda: lldb.SBDebugger.Terminate())
+ unittest2.main()
Added: lldb/trunk/test/functionalities/data-formatter/data-formatter-stl/libcxx/map/main.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/test/functionalities/data-formatter/data-formatter-stl/libcxx/map/main.cpp?rev=152570&view=auto
==============================================================================
--- lldb/trunk/test/functionalities/data-formatter/data-formatter-stl/libcxx/map/main.cpp (added)
+++ lldb/trunk/test/functionalities/data-formatter/data-formatter-stl/libcxx/map/main.cpp Mon Mar 12 14:47:17 2012
@@ -0,0 +1,55 @@
+#include <map>
+#include <string>
+
+#define intint_map std::map<int, int>
+#define strint_map std::map<std::string, int>
+#define intstr_map std::map<int, std::string>
+#define strstr_map std::map<std::string, std::string>
+
+
+int main()
+{
+ intint_map ii;
+
+ ii[0] = 0; // Set break point at this line.
+ ii[1] = 1;
+ ii[2] = 0;
+ ii[3] = 1;
+ ii[4] = 0;
+ ii[5] = 1;
+ ii[6] = 0;
+ ii[7] = 1;
+ ii[85] = 1234567;
+
+ ii.clear();
+
+ strint_map si;
+
+ si["zero"] = 0;
+ si["one"] = 1;
+ si["two"] = 2;
+ si["three"] = 3;
+ si["four"] = 4;
+
+ si.clear();
+
+ intstr_map is;
+
+ is[85] = "goofy";
+ is[1] = "is";
+ is[2] = "smart";
+ is[3] = "!!!";
+
+ is.clear();
+
+ strstr_map ss;
+
+ ss["ciao"] = "hello";
+ ss["casa"] = "house";
+ ss["gatto"] = "cat";
+ ss["a Mac.."] = "..is always a Mac!";
+
+ ss.clear();
+
+ return 0;
+}
\ No newline at end of file
Added: lldb/trunk/test/functionalities/data-formatter/data-formatter-stl/libcxx/vector/Makefile
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/test/functionalities/data-formatter/data-formatter-stl/libcxx/vector/Makefile?rev=152570&view=auto
==============================================================================
--- lldb/trunk/test/functionalities/data-formatter/data-formatter-stl/libcxx/vector/Makefile (added)
+++ lldb/trunk/test/functionalities/data-formatter/data-formatter-stl/libcxx/vector/Makefile Mon Mar 12 14:47:17 2012
@@ -0,0 +1,8 @@
+LEVEL = ../../../../../make
+
+CXX_SOURCES := main.cpp
+
+include $(LEVEL)/Makefile.rules
+
+CXXFLAGS += -stdlib=libc++ -O0
+LDFLAGS += -stdlib=libc++
\ No newline at end of file
Added: lldb/trunk/test/functionalities/data-formatter/data-formatter-stl/libcxx/vector/TestDataFormatterLibcxxVector.py
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/test/functionalities/data-formatter/data-formatter-stl/libcxx/vector/TestDataFormatterLibcxxVector.py?rev=152570&view=auto
==============================================================================
--- lldb/trunk/test/functionalities/data-formatter/data-formatter-stl/libcxx/vector/TestDataFormatterLibcxxVector.py (added)
+++ lldb/trunk/test/functionalities/data-formatter/data-formatter-stl/libcxx/vector/TestDataFormatterLibcxxVector.py Mon Mar 12 14:47:17 2012
@@ -0,0 +1,204 @@
+"""
+Test lldb data formatter subsystem.
+"""
+
+import os, time
+import unittest2
+import lldb
+from lldbtest import *
+
+class LibcxxVectorDataFormatterTestCase(TestBase):
+
+ mydir = os.path.join("functionalities", "data-formatter", "data-formatter-stl", "libcxx", "vector")
+
+ @unittest2.skipUnless(sys.platform.startswith("darwin"), "requires Darwin")
+ def test_with_dsym_and_run_command(self):
+ """Test data formatter commands."""
+ self.buildDsym()
+ self.data_formatter_commands()
+
+ def test_with_dwarf_and_run_command(self):
+ """Test data formatter commands."""
+ self.buildDwarf()
+ self.data_formatter_commands()
+
+ def setUp(self):
+ # Call super's setUp().
+ TestBase.setUp(self)
+ # Find the line number to break at.
+ self.line = line_number('main.cpp', '// Set break point at this line.')
+ self.line2 = line_number('main.cpp', '// Set second break point at this line.')
+
+ def data_formatter_commands(self):
+ """Test that that file and class static variables display correctly."""
+ self.runCmd("file a.out", CURRENT_EXECUTABLE_SET)
+
+ self.expect("breakpoint set -f main.cpp -l %d" % self.line,
+ BREAKPOINT_CREATED,
+ startstr = "Breakpoint created: 1: file ='main.cpp', line = %d" %
+ self.line)
+ self.expect("breakpoint set -f main.cpp -l %d" % self.line2,
+ BREAKPOINT_CREATED,
+ startstr = "Breakpoint created: 2: file ='main.cpp', line = %d" %
+ self.line2)
+
+ 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)
+
+ # empty vectors (and storage pointers SHOULD BOTH BE NULL..)
+ self.expect("frame variable numbers",
+ substrs = ['numbers = size=0'])
+
+ self.runCmd("n")
+
+ # first value added
+ self.expect("frame variable numbers",
+ substrs = ['numbers = size=1',
+ '[0] = 1',
+ '}'])
+
+ # add some more data
+ self.runCmd("n");self.runCmd("n");self.runCmd("n");
+
+ self.expect("frame variable numbers",
+ substrs = ['numbers = size=4',
+ '[0] = 1',
+ '[1] = 12',
+ '[2] = 123',
+ '[3] = 1234',
+ '}'])
+
+ self.expect("p numbers",
+ substrs = ['$', 'size=4',
+ '[0] = 1',
+ '[1] = 12',
+ '[2] = 123',
+ '[3] = 1234',
+ '}'])
+
+
+ # check access to synthetic children
+ self.runCmd("type summary add --summary-string \"item 0 is ${var[0]}\" std::int_vect int_vect")
+ self.expect('frame variable numbers',
+ substrs = ['item 0 is 1']);
+
+ self.runCmd("type summary add --summary-string \"item 0 is ${svar[0]}\" std::int_vect int_vect")
+ self.expect('frame variable numbers',
+ substrs = ['item 0 is 1']);
+ # move on with synths
+ self.runCmd("type summary delete std::int_vect")
+ self.runCmd("type summary delete int_vect")
+
+ # add some more data
+ self.runCmd("n");self.runCmd("n");self.runCmd("n");
+
+ self.expect("frame variable numbers",
+ substrs = ['numbers = size=7',
+ '[0] = 1',
+ '[1] = 12',
+ '[2] = 123',
+ '[3] = 1234',
+ '[4] = 12345',
+ '[5] = 123456',
+ '[6] = 1234567',
+ '}'])
+
+ self.expect("p numbers",
+ substrs = ['$', 'size=7',
+ '[0] = 1',
+ '[1] = 12',
+ '[2] = 123',
+ '[3] = 1234',
+ '[4] = 12345',
+ '[5] = 123456',
+ '[6] = 1234567',
+ '}'])
+
+ # check access-by-index
+ self.expect("frame variable numbers[0]",
+ substrs = ['1']);
+ self.expect("frame variable numbers[1]",
+ substrs = ['12']);
+ self.expect("frame variable numbers[2]",
+ substrs = ['123']);
+ self.expect("frame variable numbers[3]",
+ substrs = ['1234']);
+
+ # clear out the vector and see that we do the right thing once again
+ self.runCmd("n")
+
+ self.expect("frame variable numbers",
+ substrs = ['numbers = size=0'])
+
+ self.runCmd("n")
+
+ # first value added
+ self.expect("frame variable numbers",
+ substrs = ['numbers = size=1',
+ '[0] = 7',
+ '}'])
+
+ # check if we can display strings
+ self.runCmd("c")
+
+ self.expect("frame variable strings",
+ substrs = ['goofy',
+ 'is',
+ 'smart'])
+
+ self.expect("p strings",
+ substrs = ['goofy',
+ 'is',
+ 'smart'])
+
+ # test summaries based on synthetic children
+ self.runCmd("type summary add std::string_vect string_vect --summary-string \"vector has ${svar%#} items\" -e")
+ self.expect("frame variable strings",
+ substrs = ['vector has 3 items',
+ 'goofy',
+ 'is',
+ 'smart'])
+
+ self.expect("p strings",
+ substrs = ['vector has 3 items',
+ 'goofy',
+ 'is',
+ 'smart'])
+
+ self.runCmd("n")
+
+ self.expect("frame variable strings",
+ substrs = ['vector has 4 items'])
+
+ # check access-by-index
+ self.expect("frame variable strings[0]",
+ substrs = ['goofy']);
+ self.expect("frame variable strings[1]",
+ substrs = ['is']);
+
+ self.runCmd("n")
+
+ self.expect("frame variable strings",
+ substrs = ['vector has 0 items'])
+
+if __name__ == '__main__':
+ import atexit
+ lldb.SBDebugger.Initialize()
+ atexit.register(lambda: lldb.SBDebugger.Terminate())
+ unittest2.main()
Added: lldb/trunk/test/functionalities/data-formatter/data-formatter-stl/libcxx/vector/main.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/test/functionalities/data-formatter/data-formatter-stl/libcxx/vector/main.cpp?rev=152570&view=auto
==============================================================================
--- lldb/trunk/test/functionalities/data-formatter/data-formatter-stl/libcxx/vector/main.cpp (added)
+++ lldb/trunk/test/functionalities/data-formatter/data-formatter-stl/libcxx/vector/main.cpp Mon Mar 12 14:47:17 2012
@@ -0,0 +1,32 @@
+#include <string>
+#define _LIBCPP_INLINE_VISIBILITY
+#include <vector>
+typedef std::vector<int> int_vect;
+typedef std::vector<std::string> string_vect;
+
+int main()
+{
+ int_vect numbers;
+ (numbers.push_back(1)); // Set break point at this line.
+ (numbers.push_back(12));
+ (numbers.push_back(123));
+ (numbers.push_back(1234));
+ (numbers.push_back(12345));
+ (numbers.push_back(123456));
+ (numbers.push_back(1234567));
+
+ numbers.clear();
+
+ (numbers.push_back(7));
+
+ string_vect strings;
+ (strings.push_back(std::string("goofy")));
+ (strings.push_back(std::string("is")));
+ (strings.push_back(std::string("smart")));
+
+ (strings.push_back(std::string("!!!"))); // Set second break point at this line.
+
+ strings.clear();
+
+ return 0;
+}
Modified: lldb/trunk/test/functionalities/data-formatter/data-formatter-stl/libstdcpp/list/Makefile
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/test/functionalities/data-formatter/data-formatter-stl/libstdcpp/list/Makefile?rev=152570&r1=152325&r2=152570&view=diff
==============================================================================
--- lldb/trunk/test/functionalities/data-formatter/data-formatter-stl/libstdcpp/list/Makefile (original)
+++ lldb/trunk/test/functionalities/data-formatter/data-formatter-stl/libstdcpp/list/Makefile Mon Mar 12 14:47:17 2012
@@ -1,4 +1,4 @@
-LEVEL = ../../../../make
+LEVEL = ../../../../../make
CXX_SOURCES := main.cpp
Modified: lldb/trunk/test/functionalities/data-formatter/data-formatter-stl/libstdcpp/list/TestDataFormatterStdList.py
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/test/functionalities/data-formatter/data-formatter-stl/libstdcpp/list/TestDataFormatterStdList.py?rev=152570&r1=152325&r2=152570&view=diff
==============================================================================
--- lldb/trunk/test/functionalities/data-formatter/data-formatter-stl/libstdcpp/list/TestDataFormatterStdList.py (original)
+++ lldb/trunk/test/functionalities/data-formatter/data-formatter-stl/libstdcpp/list/TestDataFormatterStdList.py Mon Mar 12 14:47:17 2012
@@ -9,7 +9,7 @@
class StdListDataFormatterTestCase(TestBase):
- mydir = os.path.join("functionalities", "data-formatter", "data-formatter-stl", "list")
+ mydir = os.path.join("functionalities", "data-formatter", "data-formatter-stl", "libstdcpp", "list")
@unittest2.skipUnless(sys.platform.startswith("darwin"), "requires Darwin")
def test_with_dsym_and_run_command(self):
Modified: lldb/trunk/test/functionalities/data-formatter/data-formatter-stl/libstdcpp/map/Makefile
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/test/functionalities/data-formatter/data-formatter-stl/libstdcpp/map/Makefile?rev=152570&r1=152325&r2=152570&view=diff
==============================================================================
--- lldb/trunk/test/functionalities/data-formatter/data-formatter-stl/libstdcpp/map/Makefile (original)
+++ lldb/trunk/test/functionalities/data-formatter/data-formatter-stl/libstdcpp/map/Makefile Mon Mar 12 14:47:17 2012
@@ -1,4 +1,4 @@
-LEVEL = ../../../../make
+LEVEL = ../../../../../make
CXX_SOURCES := main.cpp
Modified: lldb/trunk/test/functionalities/data-formatter/data-formatter-stl/libstdcpp/map/TestDataFormatterStdMap.py
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/test/functionalities/data-formatter/data-formatter-stl/libstdcpp/map/TestDataFormatterStdMap.py?rev=152570&r1=152325&r2=152570&view=diff
==============================================================================
--- lldb/trunk/test/functionalities/data-formatter/data-formatter-stl/libstdcpp/map/TestDataFormatterStdMap.py (original)
+++ lldb/trunk/test/functionalities/data-formatter/data-formatter-stl/libstdcpp/map/TestDataFormatterStdMap.py Mon Mar 12 14:47:17 2012
@@ -9,7 +9,7 @@
class StdMapDataFormatterTestCase(TestBase):
- mydir = os.path.join("functionalities", "data-formatter", "data-formatter-stl", "map")
+ mydir = os.path.join("functionalities", "data-formatter", "data-formatter-stl", "libstdcpp", "map")
@unittest2.skipUnless(sys.platform.startswith("darwin"), "requires Darwin")
def test_with_dsym_and_run_command(self):
Modified: lldb/trunk/test/functionalities/data-formatter/data-formatter-stl/libstdcpp/vector/Makefile
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/test/functionalities/data-formatter/data-formatter-stl/libstdcpp/vector/Makefile?rev=152570&r1=152325&r2=152570&view=diff
==============================================================================
--- lldb/trunk/test/functionalities/data-formatter/data-formatter-stl/libstdcpp/vector/Makefile (original)
+++ lldb/trunk/test/functionalities/data-formatter/data-formatter-stl/libstdcpp/vector/Makefile Mon Mar 12 14:47:17 2012
@@ -1,4 +1,4 @@
-LEVEL = ../../../../make
+LEVEL = ../../../../../make
CXX_SOURCES := main.cpp
Modified: lldb/trunk/test/functionalities/data-formatter/data-formatter-stl/libstdcpp/vector/TestDataFormatterStdVector.py
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/test/functionalities/data-formatter/data-formatter-stl/libstdcpp/vector/TestDataFormatterStdVector.py?rev=152570&r1=152325&r2=152570&view=diff
==============================================================================
--- lldb/trunk/test/functionalities/data-formatter/data-formatter-stl/libstdcpp/vector/TestDataFormatterStdVector.py (original)
+++ lldb/trunk/test/functionalities/data-formatter/data-formatter-stl/libstdcpp/vector/TestDataFormatterStdVector.py Mon Mar 12 14:47:17 2012
@@ -9,7 +9,7 @@
class StdVectorDataFormatterTestCase(TestBase):
- mydir = os.path.join("functionalities", "data-formatter", "data-formatter-stl", "vector")
+ mydir = os.path.join("functionalities", "data-formatter", "data-formatter-stl", "libstdcpp", "vector")
@unittest2.skipUnless(sys.platform.startswith("darwin"), "requires Darwin")
def test_with_dsym_and_run_command(self):
More information about the lldb-commits
mailing list