Author: sivachandra
Date: Tue Mar 17 16:23:17 2015
New Revision: 232548

URL: http://llvm.org/viewvc/llvm-project?rev=232548&view=rev
Log:
Implement formatter for std::vector<bool, ...> of libstdc++ in Python.

Summary:
The existing formatter in C++ has been removed as it was not being used. 
The associated test TestDataFormatterStdVBool.py has been enabled for
both Clang and GCC on Linux.

Test Plan: dotest.py -p TestDataFormatterStdVBool

Reviewers: vharron, clayborg

Reviewed By: clayborg

Subscribers: lldb-commits

Differential Revision: http://reviews.llvm.org/D8390

Modified:
    lldb/trunk/examples/synthetic/gnu_libstdcpp.py
    lldb/trunk/include/lldb/DataFormatters/CXXFormatterFunctions.h
    lldb/trunk/source/DataFormatters/LibStdcpp.cpp
    
lldb/trunk/test/functionalities/data-formatter/data-formatter-stl/libstdcpp/vbool/TestDataFormatterStdVBool.py

Modified: lldb/trunk/examples/synthetic/gnu_libstdcpp.py
URL: 
http://llvm.org/viewvc/llvm-project/lldb/trunk/examples/synthetic/gnu_libstdcpp.py?rev=232548&r1=232547&r2=232548&view=diff
==============================================================================
--- lldb/trunk/examples/synthetic/gnu_libstdcpp.py (original)
+++ lldb/trunk/examples/synthetic/gnu_libstdcpp.py Tue Mar 17 16:23:17 2015
@@ -137,50 +137,134 @@ class StdListSynthProvider:
 
 class StdVectorSynthProvider:
 
+       class StdVectorImplementation(object):
+               def __init__(self, valobj):
+                       self.valobj = valobj
+                       self.count = None
+
+               def num_children(self):
+                        if self.count == None:
+                                self.count = self.num_children_impl()
+                        return self.count
+
+                def num_children_impl(self):
+                       try:
+                               start_val = self.start.GetValueAsUnsigned(0)
+                               finish_val = self.finish.GetValueAsUnsigned(0)
+                               end_val  = self.end.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 or end_val 
== 0:
+                                       return 0
+                               # Make sure start is less than finish
+                               if start_val >= finish_val:
+                                       return 0
+                               # Make sure finish is less than or equal to end 
of storage
+                               if finish_val > end_val:
+                                       return 0
+
+                               # if we have a struct (or other data type that 
the compiler pads to native word size)
+                               # this check might fail, unless the sizeof() we 
get is itself incremented to take the
+                               # padding bytes into account - on current clang 
it looks like this is the case
+                               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_at_index(self, index):
+                       logger = lldb.formatters.Logger.Logger()
+                       logger >> "Retrieving child " + str(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):
+                       # preemptively setting this to None - we might end up 
changing our mind later
+                       self.count = None
+                       try:
+                               impl = 
self.valobj.GetChildMemberWithName('_M_impl')
+                               self.start = 
impl.GetChildMemberWithName('_M_start')
+                               self.finish = 
impl.GetChildMemberWithName('_M_finish')
+                               self.end = 
impl.GetChildMemberWithName('_M_end_of_storage')
+                               self.data_type = 
self.start.GetType().GetPointeeType()
+                               self.data_size = self.data_type.GetByteSize()
+                               # if any of these objects is invalid, it means 
there is no point in trying to fetch anything
+                               if self.start.IsValid() and 
self.finish.IsValid() and self.end.IsValid() and self.data_type.IsValid():
+                                       self.count = None
+                               else:
+                                       self.count = 0
+                       except:
+                               pass
+                       return True
+
+       class StdVBoolImplementation(object):
+               def __init__(self, valobj, bool_type):
+                       self.valobj = valobj
+                       self.bool_type = bool_type
+                       self.valid = False
+
+               def num_children(self):
+                       if self.valid:
+                               start = self.start_p.GetValueAsUnsigned(0)
+                               finish = self.finish_p.GetValueAsUnsigned(0)
+                               offset = self.offset.GetValueAsUnsigned(0)
+                               if finish >= start:
+                                       return (finish - start) * 8 + offset
+                       return 0
+
+               def get_child_at_index(self, index):
+                       if index >= self.num_children():
+                               return None
+                       byte_offset = index / 8
+                       bit_offset = index % 8
+                       data = self.start_p.GetPointeeData()
+                       bit = data.GetUnsignedInt8(lldb.SBError(), byte_offset) 
& (1 << bit_offset)
+                       if bit != 0:
+                               value_expr = "(bool)true"
+                       else:
+                               value_expr = "(bool)false"
+                       return self.valobj.CreateValueFromExpression("[%d]" % 
index, value_expr)
+
+               def update(self):
+                       try:
+                               m_impl = 
self.valobj.GetChildMemberWithName('_M_impl')
+                               self.m_start = 
m_impl.GetChildMemberWithName('_M_start')
+                               self.m_finish = 
m_impl.GetChildMemberWithName('_M_finish')
+                               self.start_p = 
self.m_start.GetChildMemberWithName('_M_p')
+                               self.finish_p = 
self.m_finish.GetChildMemberWithName('_M_p')
+                               self.offset = 
self.m_finish.GetChildMemberWithName('_M_offset')
+                               self.valid = True
+                       except:
+                               self.valid = False
+                       return True
+
        def __init__(self, valobj, dict):
                logger = lldb.formatters.Logger.Logger()
-               self.count = None
-               self.valobj = valobj
+               first_template_arg_type = 
valobj.GetType().GetTemplateArgumentType(0)
+               if str(first_template_arg_type.GetName()) == "bool":
+                       self.impl = self.StdVBoolImplementation(valobj, 
first_template_arg_type)
+               else:
+                       self.impl = self.StdVectorImplementation(valobj)
                logger >> "Providing synthetic children for a vector named " + 
str(valobj.GetName())
 
        def num_children(self):
-               if self.count == None:
-                       self.count = self.num_children_impl()
-               return self.count
-
-       def num_children_impl(self):
-               try:
-                       start_val = self.start.GetValueAsUnsigned(0)
-                       finish_val = self.finish.GetValueAsUnsigned(0)
-                       end_val  = self.end.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 or end_val == 0:
-                               return 0
-                       # Make sure start is less than finish
-                       if start_val >= finish_val:
-                               return 0
-                       # Make sure finish is less than or equal to end of 
storage
-                       if finish_val > end_val:
-                               return 0
-
-                       # if we have a struct (or other data type that the 
compiler pads to native word size)
-                       # this check might fail, unless the sizeof() we get is 
itself incremented to take the
-                       # padding bytes into account - on current clang it 
looks like this is the case
-                       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;
+               return self.impl.num_children()
 
        def get_child_index(self,name):
                try:
@@ -188,37 +272,11 @@ class StdVectorSynthProvider:
                except:
                        return -1
 
-       def get_child_at_index(self,index):
-               logger = lldb.formatters.Logger.Logger()
-               logger >> "Retrieving child " + str(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 get_child_at_index(self, index):
+               return self.impl.get_child_at_index(index)
 
        def update(self):
-               # preemptively setting this to None - we might end up changing 
our mind later
-               self.count = None
-               try:
-                       impl = self.valobj.GetChildMemberWithName('_M_impl')
-                       self.start = impl.GetChildMemberWithName('_M_start')
-                       self.finish = impl.GetChildMemberWithName('_M_finish')
-                       self.end = 
impl.GetChildMemberWithName('_M_end_of_storage')
-                       self.data_type = self.start.GetType().GetPointeeType()
-                       self.data_size = self.data_type.GetByteSize()
-                       # if any of these objects is invalid, it means there is 
no point in trying to fetch anything
-                       if self.start.IsValid() and self.finish.IsValid() and 
self.end.IsValid() and self.data_type.IsValid():
-                               self.count = None
-                       else:
-                               self.count = 0
-               except:
-                       pass
-                       
+               return self.impl.update()
 
        def has_children(self):
                return True

Modified: lldb/trunk/include/lldb/DataFormatters/CXXFormatterFunctions.h
URL: 
http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/DataFormatters/CXXFormatterFunctions.h?rev=232548&r1=232547&r2=232548&view=diff
==============================================================================
--- lldb/trunk/include/lldb/DataFormatters/CXXFormatterFunctions.h (original)
+++ lldb/trunk/include/lldb/DataFormatters/CXXFormatterFunctions.h Tue Mar 17 
16:23:17 2015
@@ -232,37 +232,6 @@ namespace lldb_private {
         bool
         LibcxxContainerSummaryProvider (ValueObject& valobj, Stream& stream, 
const TypeSummaryOptions& options);
         
-        class LibstdcppVectorBoolSyntheticFrontEnd : public 
SyntheticChildrenFrontEnd
-        {
-        public:
-            LibstdcppVectorBoolSyntheticFrontEnd (lldb::ValueObjectSP 
valobj_sp);
-            
-            virtual size_t
-            CalculateNumChildren ();
-            
-            virtual lldb::ValueObjectSP
-            GetChildAtIndex (size_t idx);
-            
-            virtual bool
-            Update();
-            
-            virtual bool
-            MightHaveChildren ();
-            
-            virtual size_t
-            GetIndexOfChildWithName (const ConstString &name);
-            
-            virtual
-            ~LibstdcppVectorBoolSyntheticFrontEnd ();
-        private:
-            ExecutionContextRef m_exe_ctx_ref;
-            uint64_t m_count;
-            lldb::addr_t m_base_data_address;
-            EvaluateExpressionOptions m_options;
-        };
-        
-        SyntheticChildrenFrontEnd* LibstdcppVectorBoolSyntheticFrontEndCreator 
(CXXSyntheticChildren*, lldb::ValueObjectSP);
-        
         class LibstdcppMapIteratorSyntheticFrontEnd : public 
SyntheticChildrenFrontEnd
         {
         public:

Modified: lldb/trunk/source/DataFormatters/LibStdcpp.cpp
URL: 
http://llvm.org/viewvc/llvm-project/lldb/trunk/source/DataFormatters/LibStdcpp.cpp?rev=232548&r1=232547&r2=232548&view=diff
==============================================================================
--- lldb/trunk/source/DataFormatters/LibStdcpp.cpp (original)
+++ lldb/trunk/source/DataFormatters/LibStdcpp.cpp Tue Mar 17 16:23:17 2015
@@ -25,175 +25,6 @@ using namespace lldb;
 using namespace lldb_private;
 using namespace lldb_private::formatters;
 
-lldb_private::formatters::LibstdcppVectorBoolSyntheticFrontEnd::LibstdcppVectorBoolSyntheticFrontEnd
 (lldb::ValueObjectSP valobj_sp) :
-SyntheticChildrenFrontEnd(*valobj_sp.get()),
-m_exe_ctx_ref(),
-m_count(0),
-m_base_data_address(0),
-m_options()
-{
-    if (valobj_sp)
-        Update();
-    m_options.SetCoerceToId(false);
-    m_options.SetUnwindOnError(true);
-    m_options.SetKeepInMemory(true);
-    m_options.SetUseDynamic(lldb::eDynamicCanRunTarget);
-}
-
-size_t
-lldb_private::formatters::LibstdcppVectorBoolSyntheticFrontEnd::CalculateNumChildren
 ()
-{
-    return m_count;
-}
-
-lldb::ValueObjectSP
-lldb_private::formatters::LibstdcppVectorBoolSyntheticFrontEnd::GetChildAtIndex
 (size_t idx)
-{
-    if (idx >= m_count)
-        return ValueObjectSP();
-    if (m_base_data_address == 0 || m_count == 0)
-        return ValueObjectSP();
-    size_t byte_idx = (idx >> 3); // divide by 8 to get byte index
-    size_t bit_index = (idx & 7); // efficient idx % 8 for bit index
-    lldb::addr_t byte_location = m_base_data_address + byte_idx;
-    ProcessSP process_sp(m_exe_ctx_ref.GetProcessSP());
-    if (!process_sp)
-        return ValueObjectSP();
-    uint8_t byte = 0;
-    uint8_t mask = 0;
-    Error err;
-    size_t bytes_read = process_sp->ReadMemory(byte_location, &byte, 1, err);
-    if (err.Fail() || bytes_read == 0)
-        return ValueObjectSP();
-    switch (bit_index)
-    {
-        case 0:
-            mask = 1; break;
-        case 1:
-            mask = 2; break;
-        case 2:
-            mask = 4; break;
-        case 3:
-            mask = 8; break;
-        case 4:
-            mask = 16; break;
-        case 5:
-            mask = 32; break;
-        case 6:
-            mask = 64; break;
-        case 7:
-            mask = 128; break;
-        default:
-            return ValueObjectSP();
-    }
-    bool bit_set = ((byte & mask) != 0);
-    Target& target(process_sp->GetTarget());
-    ValueObjectSP retval_sp;
-    if (bit_set)
-        target.EvaluateExpression("(bool)true", NULL, retval_sp);
-    else
-        target.EvaluateExpression("(bool)false", NULL, retval_sp);
-    StreamString name; name.Printf("[%" PRIu64 "]", (uint64_t)idx);
-    if (retval_sp)
-        retval_sp->SetName(ConstString(name.GetData()));
-    return retval_sp;
-}
-
-/*((std::vector<std::allocator<bool> >) vBool = {
- (std::_Bvector_base<std::allocator<bool> >) 
std::_Bvector_base<std::allocator<bool> > = {
- (std::_Bvector_base<std::allocator<bool> >::_Bvector_impl) _M_impl = {
- (std::_Bit_iterator) _M_start = {
- (std::_Bit_iterator_base) std::_Bit_iterator_base = {
- (_Bit_type *) _M_p = 0x0016b160
- (unsigned int) _M_offset = 0
- }
- }
- (std::_Bit_iterator) _M_finish = {
- (std::_Bit_iterator_base) std::_Bit_iterator_base = {
- (_Bit_type *) _M_p = 0x0016b16c
- (unsigned int) _M_offset = 16
- }
- }
- (_Bit_type *) _M_end_of_storage = 0x0016b170
- }
- }
- }
- */
-
-bool
-lldb_private::formatters::LibstdcppVectorBoolSyntheticFrontEnd::Update()
-{
-    ValueObjectSP valobj_sp = m_backend.GetSP();
-    if (!valobj_sp)
-        return false;
-    if (!valobj_sp)
-        return false;
-    m_exe_ctx_ref = valobj_sp->GetExecutionContextRef();
-    
-    ValueObjectSP 
m_impl_sp(valobj_sp->GetChildMemberWithName(ConstString("_M_impl"), true));
-    if (!m_impl_sp)
-        return false;
-    
-    ValueObjectSP 
m_start_sp(m_impl_sp->GetChildMemberWithName(ConstString("_M_start"), true));
-    ValueObjectSP 
m_finish_sp(m_impl_sp->GetChildMemberWithName(ConstString("_M_finish"), true));
-    
-    ValueObjectSP start_p_sp, finish_p_sp, finish_offset_sp;
-    
-    if (!m_start_sp || !m_finish_sp)
-        return false;
-    
-    start_p_sp = m_start_sp->GetChildMemberWithName(ConstString("_M_p"), true);
-    finish_p_sp = m_finish_sp->GetChildMemberWithName(ConstString("_M_p"), 
true);
-    finish_offset_sp = 
m_finish_sp->GetChildMemberWithName(ConstString("_M_offset"), true);
-    
-    if (!start_p_sp || !finish_offset_sp || !finish_p_sp)
-        return false;
-    
-    m_base_data_address = start_p_sp->GetValueAsUnsigned(0);
-    if (!m_base_data_address)
-        return false;
-    
-    lldb::addr_t end_data_address(finish_p_sp->GetValueAsUnsigned(0));
-    if (!end_data_address)
-        return false;
-    
-    if (end_data_address < m_base_data_address)
-        return false;
-    else
-        m_count = finish_offset_sp->GetValueAsUnsigned(0) + 
(end_data_address-m_base_data_address)*8;
-    
-    return true;
-}
-
-bool
-lldb_private::formatters::LibstdcppVectorBoolSyntheticFrontEnd::MightHaveChildren
 ()
-{
-    return true;
-}
-
-size_t
-lldb_private::formatters::LibstdcppVectorBoolSyntheticFrontEnd::GetIndexOfChildWithName
 (const ConstString &name)
-{
-    if (!m_count || !m_base_data_address)
-        return UINT32_MAX;
-    const char* item_name = name.GetCString();
-    uint32_t idx = ExtractIndexFromString(item_name);
-    if (idx < UINT32_MAX && idx >= CalculateNumChildren())
-        return UINT32_MAX;
-    return idx;
-}
-
-lldb_private::formatters::LibstdcppVectorBoolSyntheticFrontEnd::~LibstdcppVectorBoolSyntheticFrontEnd
 ()
-{}
-
-SyntheticChildrenFrontEnd*
-lldb_private::formatters::LibstdcppVectorBoolSyntheticFrontEndCreator 
(CXXSyntheticChildren*, lldb::ValueObjectSP valobj_sp)
-{
-    if (!valobj_sp)
-        return NULL;
-    return (new LibstdcppVectorBoolSyntheticFrontEnd(valobj_sp));
-}
-
 /*
  (std::_Rb_tree_iterator<std::pair<const int, std::basic_string<char, 
std::char_traits<char>, std::allocator<char> > > >) ibeg = {
  (_Base_ptr) _M_node = 0x0000000100103910 {

Modified: 
lldb/trunk/test/functionalities/data-formatter/data-formatter-stl/libstdcpp/vbool/TestDataFormatterStdVBool.py
URL: 
http://llvm.org/viewvc/llvm-project/lldb/trunk/test/functionalities/data-formatter/data-formatter-stl/libstdcpp/vbool/TestDataFormatterStdVBool.py?rev=232548&r1=232547&r2=232548&view=diff
==============================================================================
--- 
lldb/trunk/test/functionalities/data-formatter/data-formatter-stl/libstdcpp/vbool/TestDataFormatterStdVBool.py
 (original)
+++ 
lldb/trunk/test/functionalities/data-formatter/data-formatter-stl/libstdcpp/vbool/TestDataFormatterStdVBool.py
 Tue Mar 17 16:23:17 2015
@@ -21,10 +21,6 @@ class StdVBoolDataFormatterTestCase(Test
         self.data_formatter_commands()
 
     @expectedFailureFreeBSD("llvm.org/pr20548") # fails to build on 
lab.llvm.org buildbot
-    @expectedFailureLinux # non-core functionality, need to reenable and fix
-                          # later (DES 2014.11.07). Most likely failing because
-                          # of mis-match is version of libstdc++ supported by
-                          # the data-formatters.
     @dwarf_test
     @skipIfWindows # http://llvm.org/pr21800
     @skipIfDarwin
@@ -39,7 +35,6 @@ class StdVBoolDataFormatterTestCase(Test
         # Find the line number to break at.
         self.line = line_number('main.cpp', '// Set break point at this line.')
 
-    @expectedFailureGcc # llvm.org/pr15301: lldb does not print the correct 
sizes of STL containers when building with GCC
     @expectedFailureIcc # llvm.org/pr15301: lldb does not print the correct 
sizes of STL containers when building with ICC
     def data_formatter_commands(self):
         """Test that that file and class static variables display correctly."""


_______________________________________________
lldb-commits mailing list
[email protected]
http://lists.cs.uiuc.edu/mailman/listinfo/lldb-commits

Reply via email to