forked from OSchip/llvm-project
[DataFormatters] Add formatter for libc++ std::unique_ptr
This adds a formatter for libc++ std::unique_ptr. I also refactored GetValueOfCompressedPair(...) out of LibCxxList.cpp since I need the same functionality and it made sense to share it. Differential Revision: https://reviews.llvm.org/D76476
This commit is contained in:
parent
1b9cd51d55
commit
a567d6809e
|
@ -56,6 +56,8 @@ size_t ExtractIndexFromString(const char *item_name);
|
|||
|
||||
lldb::addr_t GetArrayAddressOrPointerValue(ValueObject &valobj);
|
||||
|
||||
lldb::ValueObjectSP GetValueOfLibCXXCompressedPair(ValueObject &pair);
|
||||
|
||||
time_t GetOSXEpoch();
|
||||
|
||||
struct InferiorSizedWord {
|
||||
|
|
|
@ -142,3 +142,14 @@ lldb_private::formatters::GetArrayAddressOrPointerValue(ValueObject &valobj) {
|
|||
|
||||
return data_addr;
|
||||
}
|
||||
|
||||
lldb::ValueObjectSP
|
||||
lldb_private::formatters::GetValueOfLibCXXCompressedPair(ValueObject &pair) {
|
||||
ValueObjectSP value =
|
||||
pair.GetChildMemberWithName(ConstString("__value_"), true);
|
||||
if (!value) {
|
||||
// pre-r300140 member name
|
||||
value = pair.GetChildMemberWithName(ConstString("__first_"), true);
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
|
|
@ -611,6 +611,15 @@ static void LoadLibCxxFormatters(lldb::TypeCategoryImplSP cpp_category_sp) {
|
|||
"shared_ptr synthetic children",
|
||||
ConstString("^(std::__[[:alnum:]]+::)shared_ptr<.+>(( )?&)?$"),
|
||||
stl_synth_flags, true);
|
||||
|
||||
ConstString libcxx_std_unique_ptr_regex(
|
||||
"^std::__[[:alnum:]]+::unique_ptr<.+>(( )?&)?$");
|
||||
AddCXXSynthetic(
|
||||
cpp_category_sp,
|
||||
lldb_private::formatters::LibcxxUniquePtrSyntheticFrontEndCreator,
|
||||
"unique_ptr synthetic children", libcxx_std_unique_ptr_regex,
|
||||
stl_synth_flags, true);
|
||||
|
||||
AddCXXSynthetic(
|
||||
cpp_category_sp,
|
||||
lldb_private::formatters::LibcxxSharedPtrSyntheticFrontEndCreator,
|
||||
|
@ -715,6 +724,10 @@ static void LoadLibCxxFormatters(lldb::TypeCategoryImplSP cpp_category_sp) {
|
|||
"libc++ std::weak_ptr summary provider",
|
||||
ConstString("^std::__[[:alnum:]]+::weak_ptr<.+>(( )?&)?$"),
|
||||
stl_summary_flags, true);
|
||||
AddCXXSummary(cpp_category_sp,
|
||||
lldb_private::formatters::LibcxxUniquePointerSummaryProvider,
|
||||
"libc++ std::unique_ptr summary provider",
|
||||
libcxx_std_unique_ptr_regex, stl_summary_flags, true);
|
||||
|
||||
AddCXXSynthetic(
|
||||
cpp_category_sp,
|
||||
|
|
|
@ -144,6 +144,43 @@ bool lldb_private::formatters::LibcxxSmartPointerSummaryProvider(
|
|||
return true;
|
||||
}
|
||||
|
||||
bool lldb_private::formatters::LibcxxUniquePointerSummaryProvider(
|
||||
ValueObject &valobj, Stream &stream, const TypeSummaryOptions &options) {
|
||||
ValueObjectSP valobj_sp(valobj.GetNonSyntheticValue());
|
||||
if (!valobj_sp)
|
||||
return false;
|
||||
|
||||
ValueObjectSP ptr_sp(
|
||||
valobj_sp->GetChildMemberWithName(ConstString("__ptr_"), true));
|
||||
if (!ptr_sp)
|
||||
return false;
|
||||
|
||||
ptr_sp = GetValueOfLibCXXCompressedPair(*ptr_sp);
|
||||
if (!ptr_sp)
|
||||
return false;
|
||||
|
||||
if (ptr_sp->GetValueAsUnsigned(0) == 0) {
|
||||
stream.Printf("nullptr");
|
||||
return true;
|
||||
} else {
|
||||
bool print_pointee = false;
|
||||
Status error;
|
||||
ValueObjectSP pointee_sp = ptr_sp->Dereference(error);
|
||||
if (pointee_sp && error.Success()) {
|
||||
if (pointee_sp->DumpPrintableRepresentation(
|
||||
stream, ValueObject::eValueObjectRepresentationStyleSummary,
|
||||
lldb::eFormatInvalid,
|
||||
ValueObject::PrintableRepresentationSpecialCases::eDisable,
|
||||
false))
|
||||
print_pointee = true;
|
||||
}
|
||||
if (!print_pointee)
|
||||
stream.Printf("ptr = 0x%" PRIx64, ptr_sp->GetValueAsUnsigned(0));
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
(lldb) fr var ibeg --raw --ptr-depth 1
|
||||
(std::__1::__map_iterator<std::__1::__tree_iterator<std::__1::pair<int,
|
||||
|
@ -449,6 +486,67 @@ lldb_private::formatters::LibcxxSharedPtrSyntheticFrontEndCreator(
|
|||
: nullptr);
|
||||
}
|
||||
|
||||
lldb_private::formatters::LibcxxUniquePtrSyntheticFrontEnd::
|
||||
LibcxxUniquePtrSyntheticFrontEnd(lldb::ValueObjectSP valobj_sp)
|
||||
: SyntheticChildrenFrontEnd(*valobj_sp), m_compressed_pair_sp() {
|
||||
if (valobj_sp)
|
||||
Update();
|
||||
}
|
||||
|
||||
lldb_private::formatters::LibcxxUniquePtrSyntheticFrontEnd::
|
||||
~LibcxxUniquePtrSyntheticFrontEnd() = default;
|
||||
|
||||
SyntheticChildrenFrontEnd *
|
||||
lldb_private::formatters::LibcxxUniquePtrSyntheticFrontEndCreator(
|
||||
CXXSyntheticChildren *, lldb::ValueObjectSP valobj_sp) {
|
||||
return (valobj_sp ? new LibcxxUniquePtrSyntheticFrontEnd(valobj_sp)
|
||||
: nullptr);
|
||||
}
|
||||
|
||||
size_t lldb_private::formatters::LibcxxUniquePtrSyntheticFrontEnd::
|
||||
CalculateNumChildren() {
|
||||
return (m_compressed_pair_sp ? 1 : 0);
|
||||
}
|
||||
|
||||
lldb::ValueObjectSP
|
||||
lldb_private::formatters::LibcxxUniquePtrSyntheticFrontEnd::GetChildAtIndex(
|
||||
size_t idx) {
|
||||
if (!m_compressed_pair_sp)
|
||||
return lldb::ValueObjectSP();
|
||||
|
||||
if (idx != 0)
|
||||
return lldb::ValueObjectSP();
|
||||
|
||||
return m_compressed_pair_sp;
|
||||
}
|
||||
|
||||
bool lldb_private::formatters::LibcxxUniquePtrSyntheticFrontEnd::Update() {
|
||||
ValueObjectSP valobj_sp = m_backend.GetSP();
|
||||
if (!valobj_sp)
|
||||
return false;
|
||||
|
||||
ValueObjectSP ptr_sp(
|
||||
valobj_sp->GetChildMemberWithName(ConstString("__ptr_"), true));
|
||||
if (!ptr_sp)
|
||||
return false;
|
||||
|
||||
m_compressed_pair_sp = GetValueOfLibCXXCompressedPair(*ptr_sp);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool lldb_private::formatters::LibcxxUniquePtrSyntheticFrontEnd::
|
||||
MightHaveChildren() {
|
||||
return true;
|
||||
}
|
||||
|
||||
size_t lldb_private::formatters::LibcxxUniquePtrSyntheticFrontEnd::
|
||||
GetIndexOfChildWithName(ConstString name) {
|
||||
if (name == "__value_")
|
||||
return 0;
|
||||
return UINT32_MAX;
|
||||
}
|
||||
|
||||
bool lldb_private::formatters::LibcxxContainerSummaryProvider(
|
||||
ValueObject &valobj, Stream &stream, const TypeSummaryOptions &options) {
|
||||
if (valobj.IsPointerType()) {
|
||||
|
|
|
@ -43,6 +43,10 @@ bool LibcxxSmartPointerSummaryProvider(
|
|||
const TypeSummaryOptions
|
||||
&options); // libc++ std::shared_ptr<> and std::weak_ptr<>
|
||||
|
||||
// libc++ std::unique_ptr<>
|
||||
bool LibcxxUniquePointerSummaryProvider(ValueObject &valobj, Stream &stream,
|
||||
const TypeSummaryOptions &options);
|
||||
|
||||
bool LibcxxFunctionSummaryProvider(
|
||||
ValueObject &valobj, Stream &stream,
|
||||
const TypeSummaryOptions &options); // libc++ std::function<>
|
||||
|
@ -107,6 +111,26 @@ private:
|
|||
lldb::ByteOrder m_byte_order;
|
||||
};
|
||||
|
||||
class LibcxxUniquePtrSyntheticFrontEnd : public SyntheticChildrenFrontEnd {
|
||||
public:
|
||||
LibcxxUniquePtrSyntheticFrontEnd(lldb::ValueObjectSP valobj_sp);
|
||||
|
||||
size_t CalculateNumChildren() override;
|
||||
|
||||
lldb::ValueObjectSP GetChildAtIndex(size_t idx) override;
|
||||
|
||||
bool Update() override;
|
||||
|
||||
bool MightHaveChildren() override;
|
||||
|
||||
size_t GetIndexOfChildWithName(ConstString name) override;
|
||||
|
||||
~LibcxxUniquePtrSyntheticFrontEnd() override;
|
||||
|
||||
private:
|
||||
lldb::ValueObjectSP m_compressed_pair_sp;
|
||||
};
|
||||
|
||||
SyntheticChildrenFrontEnd *
|
||||
LibcxxBitsetSyntheticFrontEndCreator(CXXSyntheticChildren *,
|
||||
lldb::ValueObjectSP);
|
||||
|
@ -115,6 +139,10 @@ SyntheticChildrenFrontEnd *
|
|||
LibcxxSharedPtrSyntheticFrontEndCreator(CXXSyntheticChildren *,
|
||||
lldb::ValueObjectSP);
|
||||
|
||||
SyntheticChildrenFrontEnd *
|
||||
LibcxxUniquePtrSyntheticFrontEndCreator(CXXSyntheticChildren *,
|
||||
lldb::ValueObjectSP);
|
||||
|
||||
SyntheticChildrenFrontEnd *
|
||||
LibcxxStdVectorSyntheticFrontEndCreator(CXXSyntheticChildren *,
|
||||
lldb::ValueObjectSP);
|
||||
|
|
|
@ -290,15 +290,6 @@ ValueObjectSP ForwardListFrontEnd::GetChildAtIndex(size_t idx) {
|
|||
m_element_type);
|
||||
}
|
||||
|
||||
static ValueObjectSP GetValueOfCompressedPair(ValueObject &pair) {
|
||||
ValueObjectSP value = pair.GetChildMemberWithName(ConstString("__value_"), true);
|
||||
if (! value) {
|
||||
// pre-r300140 member name
|
||||
value = pair.GetChildMemberWithName(ConstString("__first_"), true);
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
bool ForwardListFrontEnd::Update() {
|
||||
AbstractListFrontEnd::Update();
|
||||
|
||||
|
@ -311,7 +302,7 @@ bool ForwardListFrontEnd::Update() {
|
|||
m_backend.GetChildMemberWithName(ConstString("__before_begin_"), true));
|
||||
if (!impl_sp)
|
||||
return false;
|
||||
impl_sp = GetValueOfCompressedPair(*impl_sp);
|
||||
impl_sp = GetValueOfLibCXXCompressedPair(*impl_sp);
|
||||
if (!impl_sp)
|
||||
return false;
|
||||
m_head = impl_sp->GetChildMemberWithName(ConstString("__next_"), true).get();
|
||||
|
@ -332,7 +323,7 @@ size_t ListFrontEnd::CalculateNumChildren() {
|
|||
ValueObjectSP size_alloc(
|
||||
m_backend.GetChildMemberWithName(ConstString("__size_alloc_"), true));
|
||||
if (size_alloc) {
|
||||
ValueObjectSP value = GetValueOfCompressedPair(*size_alloc);
|
||||
ValueObjectSP value = GetValueOfLibCXXCompressedPair(*size_alloc);
|
||||
if (value) {
|
||||
m_count = value->GetValueAsUnsigned(UINT32_MAX);
|
||||
}
|
||||
|
|
|
@ -0,0 +1,6 @@
|
|||
CXX_SOURCES := main.cpp
|
||||
|
||||
USE_LIBCPP := 1
|
||||
|
||||
CXXFLAGS_EXTRAS := -std=c++14
|
||||
include Makefile.rules
|
|
@ -0,0 +1,47 @@
|
|||
"""
|
||||
Test lldb data formatter for libc++ std::unique_ptr.
|
||||
"""
|
||||
|
||||
|
||||
|
||||
import lldb
|
||||
from lldbsuite.test.decorators import *
|
||||
from lldbsuite.test.lldbtest import *
|
||||
from lldbsuite.test import lldbutil
|
||||
|
||||
class LibcxUniquePtrDataFormatterTestCase(TestBase):
|
||||
|
||||
mydir = TestBase.compute_mydir(__file__)
|
||||
|
||||
@add_test_categories(["libc++"])
|
||||
def test_with_run_command(self):
|
||||
"""Test that that file and class static variables display correctly."""
|
||||
self.build()
|
||||
|
||||
(self.target, self.process, _, bkpt) = lldbutil.run_to_source_breakpoint(self, '// break here',
|
||||
lldb.SBFileSpec("main.cpp", False))
|
||||
|
||||
self.expect("frame variable up_empty",
|
||||
substrs=['(std::unique_ptr<int, std::default_delete<int> >) up_empty = nullptr {',
|
||||
'__value_ = ',
|
||||
'}'])
|
||||
|
||||
self.expect("frame variable up_int",
|
||||
substrs=['(std::unique_ptr<int, std::default_delete<int> >) up_int = 10 {',
|
||||
'__value_ = ',
|
||||
'}'])
|
||||
|
||||
self.expect("frame variable up_int_ref",
|
||||
substrs=['(std::unique_ptr<int, std::default_delete<int> > &) up_int_ref = 10: {',
|
||||
'__value_ = ',
|
||||
'}'])
|
||||
|
||||
self.expect("frame variable up_int_ref_ref",
|
||||
substrs=['(std::unique_ptr<int, std::default_delete<int> > &&) up_int_ref_ref = 10: {',
|
||||
'__value_ = ',
|
||||
'}'])
|
||||
|
||||
self.expect("frame variable up_str",
|
||||
substrs=['up_str = "hello" {',
|
||||
'__value_ = ',
|
||||
'}'])
|
|
@ -0,0 +1,13 @@
|
|||
#include <cstdio>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
|
||||
int main() {
|
||||
std::unique_ptr<int> up_empty;
|
||||
std::unique_ptr<int> up_int = std::make_unique<int>(10);
|
||||
std::unique_ptr<std::string> up_str = std::make_unique<std::string>("hello");
|
||||
std::unique_ptr<int> &up_int_ref = up_int;
|
||||
std::unique_ptr<int> &&up_int_ref_ref = std::make_unique<int>(10);
|
||||
|
||||
return 0; // break here
|
||||
}
|
Loading…
Reference in New Issue