Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions lldb/source/Plugins/Language/CPlusPlus/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ add_lldb_library(lldbPluginCPlusPlusLanguage PLUGIN
LibStdcppTuple.cpp
LibStdcppUniquePointer.cpp
MsvcStl.cpp
MsvcStlAtomic.cpp
MsvcStlSmartPointer.cpp
MsvcStlTuple.cpp
MsvcStlVariant.cpp
Expand Down
13 changes: 13 additions & 0 deletions lldb/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1780,6 +1780,9 @@ static void LoadMsvcStlFormatters(lldb::TypeCategoryImplSP cpp_category_sp) {
.SetDontShowValue(false)
.SetShowMembersOneLiner(false)
.SetHideItemNames(false);
SyntheticChildren::Flags stl_synth_flags;
stl_synth_flags.SetCascades(true).SetSkipPointers(false).SetSkipReferences(
false);

using StringElementType = StringPrinter::StringElementType;

Expand All @@ -1801,6 +1804,16 @@ static void LoadMsvcStlFormatters(lldb::TypeCategoryImplSP cpp_category_sp) {
stl_summary_flags,
MsvcStlStringSummaryProvider<StringElementType::UTF32>,
"MSVC STL std::u32string summary provider"));

stl_summary_flags.SetDontShowChildren(false);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What happens if you don't set this? I think we probably do want this to be true? Would that make std::atomic look like:

(std::atomic<int>) val = 5

?

(i.e., just not print the synthetic child?)

I know that's not what libc++/libstdc++ does, but we probably should?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can be done separately since that's what libc++ and libstdc++ already do

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would that make std::atomic look like:

(std::atomic<int>) val = 5

?

Yes. I don't think that's always desired. Atomics can store structs as well (not sure why) and users might want to inspect these. This is also done in the tests here.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yea, I wondered if for summaries that can't be formatted without children this would then fall back to showing the children. But yea maybe not. Either way, not something you have to deal with here


AddCXXSynthetic(cpp_category_sp, MsvcStlAtomicSyntheticFrontEndCreator,
"MSVC STL std::atomic synthetic children",
"^std::atomic<.+>$", stl_synth_flags, true);

AddCXXSummary(cpp_category_sp, MsvcStlAtomicSummaryProvider,
"MSVC STL std::atomic summary provider", "^std::atomic<.+>$",
stl_summary_flags, true);
}

static void LoadSystemFormatters(lldb::TypeCategoryImplSP cpp_category_sp) {
Expand Down
7 changes: 7 additions & 0 deletions lldb/source/Plugins/Language/CPlusPlus/MsvcStl.h
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,13 @@ SyntheticChildrenFrontEnd *
MsvcStlVariantSyntheticFrontEndCreator(CXXSyntheticChildren *,
lldb::ValueObjectSP valobj_sp);

// MSVC STL std::atomic<>
bool MsvcStlAtomicSummaryProvider(ValueObject &valobj, Stream &stream,
const TypeSummaryOptions &options);
SyntheticChildrenFrontEnd *
MsvcStlAtomicSyntheticFrontEndCreator(CXXSyntheticChildren *,
lldb::ValueObjectSP valobj_sp);

} // namespace formatters
} // namespace lldb_private

Expand Down
102 changes: 102 additions & 0 deletions lldb/source/Plugins/Language/CPlusPlus/MsvcStlAtomic.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
//===-- MsvcStlAtomic.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 "MsvcStl.h"

#include "lldb/DataFormatters/TypeSynthetic.h"

using namespace lldb;

namespace lldb_private {
namespace formatters {

class MsvcStlAtomicSyntheticFrontEnd : public SyntheticChildrenFrontEnd {
public:
MsvcStlAtomicSyntheticFrontEnd(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;

private:
ValueObject *m_storage = nullptr;
CompilerType m_element_type;
};

} // namespace formatters
} // namespace lldb_private

lldb_private::formatters::MsvcStlAtomicSyntheticFrontEnd::
MsvcStlAtomicSyntheticFrontEnd(lldb::ValueObjectSP valobj_sp)
: SyntheticChildrenFrontEnd(*valobj_sp), m_element_type() {
if (valobj_sp)
Update();
}

llvm::Expected<uint32_t> lldb_private::formatters::
MsvcStlAtomicSyntheticFrontEnd::CalculateNumChildren() {
return m_storage ? 1 : 0;
}

lldb::ValueObjectSP
lldb_private::formatters::MsvcStlAtomicSyntheticFrontEnd::GetChildAtIndex(
uint32_t idx) {
if (idx == 0)
return m_storage->Cast(m_element_type)->Clone(ConstString("Value"));
return nullptr;
}

lldb::ChildCacheState
lldb_private::formatters::MsvcStlAtomicSyntheticFrontEnd::Update() {
m_storage = nullptr;
m_element_type.Clear();

ValueObjectSP storage_sp = m_backend.GetChildMemberWithName("_Storage");
if (!storage_sp)
return lldb::ChildCacheState::eRefetch;

m_element_type = m_backend.GetCompilerType().GetTypeTemplateArgument(0);
if (!m_element_type)
return lldb::ChildCacheState::eRefetch;

m_storage = storage_sp.get();
return lldb::ChildCacheState::eRefetch;
}

llvm::Expected<size_t> lldb_private::formatters::
MsvcStlAtomicSyntheticFrontEnd::GetIndexOfChildWithName(ConstString name) {
if (name == "Value")
return 0;
return llvm::createStringError("Type has no child named '%s'",
name.AsCString());
}

lldb_private::SyntheticChildrenFrontEnd *
lldb_private::formatters::MsvcStlAtomicSyntheticFrontEndCreator(
CXXSyntheticChildren *, lldb::ValueObjectSP valobj_sp) {
return new MsvcStlAtomicSyntheticFrontEnd(valobj_sp);
}

bool lldb_private::formatters::MsvcStlAtomicSummaryProvider(
ValueObject &valobj, Stream &stream, const TypeSummaryOptions &options) {
auto synth_sp = valobj.GetSyntheticValue();
if (!synth_sp)
return false;

auto value_sp = synth_sp->GetChildAtIndex(0);
std::string summary;
if (value_sp->GetSummaryAsCString(summary, options) && !summary.empty()) {
stream << summary;
return true;
}
return false;
}
Original file line number Diff line number Diff line change
Expand Up @@ -67,3 +67,9 @@ def do_test(self):
def test_libcxx(self):
self.build(dictionary={"USE_LIBCPP": 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()
self.do_test()
Loading