diff options
author | Enrico Granata <egranata@apple.com> | 2012-03-12 19:47:17 +0000 |
---|---|---|
committer | Enrico Granata <egranata@apple.com> | 2012-03-12 19:47:17 +0000 |
commit | c7f873064bdd2059d0a8fe4d0066b0a920dcc094 (patch) | |
tree | e7fef529a4f5855d0f5f54a81f54957619085786 | |
parent | 701a6b473dd0b91e30a212ddd86f14307fa17bbc (diff) | |
download | bcm5719-llvm-c7f873064bdd2059d0a8fe4d0066b0a920dcc094.tar.gz bcm5719-llvm-c7f873064bdd2059d0a8fe4d0066b0a920dcc094.zip |
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
llvm-svn: 152570
23 files changed, 1417 insertions, 7 deletions
diff --git a/lldb/examples/synthetic/libcxx.py b/lldb/examples/synthetic/libcxx.py new file mode 100644 index 00000000000..5e405df451a --- /dev/null +++ b/lldb/examples/synthetic/libcxx.py @@ -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") diff --git a/lldb/include/lldb/Core/FormatManager.h b/lldb/include/lldb/Core/FormatManager.h index 1614b068186..2dec8c7ff6f 100644 --- a/lldb/include/lldb/Core/FormatManager.h +++ b/lldb/include/lldb/Core/FormatManager.h @@ -670,6 +670,7 @@ private: 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 @@ private: LoadSTLFormatters(); void + LoadLibcxxFormatters(); + + void LoadSystemFormatters(); #ifndef LLDB_DISABLE_PYTHON diff --git a/lldb/scripts/Python/finish-swig-Python-LLDB.sh b/lldb/scripts/Python/finish-swig-Python-LLDB.sh index 96780925cd0..b2c194984af 100755 --- a/lldb/scripts/Python/finish-swig-Python-LLDB.sh +++ b/lldb/scripts/Python/finish-swig-Python-LLDB.sh @@ -184,6 +184,20 @@ else 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 diff --git a/lldb/source/Core/FormatManager.cpp b/lldb/source/Core/FormatManager.cpp index 84d26cf0c3e..1cda49e6498 100644 --- a/lldb/source/Core/FormatManager.cpp +++ b/lldb/source/Core/FormatManager.cpp @@ -580,6 +580,7 @@ FormatManager::FormatManager() : 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 @@ FormatManager::FormatManager() : LoadSystemFormatters(); LoadSTLFormatters(); + LoadLibcxxFormatters(); #ifndef LLDB_DISABLE_PYTHON LoadObjCFormatters(); #endif @@ -600,6 +602,7 @@ FormatManager::FormatManager() : //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 @@ FormatManager::LoadSTLFormatters() } 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) diff --git a/lldb/source/Interpreter/ScriptInterpreterPython.cpp b/lldb/source/Interpreter/ScriptInterpreterPython.cpp index 7a9140f0a2a..79b4449d356 100644 --- a/lldb/source/Interpreter/ScriptInterpreterPython.cpp +++ b/lldb/source/Interpreter/ScriptInterpreterPython.cpp @@ -279,7 +279,7 @@ ScriptInterpreterPython::ScriptInterpreterPython (CommandInterpreter &interprete 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 diff --git a/lldb/test/functionalities/data-formatter/data-formatter-stl/libcxx/list/Makefile b/lldb/test/functionalities/data-formatter/data-formatter-stl/libcxx/list/Makefile new file mode 100644 index 00000000000..f2f2b3f2fb8 --- /dev/null +++ b/lldb/test/functionalities/data-formatter/data-formatter-stl/libcxx/list/Makefile @@ -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 diff --git a/lldb/test/functionalities/data-formatter/data-formatter-stl/libcxx/list/TestDataFormatterLibcxxList.py b/lldb/test/functionalities/data-formatter/data-formatter-stl/libcxx/list/TestDataFormatterLibcxxList.py new file mode 100644 index 00000000000..fa2a84e22c6 --- /dev/null +++ b/lldb/test/functionalities/data-formatter/data-formatter-stl/libcxx/list/TestDataFormatterLibcxxList.py @@ -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() diff --git a/lldb/test/functionalities/data-formatter/data-formatter-stl/libcxx/list/main.cpp b/lldb/test/functionalities/data-formatter/data-formatter-stl/libcxx/list/main.cpp new file mode 100644 index 00000000000..07ee6cf2c44 --- /dev/null +++ b/lldb/test/functionalities/data-formatter/data-formatter-stl/libcxx/list/main.cpp @@ -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 diff --git a/lldb/test/functionalities/data-formatter/data-formatter-stl/libcxx/map/Makefile b/lldb/test/functionalities/data-formatter/data-formatter-stl/libcxx/map/Makefile new file mode 100644 index 00000000000..f2f2b3f2fb8 --- /dev/null +++ b/lldb/test/functionalities/data-formatter/data-formatter-stl/libcxx/map/Makefile @@ -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 diff --git a/lldb/test/functionalities/data-formatter/data-formatter-stl/libcxx/map/TestDataFormatterLibccMap.py b/lldb/test/functionalities/data-formatter/data-formatter-stl/libcxx/map/TestDataFormatterLibccMap.py new file mode 100644 index 00000000000..2da88eee5d4 --- /dev/null +++ b/lldb/test/functionalities/data-formatter/data-formatter-stl/libcxx/map/TestDataFormatterLibccMap.py @@ -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() diff --git a/lldb/test/functionalities/data-formatter/data-formatter-stl/map/main.cpp b/lldb/test/functionalities/data-formatter/data-formatter-stl/libcxx/map/main.cpp index 58ab9980e14..58ab9980e14 100644 --- a/lldb/test/functionalities/data-formatter/data-formatter-stl/map/main.cpp +++ b/lldb/test/functionalities/data-formatter/data-formatter-stl/libcxx/map/main.cpp diff --git a/lldb/test/functionalities/data-formatter/data-formatter-stl/libcxx/vector/Makefile b/lldb/test/functionalities/data-formatter/data-formatter-stl/libcxx/vector/Makefile new file mode 100644 index 00000000000..f2f2b3f2fb8 --- /dev/null +++ b/lldb/test/functionalities/data-formatter/data-formatter-stl/libcxx/vector/Makefile @@ -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 diff --git a/lldb/test/functionalities/data-formatter/data-formatter-stl/libcxx/vector/TestDataFormatterLibcxxVector.py b/lldb/test/functionalities/data-formatter/data-formatter-stl/libcxx/vector/TestDataFormatterLibcxxVector.py new file mode 100644 index 00000000000..b90916a5dda --- /dev/null +++ b/lldb/test/functionalities/data-formatter/data-formatter-stl/libcxx/vector/TestDataFormatterLibcxxVector.py @@ -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() diff --git a/lldb/test/functionalities/data-formatter/data-formatter-stl/libcxx/vector/main.cpp b/lldb/test/functionalities/data-formatter/data-formatter-stl/libcxx/vector/main.cpp new file mode 100644 index 00000000000..a97db4cb21b --- /dev/null +++ b/lldb/test/functionalities/data-formatter/data-formatter-stl/libcxx/vector/main.cpp @@ -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; +} diff --git a/lldb/test/functionalities/data-formatter/data-formatter-stl/list/Makefile b/lldb/test/functionalities/data-formatter/data-formatter-stl/libstdcpp/list/Makefile index ee6b9cc62b4..d473b144a8a 100644 --- a/lldb/test/functionalities/data-formatter/data-formatter-stl/list/Makefile +++ b/lldb/test/functionalities/data-formatter/data-formatter-stl/libstdcpp/list/Makefile @@ -1,4 +1,4 @@ -LEVEL = ../../../../make +LEVEL = ../../../../../make CXX_SOURCES := main.cpp diff --git a/lldb/test/functionalities/data-formatter/data-formatter-stl/list/TestDataFormatterStdList.py b/lldb/test/functionalities/data-formatter/data-formatter-stl/libstdcpp/list/TestDataFormatterStdList.py index 312669a4aa7..f65cca2e84f 100644 --- a/lldb/test/functionalities/data-formatter/data-formatter-stl/list/TestDataFormatterStdList.py +++ b/lldb/test/functionalities/data-formatter/data-formatter-stl/libstdcpp/list/TestDataFormatterStdList.py @@ -9,7 +9,7 @@ from lldbtest import * 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): diff --git a/lldb/test/functionalities/data-formatter/data-formatter-stl/list/main.cpp b/lldb/test/functionalities/data-formatter/data-formatter-stl/libstdcpp/list/main.cpp index 87ea65c5766..87ea65c5766 100644 --- a/lldb/test/functionalities/data-formatter/data-formatter-stl/list/main.cpp +++ b/lldb/test/functionalities/data-formatter/data-formatter-stl/libstdcpp/list/main.cpp diff --git a/lldb/test/functionalities/data-formatter/data-formatter-stl/map/Makefile b/lldb/test/functionalities/data-formatter/data-formatter-stl/libstdcpp/map/Makefile index ee6b9cc62b4..d473b144a8a 100644 --- a/lldb/test/functionalities/data-formatter/data-formatter-stl/map/Makefile +++ b/lldb/test/functionalities/data-formatter/data-formatter-stl/libstdcpp/map/Makefile @@ -1,4 +1,4 @@ -LEVEL = ../../../../make +LEVEL = ../../../../../make CXX_SOURCES := main.cpp diff --git a/lldb/test/functionalities/data-formatter/data-formatter-stl/map/TestDataFormatterStdMap.py b/lldb/test/functionalities/data-formatter/data-formatter-stl/libstdcpp/map/TestDataFormatterStdMap.py index f890d536f58..9ac78c94117 100644 --- a/lldb/test/functionalities/data-formatter/data-formatter-stl/map/TestDataFormatterStdMap.py +++ b/lldb/test/functionalities/data-formatter/data-formatter-stl/libstdcpp/map/TestDataFormatterStdMap.py @@ -9,7 +9,7 @@ from lldbtest import * 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): diff --git a/lldb/test/functionalities/data-formatter/data-formatter-stl/libstdcpp/map/main.cpp b/lldb/test/functionalities/data-formatter/data-formatter-stl/libstdcpp/map/main.cpp new file mode 100644 index 00000000000..58ab9980e14 --- /dev/null +++ b/lldb/test/functionalities/data-formatter/data-formatter-stl/libstdcpp/map/main.cpp @@ -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 diff --git a/lldb/test/functionalities/data-formatter/data-formatter-stl/vector/Makefile b/lldb/test/functionalities/data-formatter/data-formatter-stl/libstdcpp/vector/Makefile index ee6b9cc62b4..d473b144a8a 100644 --- a/lldb/test/functionalities/data-formatter/data-formatter-stl/vector/Makefile +++ b/lldb/test/functionalities/data-formatter/data-formatter-stl/libstdcpp/vector/Makefile @@ -1,4 +1,4 @@ -LEVEL = ../../../../make +LEVEL = ../../../../../make CXX_SOURCES := main.cpp diff --git a/lldb/test/functionalities/data-formatter/data-formatter-stl/vector/TestDataFormatterStdVector.py b/lldb/test/functionalities/data-formatter/data-formatter-stl/libstdcpp/vector/TestDataFormatterStdVector.py index 7895f6553b5..27c8200a290 100644 --- a/lldb/test/functionalities/data-formatter/data-formatter-stl/vector/TestDataFormatterStdVector.py +++ b/lldb/test/functionalities/data-formatter/data-formatter-stl/libstdcpp/vector/TestDataFormatterStdVector.py @@ -9,7 +9,7 @@ from lldbtest import * 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): diff --git a/lldb/test/functionalities/data-formatter/data-formatter-stl/vector/main.cpp b/lldb/test/functionalities/data-formatter/data-formatter-stl/libstdcpp/vector/main.cpp index 177c67db35e..177c67db35e 100644 --- a/lldb/test/functionalities/data-formatter/data-formatter-stl/vector/main.cpp +++ b/lldb/test/functionalities/data-formatter/data-formatter-stl/libstdcpp/vector/main.cpp |