-
Notifications
You must be signed in to change notification settings - Fork 14.4k
[LLDB] Add formatters for MSVC STL std::shared_ptr #147575
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
base: main
Are you sure you want to change the base?
Changes from 1 commit
8894b65
083687d
51b5615
91fd149
3784e17
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -16,7 +16,7 @@ lldb::ValueObjectSP lldb_private::formatters::GetDesugaredSmartPointerValue( | |
|
||
auto arg = container_type.GetTypeTemplateArgument(0); | ||
if (!arg) | ||
return nullptr; | ||
return ptr.GetSP(); // FIXME: PDB doesn't have info about template arguments | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Instead of adding a workaround here can we just not call this at all in There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Ah but this only is a problem with PDB. So for MSVC STL+DWARF this would pass (which I guess is what the bots are running?). I don't think we need the FIXME in that case tbh. I think it's reasonable to say that if we don't have enough debug-info to look at the template argument, then let the pointer type be whatever we got from debug-info. Worth adding a comment about that though. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Can you confirm what configuration the bots are running though? Are we testing DWARF and PDB somewhere? Or just one of them? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
The API tests always run with DWARF: Makefile.rules. That's why it's a bit more complicated to add a PDB setting there - some tests would break with PDB.
Not in API tests. The shell tests do use PDB (when passing |
||
|
||
return ptr.Cast(arg.GetPointerType()); | ||
} |
Original file line number | Diff line number | Diff line change | ||||||||
---|---|---|---|---|---|---|---|---|---|---|
@@ -0,0 +1,170 @@ | ||||||||||
//===-- MsvcStlSmartPointer.cpp -------------------------------------------===// | ||||||||||
// | ||||||||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | ||||||||||
// See https://llvm.org/LICENSE.txt for license information. | ||||||||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | ||||||||||
// | ||||||||||
//===----------------------------------------------------------------------===// | ||||||||||
|
||||||||||
#include "Generic.h" | ||||||||||
#include "MsvcStl.h" | ||||||||||
|
||||||||||
#include "lldb/DataFormatters/FormattersHelpers.h" | ||||||||||
#include "lldb/DataFormatters/TypeSynthetic.h" | ||||||||||
|
||||||||||
using namespace lldb; | ||||||||||
|
||||||||||
bool lldb_private::formatters::IsMsvcStlSmartPointer(ValueObject &valobj) { | ||||||||||
std::vector<uint32_t> indexes; | ||||||||||
return valobj.GetCompilerType().GetIndexOfChildMemberWithName("_Ptr", true, | ||||||||||
indexes) > 0; | ||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
? |
||||||||||
} | ||||||||||
|
||||||||||
bool lldb_private::formatters::MsvcStlSmartPointerSummaryProvider( | ||||||||||
ValueObject &valobj, Stream &stream, const TypeSummaryOptions &options) { | ||||||||||
ValueObjectSP valobj_sp(valobj.GetNonSyntheticValue()); | ||||||||||
if (!valobj_sp) | ||||||||||
return false; | ||||||||||
|
||||||||||
ValueObjectSP ptr_sp(valobj_sp->GetChildMemberWithName("_Ptr")); | ||||||||||
ValueObjectSP ctrl_sp(valobj_sp->GetChildMemberWithName("_Rep")); | ||||||||||
if (!ctrl_sp || !ptr_sp) | ||||||||||
return false; | ||||||||||
|
||||||||||
DumpCxxSmartPtrPointerSummary(stream, *ptr_sp, options); | ||||||||||
|
||||||||||
bool success; | ||||||||||
uint64_t ctrl_addr = ctrl_sp->GetValueAsUnsigned(0, &success); | ||||||||||
// Empty control field (expired) | ||||||||||
if (!success || ctrl_addr == 0) | ||||||||||
return true; | ||||||||||
|
||||||||||
uint64_t uses = 0; | ||||||||||
if (auto uses_sp = ctrl_sp->GetChildMemberWithName("_Uses")) { | ||||||||||
bool success; | ||||||||||
uses = uses_sp->GetValueAsUnsigned(0, &success); | ||||||||||
if (!success) | ||||||||||
return false; | ||||||||||
|
||||||||||
stream.Printf(" strong=%" PRIu64, uses); | ||||||||||
} | ||||||||||
|
||||||||||
// _Weaks is the number of weak references - (_Uses != 0). | ||||||||||
if (auto weak_count_sp = ctrl_sp->GetChildMemberWithName("_Weaks")) { | ||||||||||
bool success; | ||||||||||
uint64_t count = weak_count_sp->GetValueAsUnsigned(0, &success); | ||||||||||
if (!success) | ||||||||||
return false; | ||||||||||
|
||||||||||
stream.Printf(" weak=%" PRIu64, count - (uses != 0)); | ||||||||||
} | ||||||||||
|
||||||||||
return true; | ||||||||||
} | ||||||||||
|
||||||||||
namespace lldb_private { | ||||||||||
namespace formatters { | ||||||||||
|
||||||||||
class MsvcStlSmartPointerSyntheticFrontEnd : public SyntheticChildrenFrontEnd { | ||||||||||
public: | ||||||||||
MsvcStlSmartPointerSyntheticFrontEnd(lldb::ValueObjectSP valobj_sp); | ||||||||||
|
||||||||||
llvm::Expected<uint32_t> CalculateNumChildren() override; | ||||||||||
|
||||||||||
lldb::ValueObjectSP GetChildAtIndex(uint32_t idx) override; | ||||||||||
|
||||||||||
lldb::ChildCacheState Update() override; | ||||||||||
|
||||||||||
llvm::Expected<size_t> GetIndexOfChildWithName(ConstString name) override; | ||||||||||
|
||||||||||
~MsvcStlSmartPointerSyntheticFrontEnd() override; | ||||||||||
|
||||||||||
private: | ||||||||||
ValueObject *m_ptr_obj = nullptr; | ||||||||||
}; | ||||||||||
|
||||||||||
} // namespace formatters | ||||||||||
} // namespace lldb_private | ||||||||||
|
||||||||||
lldb_private::formatters::MsvcStlSmartPointerSyntheticFrontEnd:: | ||||||||||
MsvcStlSmartPointerSyntheticFrontEnd(lldb::ValueObjectSP valobj_sp) | ||||||||||
: SyntheticChildrenFrontEnd(*valobj_sp) { | ||||||||||
if (valobj_sp) | ||||||||||
Update(); | ||||||||||
} | ||||||||||
|
||||||||||
llvm::Expected<uint32_t> lldb_private::formatters:: | ||||||||||
MsvcStlSmartPointerSyntheticFrontEnd::CalculateNumChildren() { | ||||||||||
return (m_ptr_obj ? 1 : 0); | ||||||||||
} | ||||||||||
|
||||||||||
lldb::ValueObjectSP | ||||||||||
lldb_private::formatters::MsvcStlSmartPointerSyntheticFrontEnd::GetChildAtIndex( | ||||||||||
uint32_t idx) { | ||||||||||
if (!m_ptr_obj) | ||||||||||
return lldb::ValueObjectSP(); | ||||||||||
|
||||||||||
ValueObjectSP valobj_sp = m_backend.GetSP(); | ||||||||||
if (!valobj_sp) | ||||||||||
return lldb::ValueObjectSP(); | ||||||||||
|
||||||||||
if (idx == 0) | ||||||||||
return m_ptr_obj->GetSP(); | ||||||||||
|
||||||||||
if (idx == 1) { | ||||||||||
Status status; | ||||||||||
ValueObjectSP value_sp = m_ptr_obj->Dereference(status); | ||||||||||
if (status.Success()) | ||||||||||
return value_sp; | ||||||||||
} | ||||||||||
|
||||||||||
return lldb::ValueObjectSP(); | ||||||||||
} | ||||||||||
|
||||||||||
lldb::ChildCacheState | ||||||||||
lldb_private::formatters::MsvcStlSmartPointerSyntheticFrontEnd::Update() { | ||||||||||
m_ptr_obj = nullptr; | ||||||||||
|
||||||||||
ValueObjectSP valobj_sp = m_backend.GetSP(); | ||||||||||
if (!valobj_sp) | ||||||||||
return lldb::ChildCacheState::eRefetch; | ||||||||||
|
||||||||||
auto ptr_obj_sp = valobj_sp->GetChildMemberWithName("_Ptr"); | ||||||||||
if (!ptr_obj_sp) | ||||||||||
return lldb::ChildCacheState::eRefetch; | ||||||||||
|
||||||||||
auto cast_ptr_sp = GetDesugaredSmartPointerValue(*ptr_obj_sp, *valobj_sp); | ||||||||||
if (!cast_ptr_sp) | ||||||||||
return lldb::ChildCacheState::eRefetch; | ||||||||||
|
||||||||||
m_ptr_obj = cast_ptr_sp->Clone(ConstString("pointer")).get(); | ||||||||||
return lldb::ChildCacheState::eRefetch; | ||||||||||
} | ||||||||||
|
||||||||||
llvm::Expected<size_t> | ||||||||||
lldb_private::formatters::MsvcStlSmartPointerSyntheticFrontEnd:: | ||||||||||
GetIndexOfChildWithName(ConstString name) { | ||||||||||
if (name == "_Ptr" || name == "pointer") | ||||||||||
return 0; | ||||||||||
|
||||||||||
if (name == "object" || name == "$$dereference$$") | ||||||||||
return 1; | ||||||||||
|
||||||||||
return llvm::createStringError("Type has no child named '%s'", | ||||||||||
name.AsCString()); | ||||||||||
} | ||||||||||
|
||||||||||
lldb_private::formatters::MsvcStlSmartPointerSyntheticFrontEnd:: | ||||||||||
~MsvcStlSmartPointerSyntheticFrontEnd() = default; | ||||||||||
|
||||||||||
lldb_private::SyntheticChildrenFrontEnd * | ||||||||||
lldb_private::formatters::MsvcStlSmartPointerSyntheticFrontEndCreator( | ||||||||||
lldb::ValueObjectSP valobj_sp) { | ||||||||||
if (!valobj_sp) | ||||||||||
return nullptr; | ||||||||||
|
||||||||||
if (!IsMsvcStlSmartPointer(*valobj_sp)) | ||||||||||
return nullptr; | ||||||||||
|
||||||||||
return new MsvcStlSmartPointerSyntheticFrontEnd(valobj_sp); | ||||||||||
} |
Original file line number | Diff line number | Diff line change | ||||||||
---|---|---|---|---|---|---|---|---|---|---|
|
@@ -118,3 +118,9 @@ def test_libcxx(self): | |||||||||
def test_libstdcxx(self): | ||||||||||
self.build(dictionary={"USE_LIBSTDCPP": 1}) | ||||||||||
self.do_test() | ||||||||||
|
||||||||||
@add_test_categories(["msvcstl"]) | ||||||||||
def test_msvcstl(self): | ||||||||||
# No flags, because the "msvcstl" category checks that the MSVC STL is used by default. | ||||||||||
self.build(dictionary={}) | ||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||||||
self.do_test() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
These registrations are getting a bit noisy in my opinion. Could we move all this to a separate helper called
RegisterCommonStlSmartPtrFormatters
(or something like that?There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This will be a problem for the other types as well. What about having a
Common{Type}SyntheticFrontEndCreator
andCommon{Type}SummaryProvider
inGeneric.h
(or maybe a new header)?