forked from OSchip/llvm-project
Add data formatter for libstdc++ unique_ptr
Differential revision: https://reviews.llvm.org/D25734 llvm-svn: 284830
This commit is contained in:
parent
7f15dba16d
commit
d161b2147b
|
@ -0,0 +1,8 @@
|
|||
LEVEL = ../../../../../make
|
||||
|
||||
CXX_SOURCES := main.cpp
|
||||
|
||||
USE_LIBSTDCPP := 1
|
||||
CFLAGS_EXTRAS += $(NO_LIMIT_DEBUG_INFO_FLAGS)
|
||||
|
||||
include $(LEVEL)/Makefile.rules
|
|
@ -0,0 +1,61 @@
|
|||
"""
|
||||
Test lldb data formatter subsystem.
|
||||
"""
|
||||
|
||||
from __future__ import print_function
|
||||
|
||||
import os
|
||||
import time
|
||||
import lldb
|
||||
from lldbsuite.test.decorators import *
|
||||
from lldbsuite.test.lldbtest import *
|
||||
from lldbsuite.test import lldbutil
|
||||
|
||||
|
||||
class StdUniquePtrDataFormatterTestCase(TestBase):
|
||||
mydir = TestBase.compute_mydir(__file__)
|
||||
|
||||
@skipIfFreeBSD
|
||||
@skipIfWindows # libstdcpp not ported to Windows
|
||||
@skipIfDarwin # doesn't compile on Darwin
|
||||
def test_with_run_command(self):
|
||||
self.build()
|
||||
self.runCmd("file a.out", CURRENT_EXECUTABLE_SET)
|
||||
|
||||
lldbutil.run_break_set_by_source_regexp(
|
||||
self, "Set break point at this 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'])
|
||||
|
||||
frame = self.frame()
|
||||
self.assertTrue(frame.IsValid())
|
||||
|
||||
self.expect("frame variable nup", substrs=['nup = nullptr'])
|
||||
self.expect("frame variable iup", substrs=['iup = 123', 'object = 123'])
|
||||
self.expect("frame variable sup", substrs=['sup = "foobar"', 'object = "foobar"'])
|
||||
|
||||
self.expect("frame variable ndp", substrs=['ndp = nullptr'])
|
||||
self.expect("frame variable idp", substrs=['idp = 456', 'object = 456', 'deleter = ', 'a = 1', 'b = 2'])
|
||||
self.expect("frame variable sdp", substrs=['sdp = "baz"', 'object = "baz"', 'deleter = ', 'a = 3', 'b = 4'])
|
||||
|
||||
self.assertEqual(123, frame.GetValueForVariablePath("iup.object").GetValueAsUnsigned())
|
||||
self.assertFalse(frame.GetValueForVariablePath("iup.deleter").IsValid())
|
||||
|
||||
self.assertEqual('"foobar"', frame.GetValueForVariablePath("sup.object").GetSummary())
|
||||
self.assertFalse(frame.GetValueForVariablePath("sup.deleter").IsValid())
|
||||
|
||||
self.assertEqual(456, frame.GetValueForVariablePath("idp.object").GetValueAsUnsigned())
|
||||
self.assertEqual('"baz"', frame.GetValueForVariablePath("sdp.object").GetSummary())
|
||||
|
||||
idp_deleter = frame.GetValueForVariablePath("idp.deleter")
|
||||
self.assertTrue(idp_deleter.IsValid())
|
||||
self.assertEqual(1, idp_deleter.GetChildMemberWithName("a").GetValueAsUnsigned())
|
||||
self.assertEqual(2, idp_deleter.GetChildMemberWithName("b").GetValueAsUnsigned())
|
||||
|
||||
sdp_deleter = frame.GetValueForVariablePath("sdp.deleter")
|
||||
self.assertTrue(sdp_deleter.IsValid())
|
||||
self.assertEqual(3, sdp_deleter.GetChildMemberWithName("a").GetValueAsUnsigned())
|
||||
self.assertEqual(4, sdp_deleter.GetChildMemberWithName("b").GetValueAsUnsigned())
|
|
@ -0,0 +1,22 @@
|
|||
#include <memory>
|
||||
#include <string>
|
||||
|
||||
struct Deleter {
|
||||
void operator()(void *) {}
|
||||
|
||||
int a;
|
||||
int b;
|
||||
};
|
||||
|
||||
int main() {
|
||||
std::unique_ptr<char> nup;
|
||||
std::unique_ptr<int> iup(new int{123});
|
||||
std::unique_ptr<std::string> sup(new std::string("foobar"));
|
||||
|
||||
std::unique_ptr<char, Deleter> ndp;
|
||||
std::unique_ptr<int, Deleter> idp(new int{456}, Deleter{1, 2});
|
||||
std::unique_ptr<std::string, Deleter> sdp(new std::string("baz"),
|
||||
Deleter{3, 4});
|
||||
|
||||
return 0; // Set break point at this line.
|
||||
}
|
|
@ -12,4 +12,5 @@ add_lldb_library(lldbPluginCPlusPlusLanguage
|
|||
LibStdcpp.cpp
|
||||
LibStdcppSmartPointer.cpp
|
||||
LibStdcppTuple.cpp
|
||||
LibStdcppUniquePointer.cpp
|
||||
)
|
||||
|
|
|
@ -801,6 +801,11 @@ static void LoadLibStdcppFormatters(lldb::TypeCategoryImplSP cpp_category_sp) {
|
|||
"std::map iterator synthetic children",
|
||||
ConstString("^std::_Rb_tree_iterator<.+>$"), stl_synth_flags, true);
|
||||
|
||||
AddCXXSynthetic(
|
||||
cpp_category_sp,
|
||||
lldb_private::formatters::LibStdcppUniquePtrSyntheticFrontEndCreator,
|
||||
"std::unique_ptr synthetic children",
|
||||
ConstString("^std::unique_ptr<.+>(( )?&)?$"), stl_synth_flags, true);
|
||||
AddCXXSynthetic(
|
||||
cpp_category_sp,
|
||||
lldb_private::formatters::LibStdcppSharedPtrSyntheticFrontEndCreator,
|
||||
|
@ -817,6 +822,11 @@ static void LoadLibStdcppFormatters(lldb::TypeCategoryImplSP cpp_category_sp) {
|
|||
"std::tuple synthetic children", ConstString("^std::tuple<.+>(( )?&)?$"),
|
||||
stl_synth_flags, true);
|
||||
|
||||
AddCXXSummary(cpp_category_sp,
|
||||
lldb_private::formatters::LibStdcppUniquePointerSummaryProvider,
|
||||
"libstdc++ std::unique_ptr summary provider",
|
||||
ConstString("^std::unique_ptr<.+>(( )?&)?$"), stl_summary_flags,
|
||||
true);
|
||||
AddCXXSummary(cpp_category_sp,
|
||||
lldb_private::formatters::LibStdcppSmartPointerSummaryProvider,
|
||||
"libstdc++ std::shared_ptr summary provider",
|
||||
|
|
|
@ -31,6 +31,10 @@ bool LibStdcppSmartPointerSummaryProvider(
|
|||
const TypeSummaryOptions
|
||||
&options); // libstdc++ std::shared_ptr<> and std::weak_ptr<>
|
||||
|
||||
bool LibStdcppUniquePointerSummaryProvider(
|
||||
ValueObject &valobj, Stream &stream,
|
||||
const TypeSummaryOptions &options); // libstdc++ std::unique_ptr<>
|
||||
|
||||
SyntheticChildrenFrontEnd *
|
||||
LibstdcppMapIteratorSyntheticFrontEndCreator(CXXSyntheticChildren *,
|
||||
lldb::ValueObjectSP);
|
||||
|
@ -46,6 +50,11 @@ LibStdcppVectorIteratorSyntheticFrontEndCreator(CXXSyntheticChildren *,
|
|||
SyntheticChildrenFrontEnd *
|
||||
LibStdcppSharedPtrSyntheticFrontEndCreator(CXXSyntheticChildren *,
|
||||
lldb::ValueObjectSP);
|
||||
|
||||
SyntheticChildrenFrontEnd *
|
||||
LibStdcppUniquePtrSyntheticFrontEndCreator(CXXSyntheticChildren *,
|
||||
lldb::ValueObjectSP);
|
||||
|
||||
} // namespace formatters
|
||||
} // namespace lldb_private
|
||||
|
||||
|
|
|
@ -0,0 +1,160 @@
|
|||
//===-- LibStdcppUniquePointer.cpp ------------------------------*- C++ -*-===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "LibStdcpp.h"
|
||||
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
|
||||
#include "lldb/Core/ConstString.h"
|
||||
#include "lldb/Core/ValueObject.h"
|
||||
#include "lldb/DataFormatters/FormattersHelpers.h"
|
||||
#include "lldb/DataFormatters/TypeSynthetic.h"
|
||||
|
||||
using namespace lldb;
|
||||
using namespace lldb_private;
|
||||
using namespace lldb_private::formatters;
|
||||
|
||||
namespace {
|
||||
|
||||
class LibStdcppUniquePtrSyntheticFrontEnd : public SyntheticChildrenFrontEnd {
|
||||
public:
|
||||
explicit LibStdcppUniquePtrSyntheticFrontEnd(lldb::ValueObjectSP valobj_sp);
|
||||
|
||||
size_t CalculateNumChildren() override;
|
||||
|
||||
lldb::ValueObjectSP GetChildAtIndex(size_t idx) override;
|
||||
|
||||
bool Update() override;
|
||||
|
||||
bool MightHaveChildren() override;
|
||||
|
||||
size_t GetIndexOfChildWithName(const ConstString &name) override;
|
||||
|
||||
bool GetSummary(Stream &stream, const TypeSummaryOptions &options);
|
||||
|
||||
private:
|
||||
ValueObjectSP m_ptr_obj;
|
||||
ValueObjectSP m_obj_obj;
|
||||
ValueObjectSP m_del_obj;
|
||||
};
|
||||
|
||||
} // end of anonymous namespace
|
||||
|
||||
LibStdcppUniquePtrSyntheticFrontEnd::LibStdcppUniquePtrSyntheticFrontEnd(
|
||||
lldb::ValueObjectSP valobj_sp)
|
||||
: SyntheticChildrenFrontEnd(*valobj_sp) {
|
||||
Update();
|
||||
}
|
||||
|
||||
bool LibStdcppUniquePtrSyntheticFrontEnd::Update() {
|
||||
ValueObjectSP valobj_backend_sp = m_backend.GetSP();
|
||||
if (!valobj_backend_sp)
|
||||
return false;
|
||||
|
||||
ValueObjectSP valobj_sp = valobj_backend_sp->GetNonSyntheticValue();
|
||||
if (!valobj_sp)
|
||||
return false;
|
||||
|
||||
ValueObjectSP tuple_sp =
|
||||
valobj_sp->GetChildMemberWithName(ConstString("_M_t"), true);
|
||||
if (!tuple_sp)
|
||||
return false;
|
||||
|
||||
std::unique_ptr<SyntheticChildrenFrontEnd> tuple_frontend(
|
||||
LibStdcppTupleSyntheticFrontEndCreator(nullptr, tuple_sp));
|
||||
|
||||
m_ptr_obj = tuple_frontend->GetChildAtIndex(0);
|
||||
if (m_ptr_obj)
|
||||
m_ptr_obj->SetName(ConstString("pointer"));
|
||||
|
||||
m_del_obj = tuple_frontend->GetChildAtIndex(1);
|
||||
if (m_del_obj)
|
||||
m_del_obj->SetName(ConstString("deleter"));
|
||||
|
||||
if (m_ptr_obj) {
|
||||
Error error;
|
||||
m_obj_obj = m_ptr_obj->Dereference(error);
|
||||
if (error.Success()) {
|
||||
m_obj_obj->SetName(ConstString("object"));
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool LibStdcppUniquePtrSyntheticFrontEnd::MightHaveChildren() { return true; }
|
||||
|
||||
lldb::ValueObjectSP
|
||||
LibStdcppUniquePtrSyntheticFrontEnd::GetChildAtIndex(size_t idx) {
|
||||
if (idx == 0)
|
||||
return m_obj_obj;
|
||||
if (idx == 1)
|
||||
return m_del_obj;
|
||||
if (idx == 2)
|
||||
return m_ptr_obj;
|
||||
return lldb::ValueObjectSP();
|
||||
}
|
||||
|
||||
size_t LibStdcppUniquePtrSyntheticFrontEnd::CalculateNumChildren() {
|
||||
if (m_del_obj)
|
||||
return 2;
|
||||
if (m_ptr_obj && m_ptr_obj->GetValueAsUnsigned(0) != 0)
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
size_t LibStdcppUniquePtrSyntheticFrontEnd::GetIndexOfChildWithName(
|
||||
const ConstString &name) {
|
||||
if (name == ConstString("obj") || name == ConstString("object"))
|
||||
return 0;
|
||||
if (name == ConstString("del") || name == ConstString("deleter"))
|
||||
return 1;
|
||||
if (name == ConstString("ptr") || name == ConstString("pointer"))
|
||||
return 2;
|
||||
return UINT32_MAX;
|
||||
}
|
||||
|
||||
bool LibStdcppUniquePtrSyntheticFrontEnd::GetSummary(
|
||||
Stream &stream, const TypeSummaryOptions &options) {
|
||||
if (!m_ptr_obj)
|
||||
return false;
|
||||
|
||||
if (m_ptr_obj->GetValueAsUnsigned(0) == 0) {
|
||||
stream.Printf("nullptr");
|
||||
} else {
|
||||
Error error;
|
||||
bool print_pointee = false;
|
||||
if (m_obj_obj) {
|
||||
if (m_obj_obj->DumpPrintableRepresentation(
|
||||
stream, ValueObject::eValueObjectRepresentationStyleSummary,
|
||||
lldb::eFormatInvalid,
|
||||
ValueObject::ePrintableRepresentationSpecialCasesDisable,
|
||||
false)) {
|
||||
print_pointee = true;
|
||||
}
|
||||
}
|
||||
if (!print_pointee)
|
||||
stream.Printf("ptr = 0x%" PRIx64, m_ptr_obj->GetValueAsUnsigned(0));
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
SyntheticChildrenFrontEnd *
|
||||
lldb_private::formatters::LibStdcppUniquePtrSyntheticFrontEndCreator(
|
||||
CXXSyntheticChildren *, lldb::ValueObjectSP valobj_sp) {
|
||||
return (valobj_sp ? new LibStdcppUniquePtrSyntheticFrontEnd(valobj_sp)
|
||||
: nullptr);
|
||||
}
|
||||
|
||||
bool lldb_private::formatters::LibStdcppUniquePointerSummaryProvider(
|
||||
ValueObject &valobj, Stream &stream, const TypeSummaryOptions &options) {
|
||||
LibStdcppUniquePtrSyntheticFrontEnd formatter(valobj.GetSP());
|
||||
return formatter.GetSummary(stream, options);
|
||||
}
|
Loading…
Reference in New Issue