Reorganize some of the data formatters code to simplify CXXFormattersFunction.h. Also, add a synthetic child provider for libc++'s version of std::initializer_list<T>

llvm-svn: 220421
This commit is contained in:
Enrico Granata 2014-10-22 20:34:38 +00:00
parent 4bd54a1544
commit e85fe3a4d1
11 changed files with 454 additions and 238 deletions

View File

@ -667,149 +667,16 @@ namespace lldb_private {
SyntheticChildrenFrontEnd* LibcxxSharedPtrSyntheticFrontEndCreator (CXXSyntheticChildren*, lldb::ValueObjectSP);
class LibcxxStdVectorSyntheticFrontEnd : public SyntheticChildrenFrontEnd
{
public:
LibcxxStdVectorSyntheticFrontEnd (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
~LibcxxStdVectorSyntheticFrontEnd ();
private:
ValueObject* m_start;
ValueObject* m_finish;
ClangASTType m_element_type;
uint32_t m_element_size;
std::map<size_t,lldb::ValueObjectSP> m_children;
};
SyntheticChildrenFrontEnd* LibcxxStdVectorSyntheticFrontEndCreator (CXXSyntheticChildren*, lldb::ValueObjectSP);
class LibcxxStdListSyntheticFrontEnd : public SyntheticChildrenFrontEnd
{
public:
LibcxxStdListSyntheticFrontEnd (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
~LibcxxStdListSyntheticFrontEnd ();
private:
bool
HasLoop(size_t);
size_t m_list_capping_size;
static const bool g_use_loop_detect = true;
size_t m_loop_detected;
lldb::addr_t m_node_address;
ValueObject* m_head;
ValueObject* m_tail;
ClangASTType m_element_type;
size_t m_count;
std::map<size_t,lldb::ValueObjectSP> m_children;
};
SyntheticChildrenFrontEnd* LibcxxStdListSyntheticFrontEndCreator (CXXSyntheticChildren*, lldb::ValueObjectSP);
class LibcxxStdMapSyntheticFrontEnd : public SyntheticChildrenFrontEnd
{
public:
LibcxxStdMapSyntheticFrontEnd (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
~LibcxxStdMapSyntheticFrontEnd ();
private:
bool
GetDataType();
void
GetValueOffset (const lldb::ValueObjectSP& node);
ValueObject* m_tree;
ValueObject* m_root_node;
ClangASTType m_element_type;
uint32_t m_skip_size;
size_t m_count;
std::map<size_t,lldb::ValueObjectSP> m_children;
};
SyntheticChildrenFrontEnd* LibcxxStdMapSyntheticFrontEndCreator (CXXSyntheticChildren*, lldb::ValueObjectSP);
class LibcxxStdUnorderedMapSyntheticFrontEnd : public SyntheticChildrenFrontEnd
{
public:
LibcxxStdUnorderedMapSyntheticFrontEnd (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
~LibcxxStdUnorderedMapSyntheticFrontEnd ();
private:
ValueObject* m_tree;
size_t m_num_elements;
ValueObject* m_next_element;
std::map<size_t,lldb::ValueObjectSP> m_children;
std::vector<std::pair<ValueObject*, uint64_t> > m_elements_cache;
};
SyntheticChildrenFrontEnd* LibcxxStdUnorderedMapSyntheticFrontEndCreator (CXXSyntheticChildren*, lldb::ValueObjectSP);
SyntheticChildrenFrontEnd* LibcxxInitializerListSyntheticFrontEndCreator (CXXSyntheticChildren*, lldb::ValueObjectSP);
} // namespace formatters
} // namespace lldb_private

View File

@ -646,6 +646,8 @@
941BCC8014E48C4000BB969C /* SBTypeFormat.h in Headers */ = {isa = PBXBuildFile; fileRef = 9461568714E355F2003A195C /* SBTypeFormat.h */; settings = {ATTRIBUTES = (Public, ); }; };
941BCC8114E48C4000BB969C /* SBTypeSummary.h in Headers */ = {isa = PBXBuildFile; fileRef = 9461568814E355F2003A195C /* SBTypeSummary.h */; settings = {ATTRIBUTES = (Public, ); }; };
941BCC8214E48C4000BB969C /* SBTypeSynthetic.h in Headers */ = {isa = PBXBuildFile; fileRef = 9461568914E355F2003A195C /* SBTypeSynthetic.h */; settings = {ATTRIBUTES = (Public, ); }; };
942AFF0519F84ABF007B43B4 /* LibCxxVector.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 942AFF0419F84ABF007B43B4 /* LibCxxVector.cpp */; };
942AFF0719F84C02007B43B4 /* LibCxxInitializerList.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 942AFF0619F84C02007B43B4 /* LibCxxInitializerList.cpp */; };
94380B8219940B0A00BFE4A8 /* StringLexer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 94380B8119940B0A00BFE4A8 /* StringLexer.cpp */; };
9439FB1A19EF140C006FD6A4 /* NSIndexPath.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9439FB1919EF140C006FD6A4 /* NSIndexPath.cpp */; };
944372DC171F6B4300E57C32 /* RegisterContextDummy.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 944372DA171F6B4300E57C32 /* RegisterContextDummy.cpp */; };
@ -1983,6 +1985,8 @@
940B02F519DC96E700AD0F52 /* SBExecutionContext.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = SBExecutionContext.cpp; path = source/API/SBExecutionContext.cpp; sourceTree = "<group>"; };
940B02F719DC970900AD0F52 /* SBExecutionContext.i */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c.preprocessed; path = SBExecutionContext.i; sourceTree = "<group>"; };
94145430175D7FDE00284436 /* lldb-versioning.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "lldb-versioning.h"; path = "include/lldb/lldb-versioning.h"; sourceTree = "<group>"; };
942AFF0419F84ABF007B43B4 /* LibCxxVector.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = LibCxxVector.cpp; path = source/DataFormatters/LibCxxVector.cpp; sourceTree = "<group>"; };
942AFF0619F84C02007B43B4 /* LibCxxInitializerList.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = LibCxxInitializerList.cpp; path = source/DataFormatters/LibCxxInitializerList.cpp; sourceTree = "<group>"; };
94380B8019940B0300BFE4A8 /* StringLexer.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = StringLexer.h; path = include/lldb/Utility/StringLexer.h; sourceTree = "<group>"; };
94380B8119940B0A00BFE4A8 /* StringLexer.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = StringLexer.cpp; path = source/Utility/StringLexer.cpp; sourceTree = "<group>"; };
9439FB1919EF140C006FD6A4 /* NSIndexPath.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = NSIndexPath.cpp; path = source/DataFormatters/NSIndexPath.cpp; sourceTree = "<group>"; };
@ -4322,9 +4326,11 @@
94CB255A16B069770059775D /* FormatManager.cpp */,
94EE33F218643C6900CD703B /* FormattersContainer.h */,
94D0B10A16D5535900EA9C70 /* LibCxx.cpp */,
942AFF0619F84C02007B43B4 /* LibCxxInitializerList.cpp */,
94CD704F16F8DF1C00CF1E42 /* LibCxxList.cpp */,
94CD705116F8F5BC00CF1E42 /* LibCxxMap.cpp */,
94EA27CD17DE91750070F505 /* LibCxxUnorderedMap.cpp */,
942AFF0419F84ABF007B43B4 /* LibCxxVector.cpp */,
94D0B10B16D5535900EA9C70 /* LibStdcpp.cpp */,
94D6A0A716CEB55F00833B6E /* NSArray.cpp */,
94D6A0A816CEB55F00833B6E /* NSDictionary.cpp */,
@ -5105,6 +5111,7 @@
3FDFED0F19B7D269009756A7 /* ThisThread.cpp in Sources */,
2689005F13353E0E00698AC0 /* ClangFunction.cpp in Sources */,
2689006013353E0E00698AC0 /* ClangExpressionDeclMap.cpp in Sources */,
942AFF0719F84C02007B43B4 /* LibCxxInitializerList.cpp in Sources */,
2689006113353E0E00698AC0 /* ClangExpressionParser.cpp in Sources */,
2689006213353E0E00698AC0 /* ClangExpressionVariable.cpp in Sources */,
2689006313353E0E00698AC0 /* ClangPersistentVariables.cpp in Sources */,
@ -5249,6 +5256,7 @@
26BC17AD18C7F4CB00D2196D /* RegisterContextPOSIXCore_mips64.cpp in Sources */,
268900F113353E6F00698AC0 /* RegisterContext.cpp in Sources */,
268900F213353E6F00698AC0 /* SectionLoadList.cpp in Sources */,
942AFF0519F84ABF007B43B4 /* LibCxxVector.cpp in Sources */,
268900F313353E6F00698AC0 /* StackFrame.cpp in Sources */,
268900F413353E6F00698AC0 /* StackFrameList.cpp in Sources */,
268900F513353E6F00698AC0 /* StackID.cpp in Sources */,

View File

@ -1085,6 +1085,7 @@ FormatManager::LoadLibcxxFormatters()
AddCXXSynthetic(libcxx_category_sp, lldb_private::formatters::LibcxxStdMapSyntheticFrontEndCreator, "libc++ std::multiset synthetic children", ConstString("^std::__1::multiset<.+> >(( )?&)?$"), stl_synth_flags, true);
AddCXXSynthetic(libcxx_category_sp, lldb_private::formatters::LibcxxStdMapSyntheticFrontEndCreator, "libc++ std::multimap synthetic children", ConstString("^std::__1::multimap<.+> >(( )?&)?$"), stl_synth_flags, true);
AddCXXSynthetic(libcxx_category_sp, lldb_private::formatters::LibcxxStdUnorderedMapSyntheticFrontEndCreator, "libc++ std::unordered containers synthetic children", ConstString("^(std::__1::)unordered_(multi)?(map|set)<.+> >$"), stl_synth_flags, true);
AddCXXSynthetic(libcxx_category_sp, lldb_private::formatters::LibcxxInitializerListSyntheticFrontEndCreator, "libc++ std::initializer_list synthetic children", ConstString("^std::initializer_list<.+>(( )?&)?$"), stl_synth_flags, true);
libcxx_category_sp->GetRegexTypeSyntheticsContainer()->Add(RegularExpressionSP(new RegularExpression("^(std::__1::)deque<.+>(( )?&)?$")),
SyntheticChildrenSP(new ScriptedSyntheticChildren(stl_synth_flags,

View File

@ -450,109 +450,6 @@ lldb_private::formatters::LibcxxSharedPtrSyntheticFrontEndCreator (CXXSyntheticC
return (new LibcxxSharedPtrSyntheticFrontEnd(valobj_sp));
}
lldb_private::formatters::LibcxxStdVectorSyntheticFrontEnd::LibcxxStdVectorSyntheticFrontEnd (lldb::ValueObjectSP valobj_sp) :
SyntheticChildrenFrontEnd(*valobj_sp.get()),
m_start(NULL),
m_finish(NULL),
m_element_type(),
m_element_size(0),
m_children()
{
if (valobj_sp)
Update();
}
size_t
lldb_private::formatters::LibcxxStdVectorSyntheticFrontEnd::CalculateNumChildren ()
{
if (!m_start || !m_finish)
return 0;
uint64_t start_val = m_start->GetValueAsUnsigned(0);
uint64_t finish_val = m_finish->GetValueAsUnsigned(0);
if (start_val == 0 || finish_val == 0)
return 0;
if (start_val >= finish_val)
return 0;
size_t num_children = (finish_val - start_val);
if (num_children % m_element_size)
return 0;
return num_children/m_element_size;
}
lldb::ValueObjectSP
lldb_private::formatters::LibcxxStdVectorSyntheticFrontEnd::GetChildAtIndex (size_t idx)
{
if (!m_start || !m_finish)
return lldb::ValueObjectSP();
auto cached = m_children.find(idx);
if (cached != m_children.end())
return cached->second;
uint64_t offset = idx * m_element_size;
offset = offset + m_start->GetValueAsUnsigned(0);
StreamString name;
name.Printf("[%" PRIu64 "]", (uint64_t)idx);
ValueObjectSP child_sp = ValueObject::CreateValueObjectFromAddress(name.GetData(), offset, m_backend.GetExecutionContextRef(), m_element_type);
m_children[idx] = child_sp;
return child_sp;
}
bool
lldb_private::formatters::LibcxxStdVectorSyntheticFrontEnd::Update()
{
m_start = m_finish = NULL;
m_children.clear();
ValueObjectSP data_type_finder_sp(m_backend.GetChildMemberWithName(ConstString("__end_cap_"),true));
if (!data_type_finder_sp)
return false;
data_type_finder_sp = data_type_finder_sp->GetChildMemberWithName(ConstString("__first_"),true);
if (!data_type_finder_sp)
return false;
m_element_type = data_type_finder_sp->GetClangType().GetPointeeType();
m_element_size = m_element_type.GetByteSize();
if (m_element_size > 0)
{
// store raw pointers or end up with a circular dependency
m_start = m_backend.GetChildMemberWithName(ConstString("__begin_"),true).get();
m_finish = m_backend.GetChildMemberWithName(ConstString("__end_"),true).get();
}
return false;
}
bool
lldb_private::formatters::LibcxxStdVectorSyntheticFrontEnd::MightHaveChildren ()
{
return true;
}
size_t
lldb_private::formatters::LibcxxStdVectorSyntheticFrontEnd::GetIndexOfChildWithName (const ConstString &name)
{
if (!m_start || !m_finish)
return UINT32_MAX;
return ExtractIndexFromString(name.GetCString());
}
lldb_private::formatters::LibcxxStdVectorSyntheticFrontEnd::~LibcxxStdVectorSyntheticFrontEnd ()
{
// these need to stay around because they are child objects who will follow their parent's life cycle
// delete m_start;
// delete m_finish;
}
SyntheticChildrenFrontEnd*
lldb_private::formatters::LibcxxStdVectorSyntheticFrontEndCreator (CXXSyntheticChildren*, lldb::ValueObjectSP valobj_sp)
{
if (!valobj_sp)
return NULL;
return (new LibcxxStdVectorSyntheticFrontEnd(valobj_sp));
}
bool
lldb_private::formatters::LibcxxContainerSummaryProvider (ValueObject& valobj, Stream& stream)
{

View File

@ -0,0 +1,145 @@
//===-- LibCxxInitializerList.cpp ----------------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#include "lldb/lldb-python.h"
#include "lldb/DataFormatters/CXXFormatterFunctions.h"
#include "lldb/Core/ConstString.h"
#include "lldb/Core/ValueObject.h"
using namespace lldb;
using namespace lldb_private;
using namespace lldb_private::formatters;
namespace lldb_private {
namespace formatters {
class LibcxxInitializerListSyntheticFrontEnd : public SyntheticChildrenFrontEnd
{
public:
LibcxxInitializerListSyntheticFrontEnd (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
~LibcxxInitializerListSyntheticFrontEnd ();
private:
ValueObject* m_start;
ClangASTType m_element_type;
uint32_t m_element_size;
size_t m_num_elements;
std::map<size_t,lldb::ValueObjectSP> m_children;
};
}
}
lldb_private::formatters::LibcxxInitializerListSyntheticFrontEnd::LibcxxInitializerListSyntheticFrontEnd (lldb::ValueObjectSP valobj_sp) :
SyntheticChildrenFrontEnd(*valobj_sp.get()),
m_start(NULL),
m_element_type(),
m_element_size(0),
m_num_elements(0),
m_children()
{
if (valobj_sp)
Update();
}
size_t
lldb_private::formatters::LibcxxInitializerListSyntheticFrontEnd::CalculateNumChildren ()
{
static ConstString g___size_("__size_");
m_num_elements = 0;
ValueObjectSP size_sp(m_backend.GetChildMemberWithName(g___size_, true));
if (size_sp)
m_num_elements = size_sp->GetValueAsUnsigned(0);
return m_num_elements;
}
lldb::ValueObjectSP
lldb_private::formatters::LibcxxInitializerListSyntheticFrontEnd::GetChildAtIndex (size_t idx)
{
if (!m_start)
return lldb::ValueObjectSP();
auto cached = m_children.find(idx);
if (cached != m_children.end())
return cached->second;
uint64_t offset = idx * m_element_size;
offset = offset + m_start->GetValueAsUnsigned(0);
StreamString name;
name.Printf("[%" PRIu64 "]", (uint64_t)idx);
ValueObjectSP child_sp = ValueObject::CreateValueObjectFromAddress(name.GetData(), offset, m_backend.GetExecutionContextRef(), m_element_type);
m_children[idx] = child_sp;
return child_sp;
}
bool
lldb_private::formatters::LibcxxInitializerListSyntheticFrontEnd::Update()
{
static ConstString g___begin_("__begin_");
m_start = nullptr;
m_num_elements = 0;
m_children.clear();
lldb::TemplateArgumentKind kind;
m_element_type = m_backend.GetClangType().GetTemplateArgument(0, kind);
if (kind != lldb::eTemplateArgumentKindType || false == m_element_type.IsValid())
return false;
m_element_size = m_element_type.GetByteSize();
if (m_element_size > 0)
m_start = m_backend.GetChildMemberWithName(g___begin_,true).get(); // store raw pointers or end up with a circular dependency
return false;
}
bool
lldb_private::formatters::LibcxxInitializerListSyntheticFrontEnd::MightHaveChildren ()
{
return true;
}
size_t
lldb_private::formatters::LibcxxInitializerListSyntheticFrontEnd::GetIndexOfChildWithName (const ConstString &name)
{
if (!m_start)
return UINT32_MAX;
return ExtractIndexFromString(name.GetCString());
}
lldb_private::formatters::LibcxxInitializerListSyntheticFrontEnd::~LibcxxInitializerListSyntheticFrontEnd ()
{
// this needs to stay around because it's a child object who will follow its parent's life cycle
// delete m_start;
}
lldb_private::SyntheticChildrenFrontEnd*
lldb_private::formatters::LibcxxInitializerListSyntheticFrontEndCreator (CXXSyntheticChildren*, lldb::ValueObjectSP valobj_sp)
{
if (!valobj_sp)
return NULL;
return (new LibcxxInitializerListSyntheticFrontEnd(valobj_sp));
}

View File

@ -25,6 +25,47 @@ using namespace lldb;
using namespace lldb_private;
using namespace lldb_private::formatters;
namespace lldb_private {
namespace formatters {
class LibcxxStdListSyntheticFrontEnd : public SyntheticChildrenFrontEnd
{
public:
LibcxxStdListSyntheticFrontEnd (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
~LibcxxStdListSyntheticFrontEnd ();
private:
bool
HasLoop(size_t);
size_t m_list_capping_size;
static const bool g_use_loop_detect = true;
size_t m_loop_detected;
lldb::addr_t m_node_address;
ValueObject* m_head;
ValueObject* m_tail;
ClangASTType m_element_type;
size_t m_count;
std::map<size_t,lldb::ValueObjectSP> m_children;
};
}
}
class ListEntry
{
public:

View File

@ -25,6 +25,47 @@ using namespace lldb;
using namespace lldb_private;
using namespace lldb_private::formatters;
namespace lldb_private {
namespace formatters {
class LibcxxStdMapSyntheticFrontEnd : public SyntheticChildrenFrontEnd
{
public:
LibcxxStdMapSyntheticFrontEnd (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
~LibcxxStdMapSyntheticFrontEnd ();
private:
bool
GetDataType();
void
GetValueOffset (const lldb::ValueObjectSP& node);
ValueObject* m_tree;
ValueObject* m_root_node;
ClangASTType m_element_type;
uint32_t m_skip_size;
size_t m_count;
std::map<size_t,lldb::ValueObjectSP> m_children;
};
}
}
class MapEntry
{
public:

View File

@ -25,6 +25,41 @@ using namespace lldb;
using namespace lldb_private;
using namespace lldb_private::formatters;
namespace lldb_private {
namespace formatters {
class LibcxxStdUnorderedMapSyntheticFrontEnd : public SyntheticChildrenFrontEnd
{
public:
LibcxxStdUnorderedMapSyntheticFrontEnd (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
~LibcxxStdUnorderedMapSyntheticFrontEnd ();
private:
ValueObject* m_tree;
size_t m_num_elements;
ValueObject* m_next_element;
std::map<size_t,lldb::ValueObjectSP> m_children;
std::vector<std::pair<ValueObject*, uint64_t> > m_elements_cache;
};
}
}
lldb_private::formatters::LibcxxStdUnorderedMapSyntheticFrontEnd::LibcxxStdUnorderedMapSyntheticFrontEnd (lldb::ValueObjectSP valobj_sp) :
SyntheticChildrenFrontEnd(*valobj_sp.get()),
m_tree(NULL),

View File

@ -0,0 +1,157 @@
//===-- LibCxxVector.cpp -----------------------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#include "lldb/lldb-python.h"
#include "lldb/DataFormatters/CXXFormatterFunctions.h"
#include "lldb/Core/ConstString.h"
#include "lldb/Core/ValueObject.h"
using namespace lldb;
using namespace lldb_private;
using namespace lldb_private::formatters;
namespace lldb_private {
namespace formatters {
class LibcxxStdVectorSyntheticFrontEnd : public SyntheticChildrenFrontEnd
{
public:
LibcxxStdVectorSyntheticFrontEnd (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
~LibcxxStdVectorSyntheticFrontEnd ();
private:
ValueObject* m_start;
ValueObject* m_finish;
ClangASTType m_element_type;
uint32_t m_element_size;
std::map<size_t,lldb::ValueObjectSP> m_children;
};
}
}
lldb_private::formatters::LibcxxStdVectorSyntheticFrontEnd::LibcxxStdVectorSyntheticFrontEnd (lldb::ValueObjectSP valobj_sp) :
SyntheticChildrenFrontEnd(*valobj_sp.get()),
m_start(NULL),
m_finish(NULL),
m_element_type(),
m_element_size(0),
m_children()
{
if (valobj_sp)
Update();
}
size_t
lldb_private::formatters::LibcxxStdVectorSyntheticFrontEnd::CalculateNumChildren ()
{
if (!m_start || !m_finish)
return 0;
uint64_t start_val = m_start->GetValueAsUnsigned(0);
uint64_t finish_val = m_finish->GetValueAsUnsigned(0);
if (start_val == 0 || finish_val == 0)
return 0;
if (start_val >= finish_val)
return 0;
size_t num_children = (finish_val - start_val);
if (num_children % m_element_size)
return 0;
return num_children/m_element_size;
}
lldb::ValueObjectSP
lldb_private::formatters::LibcxxStdVectorSyntheticFrontEnd::GetChildAtIndex (size_t idx)
{
if (!m_start || !m_finish)
return lldb::ValueObjectSP();
auto cached = m_children.find(idx);
if (cached != m_children.end())
return cached->second;
uint64_t offset = idx * m_element_size;
offset = offset + m_start->GetValueAsUnsigned(0);
StreamString name;
name.Printf("[%" PRIu64 "]", (uint64_t)idx);
ValueObjectSP child_sp = ValueObject::CreateValueObjectFromAddress(name.GetData(), offset, m_backend.GetExecutionContextRef(), m_element_type);
m_children[idx] = child_sp;
return child_sp;
}
bool
lldb_private::formatters::LibcxxStdVectorSyntheticFrontEnd::Update()
{
m_start = m_finish = NULL;
m_children.clear();
ValueObjectSP data_type_finder_sp(m_backend.GetChildMemberWithName(ConstString("__end_cap_"),true));
if (!data_type_finder_sp)
return false;
data_type_finder_sp = data_type_finder_sp->GetChildMemberWithName(ConstString("__first_"),true);
if (!data_type_finder_sp)
return false;
m_element_type = data_type_finder_sp->GetClangType().GetPointeeType();
m_element_size = m_element_type.GetByteSize();
if (m_element_size > 0)
{
// store raw pointers or end up with a circular dependency
m_start = m_backend.GetChildMemberWithName(ConstString("__begin_"),true).get();
m_finish = m_backend.GetChildMemberWithName(ConstString("__end_"),true).get();
}
return false;
}
bool
lldb_private::formatters::LibcxxStdVectorSyntheticFrontEnd::MightHaveChildren ()
{
return true;
}
size_t
lldb_private::formatters::LibcxxStdVectorSyntheticFrontEnd::GetIndexOfChildWithName (const ConstString &name)
{
if (!m_start || !m_finish)
return UINT32_MAX;
return ExtractIndexFromString(name.GetCString());
}
lldb_private::formatters::LibcxxStdVectorSyntheticFrontEnd::~LibcxxStdVectorSyntheticFrontEnd ()
{
// these need to stay around because they are child objects who will follow their parent's life cycle
// delete m_start;
// delete m_finish;
}
lldb_private::SyntheticChildrenFrontEnd*
lldb_private::formatters::LibcxxStdVectorSyntheticFrontEndCreator (CXXSyntheticChildren*, lldb::ValueObjectSP valobj_sp)
{
if (!valobj_sp)
return NULL;
return (new LibcxxStdVectorSyntheticFrontEnd(valobj_sp));
}

View File

@ -0,0 +1,3 @@
import lldbinline
lldbinline.MakeInlineTest(__file__, globals())

View File

@ -0,0 +1,21 @@
//===-- main.cpp --------------------------------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#include <string>
#include <vector>
#include <initializer_list>
int main ()
{
std::initializer_list<int> ili{1,2,3,4,5};
std::initializer_list<std::string> ils{"1","2","3","4","surprise it is a long string!! yay!!"};
return 0; //% self.expect("frame variable ili", substrs = ['[1] = 2','[4] = 5'])
//% self.expect("frame variable ils", substrs = ['[4] = "surprise it is a long string!! yay!!"'])
}