mirror of
https://github.com/intel/llvm.git
synced 2026-01-17 23:45:25 +08:00
<rdar://problem/12953018>
Synthetic children and summary for std::vector<bool> (for both libcxx and libstdcpp). std::vector<bool> is a special case and is custom-implemented to be a vector of bits, which means we failed to handle it with the standard std::vector<T> formatter. This checkin provides custom formatters that work correctly llvm-svn: 174333
This commit is contained in:
@@ -15,6 +15,7 @@
|
||||
|
||||
#include "lldb/Core/ConstString.h"
|
||||
#include "lldb/DataFormatters/FormatClasses.h"
|
||||
#include "lldb/Target/Target.h"
|
||||
|
||||
#include "clang/AST/ASTContext.h"
|
||||
|
||||
@@ -348,6 +349,69 @@ namespace lldb_private {
|
||||
|
||||
SyntheticChildrenFrontEnd* NSDictionarySyntheticFrontEndCreator (CXXSyntheticChildren*, lldb::ValueObjectSP);
|
||||
|
||||
class LibcxxVectorBoolSyntheticFrontEnd : public SyntheticChildrenFrontEnd
|
||||
{
|
||||
public:
|
||||
LibcxxVectorBoolSyntheticFrontEnd (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
|
||||
~LibcxxVectorBoolSyntheticFrontEnd ();
|
||||
private:
|
||||
ExecutionContextRef m_exe_ctx_ref;
|
||||
uint64_t m_count;
|
||||
lldb::addr_t m_base_data_address;
|
||||
EvaluateExpressionOptions m_options;
|
||||
};
|
||||
|
||||
SyntheticChildrenFrontEnd* LibcxxVectorBoolSyntheticFrontEndCreator (CXXSyntheticChildren*, lldb::ValueObjectSP);
|
||||
|
||||
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);
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1787,6 +1787,322 @@ lldb_private::formatters::NSDictionaryMSyntheticFrontEnd::GetChildAtIndex (size_
|
||||
return dict_item.valobj_sp;
|
||||
}
|
||||
|
||||
lldb_private::formatters::LibcxxVectorBoolSyntheticFrontEnd::LibcxxVectorBoolSyntheticFrontEnd (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)
|
||||
.SetUnwindOnError(true)
|
||||
.SetKeepInMemory(true)
|
||||
.SetUseDynamic(lldb::eDynamicCanRunTarget);
|
||||
}
|
||||
|
||||
size_t
|
||||
lldb_private::formatters::LibcxxVectorBoolSyntheticFrontEnd::CalculateNumChildren ()
|
||||
{
|
||||
return m_count;
|
||||
}
|
||||
|
||||
lldb::ValueObjectSP
|
||||
lldb_private::formatters::LibcxxVectorBoolSyntheticFrontEnd::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("[%zu]",idx);
|
||||
if (retval_sp)
|
||||
retval_sp->SetName(ConstString(name.GetData()));
|
||||
return retval_sp;
|
||||
}
|
||||
|
||||
/*(std::__1::vector<std::__1::allocator<bool> >) vBool = {
|
||||
__begin_ = 0x00000001001000e0
|
||||
__size_ = 56
|
||||
__cap_alloc_ = {
|
||||
std::__1::__libcpp_compressed_pair_imp<unsigned long, std::__1::allocator<unsigned long> > = {
|
||||
__first_ = 1
|
||||
}
|
||||
}
|
||||
}*/
|
||||
|
||||
bool
|
||||
lldb_private::formatters::LibcxxVectorBoolSyntheticFrontEnd::Update()
|
||||
{
|
||||
ValueObjectSP valobj_sp = m_backend.GetSP();
|
||||
if (!valobj_sp)
|
||||
return false;
|
||||
if (valobj_sp->IsDynamic())
|
||||
valobj_sp = valobj_sp->GetStaticValue();
|
||||
if (!valobj_sp)
|
||||
return false;
|
||||
m_exe_ctx_ref = valobj_sp->GetExecutionContextRef();
|
||||
ValueObjectSP size_sp(valobj_sp->GetChildMemberWithName(ConstString("__size_"), true));
|
||||
if (!size_sp)
|
||||
return false;
|
||||
m_count = size_sp->GetValueAsUnsigned(0);
|
||||
if (!m_count)
|
||||
return true;
|
||||
ValueObjectSP begin_sp(valobj_sp->GetChildMemberWithName(ConstString("__begin_"), true));
|
||||
if (!begin_sp)
|
||||
{
|
||||
m_count = 0;
|
||||
return false;
|
||||
}
|
||||
m_base_data_address = begin_sp->GetValueAsUnsigned(0);
|
||||
if (!m_base_data_address)
|
||||
{
|
||||
m_count = 0;
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
lldb_private::formatters::LibcxxVectorBoolSyntheticFrontEnd::MightHaveChildren ()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
size_t
|
||||
lldb_private::formatters::LibcxxVectorBoolSyntheticFrontEnd::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::LibcxxVectorBoolSyntheticFrontEnd::~LibcxxVectorBoolSyntheticFrontEnd ()
|
||||
{}
|
||||
|
||||
SyntheticChildrenFrontEnd*
|
||||
lldb_private::formatters::LibcxxVectorBoolSyntheticFrontEndCreator (CXXSyntheticChildren*, lldb::ValueObjectSP valobj_sp)
|
||||
{
|
||||
if (!valobj_sp)
|
||||
return NULL;
|
||||
return (new LibcxxVectorBoolSyntheticFrontEnd(valobj_sp));
|
||||
}
|
||||
|
||||
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)
|
||||
.SetUnwindOnError(true)
|
||||
.SetKeepInMemory(true)
|
||||
.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("[%zu]",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->IsDynamic())
|
||||
valobj_sp = valobj_sp->GetStaticValue();
|
||||
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));
|
||||
}
|
||||
|
||||
template bool
|
||||
lldb_private::formatters::NSDictionarySummaryProvider<true> (ValueObject&, Stream&) ;
|
||||
|
||||
|
||||
@@ -561,6 +561,13 @@ FormatManager::LoadLibStdcppFormatters()
|
||||
gnu_category_sp->GetRegexSummaryNavigator()->Add(RegularExpressionSP(new RegularExpression("^std::list<.+>(( )?&)?$")),
|
||||
TypeSummaryImplSP(new StringSummaryFormat(stl_summary_flags,
|
||||
"size=${svar%#}")));
|
||||
|
||||
gnu_category_sp->GetSummaryNavigator()->Add(ConstString("std::vector<std::allocator<bool> >"),
|
||||
TypeSummaryImplSP(new StringSummaryFormat(stl_summary_flags, "size=${svar%#}")));
|
||||
|
||||
gnu_category_sp->GetSyntheticNavigator()->Add(ConstString("std::vector<std::allocator<bool> >"),
|
||||
SyntheticChildrenSP(new CXXSyntheticChildren(stl_synth_flags,"libc++ std::vector<bool> synthetic children",lldb_private::formatters::LibstdcppVectorBoolSyntheticFrontEndCreator)));
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -633,7 +640,10 @@ FormatManager::LoadLibcxxFormatters()
|
||||
|
||||
// this summary prevails on the regex std::vector<> because we do exact matches before regex ones
|
||||
libcxx_category_sp->GetSummaryNavigator()->Add(ConstString("std::__1::vector<std::__1::allocator<bool> >"),
|
||||
TypeSummaryImplSP(new StringSummaryFormat(stl_summary_flags, "size=${var.__size_}")));
|
||||
TypeSummaryImplSP(new StringSummaryFormat(stl_summary_flags, "size=${svar%#}")));
|
||||
|
||||
libcxx_category_sp->GetSyntheticNavigator()->Add(ConstString("std::__1::vector<std::__1::allocator<bool> >"),
|
||||
SyntheticChildrenSP(new CXXSyntheticChildren(stl_synth_flags,"libc++ std::vector<bool> synthetic children",lldb_private::formatters::LibcxxVectorBoolSyntheticFrontEndCreator)));
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
LEVEL = ../../../../../make
|
||||
|
||||
CXX_SOURCES := main.cpp
|
||||
|
||||
include $(LEVEL)/Makefile.rules
|
||||
|
||||
CXXFLAGS += -stdlib=libc++ -O0
|
||||
LDFLAGS += -stdlib=libc++
|
||||
@@ -0,0 +1,70 @@
|
||||
"""
|
||||
Test lldb data formatter subsystem.
|
||||
"""
|
||||
|
||||
import os, time
|
||||
import unittest2
|
||||
import lldb
|
||||
from lldbtest import *
|
||||
import lldbutil
|
||||
|
||||
class LibcxxVBoolDataFormatterTestCase(TestBase):
|
||||
|
||||
mydir = os.path.join("functionalities", "data-formatter", "data-formatter-stl", "libcxx", "vbool")
|
||||
|
||||
@unittest2.skipUnless(sys.platform.startswith("darwin"), "requires Darwin")
|
||||
@dsym_test
|
||||
def test_with_dsym_and_run_command(self):
|
||||
"""Test data formatter commands."""
|
||||
self.buildDsym()
|
||||
self.data_formatter_commands()
|
||||
|
||||
@skipOnLinux # No standard locations for libc++ on Linux, so skip for now
|
||||
@dwarf_test
|
||||
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)
|
||||
|
||||
lldbutil.run_break_set_by_file_and_line (self, "main.cpp", self.line, num_expected_locations=-1)
|
||||
|
||||
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.expect("frame variable vBool",
|
||||
substrs = ['size=49','[0] = false','[1] = true','[18] = false','[27] = true','[36] = false','[47] = true','[48] = true'])
|
||||
|
||||
self.expect("expr vBool",
|
||||
substrs = ['size=49','[0] = false','[1] = true','[18] = false','[27] = true','[36] = false','[47] = true','[48] = true'])
|
||||
|
||||
if __name__ == '__main__':
|
||||
import atexit
|
||||
lldb.SBDebugger.Initialize()
|
||||
atexit.register(lambda: lldb.SBDebugger.Terminate())
|
||||
unittest2.main()
|
||||
@@ -0,0 +1,69 @@
|
||||
#include <string>
|
||||
#ifdef _LIBCPP_INLINE_VISIBILITY
|
||||
#undef _LIBCPP_INLINE_VISIBILITY
|
||||
#endif
|
||||
#define _LIBCPP_INLINE_VISIBILITY
|
||||
|
||||
#include <vector>
|
||||
|
||||
int main()
|
||||
{
|
||||
std::vector<bool> vBool;
|
||||
|
||||
vBool.push_back(false);
|
||||
vBool.push_back(true);
|
||||
vBool.push_back(false);
|
||||
vBool.push_back(true);
|
||||
vBool.push_back(false);
|
||||
vBool.push_back(true);
|
||||
vBool.push_back(false);
|
||||
vBool.push_back(true);
|
||||
|
||||
vBool.push_back(false);
|
||||
vBool.push_back(true);
|
||||
vBool.push_back(false);
|
||||
vBool.push_back(true);
|
||||
vBool.push_back(false);
|
||||
vBool.push_back(true);
|
||||
vBool.push_back(false);
|
||||
vBool.push_back(true);
|
||||
|
||||
vBool.push_back(false);
|
||||
vBool.push_back(true);
|
||||
vBool.push_back(false);
|
||||
vBool.push_back(true);
|
||||
vBool.push_back(false);
|
||||
vBool.push_back(true);
|
||||
vBool.push_back(false);
|
||||
vBool.push_back(true);
|
||||
|
||||
vBool.push_back(false);
|
||||
vBool.push_back(true);
|
||||
vBool.push_back(false);
|
||||
vBool.push_back(true);
|
||||
vBool.push_back(false);
|
||||
vBool.push_back(true);
|
||||
vBool.push_back(false);
|
||||
vBool.push_back(true);
|
||||
|
||||
vBool.push_back(false);
|
||||
vBool.push_back(true);
|
||||
vBool.push_back(false);
|
||||
vBool.push_back(true);
|
||||
vBool.push_back(false);
|
||||
vBool.push_back(true);
|
||||
vBool.push_back(false);
|
||||
vBool.push_back(true);
|
||||
|
||||
vBool.push_back(false);
|
||||
vBool.push_back(true);
|
||||
vBool.push_back(false);
|
||||
vBool.push_back(true);
|
||||
vBool.push_back(false);
|
||||
vBool.push_back(true);
|
||||
vBool.push_back(false);
|
||||
vBool.push_back(true);
|
||||
vBool.push_back(true);
|
||||
|
||||
return 0; // Set break point at this line.
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
LEVEL = ../../../../../make
|
||||
|
||||
CXX_SOURCES := main.cpp
|
||||
|
||||
include $(LEVEL)/Makefile.rules
|
||||
@@ -0,0 +1,69 @@
|
||||
"""
|
||||
Test lldb data formatter subsystem.
|
||||
"""
|
||||
|
||||
import os, time
|
||||
import unittest2
|
||||
import lldb
|
||||
from lldbtest import *
|
||||
import lldbutil
|
||||
|
||||
class StdVBoolDataFormatterTestCase(TestBase):
|
||||
|
||||
mydir = os.path.join("functionalities", "data-formatter", "data-formatter-stl", "libstdcpp", "vbool")
|
||||
|
||||
@unittest2.skipUnless(sys.platform.startswith("darwin"), "requires Darwin")
|
||||
@dsym_test
|
||||
def test_with_dsym_and_run_command(self):
|
||||
"""Test data formatter commands."""
|
||||
self.buildDsym()
|
||||
self.data_formatter_commands()
|
||||
|
||||
@dwarf_test
|
||||
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)
|
||||
|
||||
lldbutil.run_break_set_by_file_and_line (self, "main.cpp", self.line, num_expected_locations=-1)
|
||||
|
||||
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.expect("frame variable vBool",
|
||||
substrs = ['size=49','[0] = false','[1] = true','[18] = false','[27] = true','[36] = false','[47] = true','[48] = true'])
|
||||
|
||||
self.expect("expr vBool",
|
||||
substrs = ['size=49','[0] = false','[1] = true','[18] = false','[27] = true','[36] = false','[47] = true','[48] = true'])
|
||||
|
||||
if __name__ == '__main__':
|
||||
import atexit
|
||||
lldb.SBDebugger.Initialize()
|
||||
atexit.register(lambda: lldb.SBDebugger.Terminate())
|
||||
unittest2.main()
|
||||
@@ -0,0 +1,63 @@
|
||||
#include <vector>
|
||||
|
||||
int main()
|
||||
{
|
||||
std::vector<bool> vBool;
|
||||
|
||||
vBool.push_back(false);
|
||||
vBool.push_back(true);
|
||||
vBool.push_back(false);
|
||||
vBool.push_back(true);
|
||||
vBool.push_back(false);
|
||||
vBool.push_back(true);
|
||||
vBool.push_back(false);
|
||||
vBool.push_back(true);
|
||||
|
||||
vBool.push_back(false);
|
||||
vBool.push_back(true);
|
||||
vBool.push_back(false);
|
||||
vBool.push_back(true);
|
||||
vBool.push_back(false);
|
||||
vBool.push_back(true);
|
||||
vBool.push_back(false);
|
||||
vBool.push_back(true);
|
||||
|
||||
vBool.push_back(false);
|
||||
vBool.push_back(true);
|
||||
vBool.push_back(false);
|
||||
vBool.push_back(true);
|
||||
vBool.push_back(false);
|
||||
vBool.push_back(true);
|
||||
vBool.push_back(false);
|
||||
vBool.push_back(true);
|
||||
|
||||
vBool.push_back(false);
|
||||
vBool.push_back(true);
|
||||
vBool.push_back(false);
|
||||
vBool.push_back(true);
|
||||
vBool.push_back(false);
|
||||
vBool.push_back(true);
|
||||
vBool.push_back(false);
|
||||
vBool.push_back(true);
|
||||
|
||||
vBool.push_back(false);
|
||||
vBool.push_back(true);
|
||||
vBool.push_back(false);
|
||||
vBool.push_back(true);
|
||||
vBool.push_back(false);
|
||||
vBool.push_back(true);
|
||||
vBool.push_back(false);
|
||||
vBool.push_back(true);
|
||||
|
||||
vBool.push_back(false);
|
||||
vBool.push_back(true);
|
||||
vBool.push_back(false);
|
||||
vBool.push_back(true);
|
||||
vBool.push_back(false);
|
||||
vBool.push_back(true);
|
||||
vBool.push_back(false);
|
||||
vBool.push_back(true);
|
||||
vBool.push_back(true);
|
||||
|
||||
return 0; // Set break point at this line.
|
||||
}
|
||||
Reference in New Issue
Block a user