mirror of
https://github.com/intel/llvm.git
synced 2026-01-24 17:01:00 +08:00
Revert "Improve the libstdc++ smart pointer formatters"
This reverts commit r284828, as it causes an infinite loop in TestPrintStackTraces (funnily enough, only when logging is enabled). llvm-svn: 285068
This commit is contained in:
@@ -2,7 +2,14 @@ LEVEL = ../../../../../make
|
||||
|
||||
CXX_SOURCES := main.cpp
|
||||
|
||||
CXXFLAGS := -O0
|
||||
USE_LIBSTDCPP := 1
|
||||
CFLAGS_EXTRAS += $(NO_LIMIT_DEBUG_INFO_FLAGS)
|
||||
|
||||
# clang-3.5+ outputs FullDebugInfo by default for Darwin/FreeBSD
|
||||
# targets. Other targets do not, which causes this test to fail.
|
||||
# This flag enables FullDebugInfo for all targets.
|
||||
ifneq (,$(findstring clang,$(CC)))
|
||||
CFLAGS_EXTRAS += -fno-limit-debug-info
|
||||
endif
|
||||
|
||||
include $(LEVEL)/Makefile.rules
|
||||
|
||||
@@ -31,58 +31,19 @@ class StdSmartPtrDataFormatterTestCase(TestBase):
|
||||
substrs=['stopped', 'stop reason = breakpoint'])
|
||||
|
||||
self.expect("frame variable nsp", substrs=['nsp = nullptr'])
|
||||
self.expect("frame variable isp", substrs=['isp = 123', 'strong=1', 'weak=1'])
|
||||
self.expect("frame variable ssp", substrs=['ssp = "foobar"', 'strong=1', 'weak=1'])
|
||||
self.expect("frame variable isp", substrs=['isp = 123'])
|
||||
self.expect("frame variable ssp", substrs=['ssp = "foobar"'])
|
||||
|
||||
self.expect("frame variable nwp", substrs=['nwp = nullptr'])
|
||||
self.expect("frame variable iwp", substrs=['iwp = 123', 'strong=1', 'weak=1'])
|
||||
self.expect("frame variable swp", substrs=['swp = "foobar"', 'strong=1', 'weak=1'])
|
||||
|
||||
frame = self.frame()
|
||||
self.assertTrue(frame.IsValid())
|
||||
|
||||
self.assertEqual(0, frame.GetValueForVariablePath("nsp.pointer").GetValueAsUnsigned())
|
||||
self.assertEqual(0, frame.GetValueForVariablePath("nwp.pointer").GetValueAsUnsigned())
|
||||
|
||||
self.assertNotEqual(0, frame.GetValueForVariablePath("isp.pointer").GetValueAsUnsigned())
|
||||
self.assertEqual(123, frame.GetValueForVariablePath("isp.object").GetValueAsUnsigned())
|
||||
self.assertEqual(1, frame.GetValueForVariablePath("isp.count").GetValueAsUnsigned())
|
||||
self.assertEqual(1, frame.GetValueForVariablePath("isp.weak_count").GetValueAsUnsigned())
|
||||
self.assertFalse(frame.GetValueForVariablePath("isp.foobar").IsValid())
|
||||
|
||||
self.assertNotEqual(0, frame.GetValueForVariablePath("ssp.pointer").GetValueAsUnsigned())
|
||||
self.assertEqual('"foobar"', frame.GetValueForVariablePath("ssp.object").GetSummary())
|
||||
self.assertEqual(1, frame.GetValueForVariablePath("ssp.count").GetValueAsUnsigned())
|
||||
self.assertEqual(1, frame.GetValueForVariablePath("ssp.weak_count").GetValueAsUnsigned())
|
||||
self.assertFalse(frame.GetValueForVariablePath("ssp.foobar").IsValid())
|
||||
|
||||
self.assertNotEqual(0, frame.GetValueForVariablePath("iwp.pointer").GetValueAsUnsigned())
|
||||
self.assertEqual(123, frame.GetValueForVariablePath("iwp.object").GetValueAsUnsigned())
|
||||
self.assertEqual(1, frame.GetValueForVariablePath("iwp.count").GetValueAsUnsigned())
|
||||
self.assertEqual(1, frame.GetValueForVariablePath("iwp.weak_count").GetValueAsUnsigned())
|
||||
self.assertFalse(frame.GetValueForVariablePath("iwp.foobar").IsValid())
|
||||
|
||||
self.assertNotEqual(0, frame.GetValueForVariablePath("swp.pointer").GetValueAsUnsigned())
|
||||
self.assertEqual('"foobar"', frame.GetValueForVariablePath("swp.object").GetSummary())
|
||||
self.assertEqual(1, frame.GetValueForVariablePath("swp.count").GetValueAsUnsigned())
|
||||
self.assertEqual(1, frame.GetValueForVariablePath("swp.weak_count").GetValueAsUnsigned())
|
||||
self.assertFalse(frame.GetValueForVariablePath("swp.foobar").IsValid())
|
||||
self.expect("frame variable iwp", substrs=['iwp = 123'])
|
||||
self.expect("frame variable swp", substrs=['swp = "foobar"'])
|
||||
|
||||
self.runCmd("continue")
|
||||
|
||||
frame = self.frame()
|
||||
self.assertTrue(frame.IsValid())
|
||||
|
||||
self.expect("frame variable nsp", substrs=['nsp = nullptr'])
|
||||
self.expect("frame variable isp", substrs=['isp = nullptr'])
|
||||
self.expect("frame variable ssp", substrs=['ssp = nullptr'])
|
||||
|
||||
self.expect("frame variable nwp", substrs=['nwp = nullptr'])
|
||||
self.expect("frame variable iwp", substrs=['iwp = nullptr', 'strong=0', 'weak=1'])
|
||||
self.expect("frame variable swp", substrs=['swp = nullptr', 'strong=0', 'weak=1'])
|
||||
|
||||
self.assertFalse(frame.GetValueForVariablePath("iwp.object").IsValid())
|
||||
self.assertEqual(0, frame.GetValueForVariablePath("iwp.count").GetValueAsUnsigned())
|
||||
self.assertEqual(1, frame.GetValueForVariablePath("iwp.weak_count").GetValueAsUnsigned())
|
||||
|
||||
self.assertFalse(frame.GetValueForVariablePath("swp.object").IsValid())
|
||||
self.assertEqual(0, frame.GetValueForVariablePath("swp.count").GetValueAsUnsigned())
|
||||
self.assertEqual(1, frame.GetValueForVariablePath("swp.weak_count").GetValueAsUnsigned())
|
||||
self.expect("frame variable iwp", substrs=['iwp = nullptr'])
|
||||
self.expect("frame variable swp", substrs=['swp = nullptr'])
|
||||
|
||||
@@ -10,7 +10,6 @@ add_lldb_library(lldbPluginCPlusPlusLanguage
|
||||
LibCxxUnorderedMap.cpp
|
||||
LibCxxVector.cpp
|
||||
LibStdcpp.cpp
|
||||
LibStdcppSmartPointer.cpp
|
||||
LibStdcppTuple.cpp
|
||||
LibStdcppUniquePointer.cpp
|
||||
)
|
||||
|
||||
@@ -63,6 +63,21 @@ private:
|
||||
lldb::ValueObjectSP m_pair_sp;
|
||||
};
|
||||
|
||||
class LibStdcppSharedPtrSyntheticFrontEnd : public SyntheticChildrenFrontEnd {
|
||||
public:
|
||||
explicit LibStdcppSharedPtrSyntheticFrontEnd(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;
|
||||
};
|
||||
|
||||
} // end of anonymous namespace
|
||||
|
||||
LibstdcppMapIteratorSyntheticFrontEnd::LibstdcppMapIteratorSyntheticFrontEnd(
|
||||
@@ -336,3 +351,80 @@ bool lldb_private::formatters::LibStdcppWStringSummaryProvider(
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
LibStdcppSharedPtrSyntheticFrontEnd::LibStdcppSharedPtrSyntheticFrontEnd(
|
||||
lldb::ValueObjectSP valobj_sp)
|
||||
: SyntheticChildrenFrontEnd(*valobj_sp) {
|
||||
if (valobj_sp)
|
||||
Update();
|
||||
}
|
||||
|
||||
size_t LibStdcppSharedPtrSyntheticFrontEnd::CalculateNumChildren() { return 1; }
|
||||
|
||||
lldb::ValueObjectSP
|
||||
LibStdcppSharedPtrSyntheticFrontEnd::GetChildAtIndex(size_t idx) {
|
||||
ValueObjectSP valobj_sp = m_backend.GetSP();
|
||||
if (!valobj_sp)
|
||||
return lldb::ValueObjectSP();
|
||||
|
||||
if (idx == 0)
|
||||
return valobj_sp->GetChildMemberWithName(ConstString("_M_ptr"), true);
|
||||
else
|
||||
return lldb::ValueObjectSP();
|
||||
}
|
||||
|
||||
bool LibStdcppSharedPtrSyntheticFrontEnd::Update() { return false; }
|
||||
|
||||
bool LibStdcppSharedPtrSyntheticFrontEnd::MightHaveChildren() { return true; }
|
||||
|
||||
size_t LibStdcppSharedPtrSyntheticFrontEnd::GetIndexOfChildWithName(
|
||||
const ConstString &name) {
|
||||
if (name == ConstString("_M_ptr"))
|
||||
return 0;
|
||||
return UINT32_MAX;
|
||||
}
|
||||
|
||||
SyntheticChildrenFrontEnd *
|
||||
lldb_private::formatters::LibStdcppSharedPtrSyntheticFrontEndCreator(
|
||||
CXXSyntheticChildren *, lldb::ValueObjectSP valobj_sp) {
|
||||
return (valobj_sp ? new LibStdcppSharedPtrSyntheticFrontEnd(valobj_sp)
|
||||
: nullptr);
|
||||
}
|
||||
|
||||
bool lldb_private::formatters::LibStdcppSmartPointerSummaryProvider(
|
||||
ValueObject &valobj, Stream &stream, const TypeSummaryOptions &options) {
|
||||
ValueObjectSP valobj_sp(valobj.GetNonSyntheticValue());
|
||||
if (!valobj_sp)
|
||||
return false;
|
||||
|
||||
ValueObjectSP ptr_sp(
|
||||
valobj_sp->GetChildMemberWithName(ConstString("_M_ptr"), true));
|
||||
if (!ptr_sp)
|
||||
return false;
|
||||
|
||||
ValueObjectSP usecount_sp(valobj_sp->GetChildAtNamePath(
|
||||
{ConstString("_M_refcount"), ConstString("_M_pi"),
|
||||
ConstString("_M_use_count")}));
|
||||
if (!usecount_sp)
|
||||
return false;
|
||||
|
||||
if (ptr_sp->GetValueAsUnsigned(0) == 0 ||
|
||||
usecount_sp->GetValueAsUnsigned(0) == 0) {
|
||||
stream.Printf("nullptr");
|
||||
return true;
|
||||
}
|
||||
|
||||
Error error;
|
||||
ValueObjectSP pointee_sp = ptr_sp->Dereference(error);
|
||||
if (pointee_sp && error.Success()) {
|
||||
if (pointee_sp->DumpPrintableRepresentation(
|
||||
stream, ValueObject::eValueObjectRepresentationStyleSummary,
|
||||
lldb::eFormatInvalid,
|
||||
ValueObject::ePrintableRepresentationSpecialCasesDisable, false)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
stream.Printf("ptr = 0x%" PRIx64, ptr_sp->GetValueAsUnsigned(0));
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -1,200 +0,0 @@
|
||||
//===-- LibStdcppSmartPointer.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 "lldb/Core/ConstString.h"
|
||||
#include "lldb/Core/ValueObject.h"
|
||||
#include "lldb/DataFormatters/FormattersHelpers.h"
|
||||
#include "lldb/DataFormatters/TypeSynthetic.h"
|
||||
#include "lldb/Target/Target.h"
|
||||
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
|
||||
using namespace lldb;
|
||||
using namespace lldb_private;
|
||||
using namespace lldb_private::formatters;
|
||||
|
||||
namespace {
|
||||
|
||||
class SharedPtrFrontEnd : public SyntheticChildrenFrontEnd {
|
||||
public:
|
||||
explicit SharedPtrFrontEnd(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_use_obj;
|
||||
ValueObjectSP m_weak_obj;
|
||||
|
||||
uint8_t m_ptr_size = 0;
|
||||
lldb::ByteOrder m_byte_order = lldb::eByteOrderInvalid;
|
||||
|
||||
bool IsEmpty();
|
||||
bool IsValid();
|
||||
};
|
||||
|
||||
} // end of anonymous namespace
|
||||
|
||||
SharedPtrFrontEnd::SharedPtrFrontEnd(lldb::ValueObjectSP valobj_sp)
|
||||
: SyntheticChildrenFrontEnd(*valobj_sp) {
|
||||
Update();
|
||||
}
|
||||
|
||||
bool SharedPtrFrontEnd::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;
|
||||
|
||||
TargetSP target_sp(valobj_sp->GetTargetSP());
|
||||
if (!target_sp)
|
||||
return false;
|
||||
|
||||
m_byte_order = target_sp->GetArchitecture().GetByteOrder();
|
||||
m_ptr_size = target_sp->GetArchitecture().GetAddressByteSize();
|
||||
|
||||
m_ptr_obj = valobj_sp->GetChildMemberWithName(ConstString("_M_ptr"), true);
|
||||
|
||||
m_use_obj = valobj_sp->GetChildAtNamePath({ConstString("_M_refcount"),
|
||||
ConstString("_M_pi"),
|
||||
ConstString("_M_use_count")});
|
||||
|
||||
m_weak_obj = valobj_sp->GetChildAtNamePath({ConstString("_M_refcount"),
|
||||
ConstString("_M_pi"),
|
||||
ConstString("_M_weak_count")});
|
||||
|
||||
// libstdc++ implements the weak usage count in a way that it is offset by 1
|
||||
// if the strong count is not 0 (as part of a preformance optimization). We
|
||||
// want to undo this before showing the weak count to the user as an offseted
|
||||
// weak count would be very confusing.
|
||||
if (m_use_obj && m_weak_obj && m_use_obj->GetValueAsUnsigned(0) > 0) {
|
||||
bool success = false;
|
||||
uint64_t count = m_weak_obj->GetValueAsUnsigned(0, &success) - 1;
|
||||
if (success) {
|
||||
auto data = std::make_shared<DataBufferHeap>(&count, sizeof(count));
|
||||
m_weak_obj = CreateValueObjectFromData(
|
||||
"weak_count", DataExtractor(data, m_byte_order, m_ptr_size),
|
||||
m_weak_obj->GetExecutionContextRef(), m_weak_obj->GetCompilerType());
|
||||
}
|
||||
}
|
||||
|
||||
if (m_ptr_obj && !IsEmpty()) {
|
||||
Error error;
|
||||
m_obj_obj = m_ptr_obj->Dereference(error);
|
||||
if (error.Success()) {
|
||||
m_obj_obj->SetName(ConstString("object"));
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool SharedPtrFrontEnd::MightHaveChildren() { return true; }
|
||||
|
||||
lldb::ValueObjectSP SharedPtrFrontEnd::GetChildAtIndex(size_t idx) {
|
||||
if (idx == 0)
|
||||
return m_obj_obj;
|
||||
if (idx == 1)
|
||||
return m_ptr_obj;
|
||||
if (idx == 2)
|
||||
return m_use_obj;
|
||||
if (idx == 3)
|
||||
return m_weak_obj;
|
||||
return lldb::ValueObjectSP();
|
||||
}
|
||||
|
||||
size_t SharedPtrFrontEnd::CalculateNumChildren() {
|
||||
if (IsEmpty())
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
size_t SharedPtrFrontEnd::GetIndexOfChildWithName(const ConstString &name) {
|
||||
if (name == ConstString("obj") || name == ConstString("object"))
|
||||
return 0;
|
||||
if (name == ConstString("ptr") || name == ConstString("pointer") ||
|
||||
name == ConstString("_M_ptr"))
|
||||
return 1;
|
||||
if (name == ConstString("cnt") || name == ConstString("count") ||
|
||||
name == ConstString("use_count") || name == ConstString("strong") ||
|
||||
name == ConstString("_M_use_count"))
|
||||
return 2;
|
||||
if (name == ConstString("weak") || name == ConstString("weak_count") ||
|
||||
name == ConstString("_M_weak_count"))
|
||||
return 3;
|
||||
return UINT32_MAX;
|
||||
}
|
||||
|
||||
bool SharedPtrFrontEnd::GetSummary(Stream &stream,
|
||||
const TypeSummaryOptions &options) {
|
||||
if (!IsValid())
|
||||
return false;
|
||||
|
||||
if (IsEmpty()) {
|
||||
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));
|
||||
}
|
||||
|
||||
if (m_use_obj && m_use_obj->GetError().Success())
|
||||
stream.Printf(" strong=%" PRIu64, m_use_obj->GetValueAsUnsigned(0));
|
||||
|
||||
if (m_weak_obj && m_weak_obj->GetError().Success())
|
||||
stream.Printf(" weak=%" PRIu64, m_weak_obj->GetValueAsUnsigned(0));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool SharedPtrFrontEnd::IsValid() { return m_ptr_obj != nullptr; }
|
||||
|
||||
bool SharedPtrFrontEnd::IsEmpty() {
|
||||
return !IsValid() || m_ptr_obj->GetValueAsUnsigned(0) == 0 ||
|
||||
(m_use_obj && m_use_obj->GetValueAsUnsigned(0) == 0);
|
||||
}
|
||||
|
||||
SyntheticChildrenFrontEnd *
|
||||
lldb_private::formatters::LibStdcppSharedPtrSyntheticFrontEndCreator(
|
||||
CXXSyntheticChildren *, lldb::ValueObjectSP valobj_sp) {
|
||||
return valobj_sp ? new SharedPtrFrontEnd(valobj_sp) : nullptr;
|
||||
}
|
||||
|
||||
bool lldb_private::formatters::LibStdcppSmartPointerSummaryProvider(
|
||||
ValueObject &valobj, Stream &stream, const TypeSummaryOptions &options) {
|
||||
SharedPtrFrontEnd formatter(valobj.GetSP());
|
||||
return formatter.GetSummary(stream, options);
|
||||
}
|
||||
Reference in New Issue
Block a user