[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