-
Notifications
You must be signed in to change notification settings - Fork 14.5k
[lldb][Formatters] Add shared/weak count to libstdc++ std::shared_ptr summary #147166
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[lldb][Formatters] Add shared/weak count to libstdc++ std::shared_ptr summary #147166
Conversation
…rs consistent with each other
@llvm/pr-subscribers-lldb Author: Michael Buch (Michael137) ChangesDepends on #147165 This adds weak/strong counts to the std::shared_ptr summary of the libstdcxx formatters. We already do this for libcxx. This will make it easier to consolidate the tests into a generic one (see #147141). Full diff: https://github.com/llvm/llvm-project/pull/147166.diff 3 Files Affected:
diff --git a/lldb/source/Plugins/Language/CPlusPlus/LibCxx.cpp b/lldb/source/Plugins/Language/CPlusPlus/LibCxx.cpp
index 104521b8c3e71..aa13e66a1b550 100644
--- a/lldb/source/Plugins/Language/CPlusPlus/LibCxx.cpp
+++ b/lldb/source/Plugins/Language/CPlusPlus/LibCxx.cpp
@@ -238,7 +238,8 @@ lldb_private::formatters::LibCxxVectorIteratorSyntheticFrontEndCreator(
lldb_private::formatters::LibcxxSharedPtrSyntheticFrontEnd::
LibcxxSharedPtrSyntheticFrontEnd(lldb::ValueObjectSP valobj_sp)
- : SyntheticChildrenFrontEnd(*valobj_sp), m_cntrl(nullptr) {
+ : SyntheticChildrenFrontEnd(*valobj_sp), m_cntrl(nullptr),
+ m_ptr_obj(nullptr) {
if (valobj_sp)
Update();
}
@@ -251,7 +252,7 @@ llvm::Expected<uint32_t> lldb_private::formatters::
lldb::ValueObjectSP
lldb_private::formatters::LibcxxSharedPtrSyntheticFrontEnd::GetChildAtIndex(
uint32_t idx) {
- if (!m_cntrl)
+ if (!m_cntrl || !m_ptr_obj)
return lldb::ValueObjectSP();
ValueObjectSP valobj_sp = m_backend.GetSP();
@@ -259,20 +260,17 @@ lldb_private::formatters::LibcxxSharedPtrSyntheticFrontEnd::GetChildAtIndex(
return lldb::ValueObjectSP();
if (idx == 0)
- return valobj_sp->GetChildMemberWithName("__ptr_");
+ return m_ptr_obj->GetSP();
if (idx == 1) {
- if (auto ptr_sp = valobj_sp->GetChildMemberWithName("__ptr_")) {
- Status status;
- auto value_type_sp =
- valobj_sp->GetCompilerType()
- .GetTypeTemplateArgument(0).GetPointerType();
- ValueObjectSP cast_ptr_sp = ptr_sp->Cast(value_type_sp);
- ValueObjectSP value_sp = cast_ptr_sp->Dereference(status);
- if (status.Success()) {
- return value_sp;
- }
- }
+ Status status;
+ auto value_type_sp = valobj_sp->GetCompilerType()
+ .GetTypeTemplateArgument(0)
+ .GetPointerType();
+ ValueObjectSP cast_ptr_sp = m_ptr_obj->Cast(value_type_sp);
+ ValueObjectSP value_sp = cast_ptr_sp->Dereference(status);
+ if (status.Success())
+ return value_sp;
}
return lldb::ValueObjectSP();
@@ -281,6 +279,7 @@ lldb_private::formatters::LibcxxSharedPtrSyntheticFrontEnd::GetChildAtIndex(
lldb::ChildCacheState
lldb_private::formatters::LibcxxSharedPtrSyntheticFrontEnd::Update() {
m_cntrl = nullptr;
+ m_ptr_obj = nullptr;
ValueObjectSP valobj_sp = m_backend.GetSP();
if (!valobj_sp)
@@ -290,6 +289,12 @@ lldb_private::formatters::LibcxxSharedPtrSyntheticFrontEnd::Update() {
if (!target_sp)
return lldb::ChildCacheState::eRefetch;
+ auto ptr_obj_sp = valobj_sp->GetChildMemberWithName("__ptr_");
+ if (!ptr_obj_sp)
+ return lldb::ChildCacheState::eRefetch;
+
+ m_ptr_obj = ptr_obj_sp->Clone(ConstString("pointer")).get();
+
lldb::ValueObjectSP cntrl_sp(valobj_sp->GetChildMemberWithName("__cntrl_"));
m_cntrl = cntrl_sp.get(); // need to store the raw pointer to avoid a circular
@@ -300,10 +305,12 @@ lldb_private::formatters::LibcxxSharedPtrSyntheticFrontEnd::Update() {
llvm::Expected<size_t>
lldb_private::formatters::LibcxxSharedPtrSyntheticFrontEnd::
GetIndexOfChildWithName(ConstString name) {
- if (name == "__ptr_")
+ if (name == "__ptr_" || name == "pointer")
return 0;
- if (name == "$$dereference$$")
+
+ if (name == "object" || name == "$$dereference$$")
return 1;
+
return llvm::createStringError("Type has no child named '%s'",
name.AsCString());
}
diff --git a/lldb/source/Plugins/Language/CPlusPlus/LibCxx.h b/lldb/source/Plugins/Language/CPlusPlus/LibCxx.h
index 56501302d116f..6115ccde38ad2 100644
--- a/lldb/source/Plugins/Language/CPlusPlus/LibCxx.h
+++ b/lldb/source/Plugins/Language/CPlusPlus/LibCxx.h
@@ -108,6 +108,7 @@ class LibcxxSharedPtrSyntheticFrontEnd : public SyntheticChildrenFrontEnd {
private:
ValueObject *m_cntrl;
+ ValueObject *m_ptr_obj;
};
class LibcxxUniquePtrSyntheticFrontEnd : public SyntheticChildrenFrontEnd {
diff --git a/lldb/source/Plugins/Language/CPlusPlus/LibStdcpp.cpp b/lldb/source/Plugins/Language/CPlusPlus/LibStdcpp.cpp
index 28b7c01ab1b5b..5862a1ff3eac3 100644
--- a/lldb/source/Plugins/Language/CPlusPlus/LibStdcpp.cpp
+++ b/lldb/source/Plugins/Language/CPlusPlus/LibStdcpp.cpp
@@ -9,6 +9,7 @@
#include "LibStdcpp.h"
#include "LibCxx.h"
+#include "lldb/DataFormatters/FormattersHelpers.h"
#include "Plugins/TypeSystem/Clang/TypeSystemClang.h"
#include "lldb/DataFormatters/StringPrinter.h"
#include "lldb/DataFormatters/VectorIterator.h"
@@ -77,8 +78,7 @@ class LibStdcppSharedPtrSyntheticFrontEnd : public SyntheticChildrenFrontEnd {
// objects are only destroyed when every shared pointer to any of them
// is destroyed, so we must not store a shared pointer to any ValueObject
// derived from our backend ValueObject (since we're in the same cluster).
- ValueObject* m_ptr_obj = nullptr; // Underlying pointer (held, not owned)
- ValueObject* m_obj_obj = nullptr; // Underlying object (held, not owned)
+ ValueObject *m_ptr_obj = nullptr; // Underlying pointer (held, not owned)
};
} // end of anonymous namespace
@@ -266,15 +266,20 @@ LibStdcppSharedPtrSyntheticFrontEnd::GetChildAtIndex(uint32_t idx) {
if (idx == 0)
return m_ptr_obj->GetSP();
+
if (idx == 1) {
- if (m_ptr_obj && !m_obj_obj) {
- Status error;
- ValueObjectSP obj_obj = m_ptr_obj->Dereference(error);
- if (error.Success())
- m_obj_obj = obj_obj->Clone(ConstString("object")).get();
- }
- if (m_obj_obj)
- return m_obj_obj->GetSP();
+ ValueObjectSP valobj_sp = m_backend.GetSP();
+ if (!valobj_sp)
+ return nullptr;
+
+ Status status;
+ auto value_type_sp = valobj_sp->GetCompilerType()
+ .GetTypeTemplateArgument(0)
+ .GetPointerType();
+ ValueObjectSP cast_ptr_sp = m_ptr_obj->Cast(value_type_sp);
+ ValueObjectSP value_sp = cast_ptr_sp->Dereference(status);
+ if (status.Success())
+ return value_sp;
}
return lldb::ValueObjectSP();
}
@@ -293,7 +298,6 @@ lldb::ChildCacheState LibStdcppSharedPtrSyntheticFrontEnd::Update() {
return lldb::ChildCacheState::eRefetch;
m_ptr_obj = ptr_obj_sp->Clone(ConstString("pointer")).get();
- m_obj_obj = nullptr;
return lldb::ChildCacheState::eRefetch;
}
@@ -302,8 +306,10 @@ llvm::Expected<size_t>
LibStdcppSharedPtrSyntheticFrontEnd::GetIndexOfChildWithName(ConstString name) {
if (name == "pointer")
return 0;
+
if (name == "object" || name == "$$dereference$$")
return 1;
+
return llvm::createStringError("Type has no child named '%s'",
name.AsCString());
}
@@ -325,29 +331,37 @@ bool lldb_private::formatters::LibStdcppSmartPointerSummaryProvider(
if (!ptr_sp)
return false;
- ValueObjectSP usecount_sp(
- valobj_sp->GetChildAtNamePath({"_M_refcount", "_M_pi", "_M_use_count"}));
- if (!usecount_sp)
+ DumpCxxSmartPtrPointerSummary(stream, *ptr_sp, options);
+
+ ValueObjectSP pi_sp = valobj_sp->GetChildAtNamePath({"_M_refcount", "_M_pi"});
+ if (!pi_sp)
return false;
- if (ptr_sp->GetValueAsUnsigned(0) == 0 ||
- usecount_sp->GetValueAsUnsigned(0) == 0) {
- stream.Printf("nullptr");
+ bool success;
+ uint64_t pi_addr = pi_sp->GetValueAsUnsigned(0, &success);
+ // Empty control field. We're done.
+ if (!success || pi_addr == 0)
return true;
+
+ int64_t shared_count = 0;
+ if (auto count_sp = pi_sp->GetChildMemberWithName("_M_use_count")) {
+ bool success;
+ shared_count = count_sp->GetValueAsSigned(0, &success);
+ if (!success)
+ return false;
+
+ stream.Printf(" strong=%" PRId64, shared_count);
}
- 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)) {
- return true;
- }
+ // _M_weak_count is the number of weak references + (_M_use_count != 0).
+ if (auto weak_count_sp = pi_sp->GetChildMemberWithName("_M_weak_count")) {
+ bool success;
+ int64_t count = weak_count_sp->GetValueAsUnsigned(0, &success);
+ if (!success)
+ return false;
+
+ stream.Printf(" weak=%" PRId64, count - (shared_count != 0));
}
- stream.Printf("ptr = 0x%" PRIx64, ptr_sp->GetValueAsUnsigned(0));
return true;
}
|
✅ With the latest revision this PR passed the C/C++ code formatter. |
Depends on #147165
This adds weak/strong counts to the std::shared_ptr summary of the libstdcxx formatters. We already do this for libcxx. This will make it easier to consolidate the tests into a generic one (see #147141).