Skip to content

Commit f78c4ce

Browse files
authored
[LLDB] Add formatters for MSVC STL std::atomic (llvm#149801)
Adds synthetic children and a summary provider for `std::atomic` on MSVC's STL. This currently only supports DWARF because it relies on the template argument. Once there are PDB tests, this will probably use the return type of some method like `value()` because template types aren't available there. Towards llvm#24834.
1 parent 7d9f913 commit f78c4ce

File tree

5 files changed

+129
-0
lines changed

5 files changed

+129
-0
lines changed

lldb/source/Plugins/Language/CPlusPlus/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ add_lldb_library(lldbPluginCPlusPlusLanguage PLUGIN
3434
LibStdcppTuple.cpp
3535
LibStdcppUniquePointer.cpp
3636
MsvcStl.cpp
37+
MsvcStlAtomic.cpp
3738
MsvcStlSmartPointer.cpp
3839
MsvcStlTuple.cpp
3940
MsvcStlVariant.cpp

lldb/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.cpp

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1780,6 +1780,9 @@ static void LoadMsvcStlFormatters(lldb::TypeCategoryImplSP cpp_category_sp) {
17801780
.SetDontShowValue(false)
17811781
.SetShowMembersOneLiner(false)
17821782
.SetHideItemNames(false);
1783+
SyntheticChildren::Flags stl_synth_flags;
1784+
stl_synth_flags.SetCascades(true).SetSkipPointers(false).SetSkipReferences(
1785+
false);
17831786

17841787
using StringElementType = StringPrinter::StringElementType;
17851788

@@ -1801,6 +1804,16 @@ static void LoadMsvcStlFormatters(lldb::TypeCategoryImplSP cpp_category_sp) {
18011804
stl_summary_flags,
18021805
MsvcStlStringSummaryProvider<StringElementType::UTF32>,
18031806
"MSVC STL std::u32string summary provider"));
1807+
1808+
stl_summary_flags.SetDontShowChildren(false);
1809+
1810+
AddCXXSynthetic(cpp_category_sp, MsvcStlAtomicSyntheticFrontEndCreator,
1811+
"MSVC STL std::atomic synthetic children",
1812+
"^std::atomic<.+>$", stl_synth_flags, true);
1813+
1814+
AddCXXSummary(cpp_category_sp, MsvcStlAtomicSummaryProvider,
1815+
"MSVC STL std::atomic summary provider", "^std::atomic<.+>$",
1816+
stl_summary_flags, true);
18041817
}
18051818

18061819
static void LoadSystemFormatters(lldb::TypeCategoryImplSP cpp_category_sp) {

lldb/source/Plugins/Language/CPlusPlus/MsvcStl.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,13 @@ SyntheticChildrenFrontEnd *
7979
MsvcStlVariantSyntheticFrontEndCreator(CXXSyntheticChildren *,
8080
lldb::ValueObjectSP valobj_sp);
8181

82+
// MSVC STL std::atomic<>
83+
bool MsvcStlAtomicSummaryProvider(ValueObject &valobj, Stream &stream,
84+
const TypeSummaryOptions &options);
85+
SyntheticChildrenFrontEnd *
86+
MsvcStlAtomicSyntheticFrontEndCreator(CXXSyntheticChildren *,
87+
lldb::ValueObjectSP valobj_sp);
88+
8289
} // namespace formatters
8390
} // namespace lldb_private
8491

Lines changed: 102 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,102 @@
1+
//===-- MsvcStlAtomic.cpp -------------------------------------------------===//
2+
//
3+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4+
// See https://llvm.org/LICENSE.txt for license information.
5+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
//
7+
//===----------------------------------------------------------------------===//
8+
9+
#include "MsvcStl.h"
10+
11+
#include "lldb/DataFormatters/TypeSynthetic.h"
12+
13+
using namespace lldb;
14+
15+
namespace lldb_private {
16+
namespace formatters {
17+
18+
class MsvcStlAtomicSyntheticFrontEnd : public SyntheticChildrenFrontEnd {
19+
public:
20+
MsvcStlAtomicSyntheticFrontEnd(lldb::ValueObjectSP valobj_sp);
21+
22+
llvm::Expected<uint32_t> CalculateNumChildren() override;
23+
24+
lldb::ValueObjectSP GetChildAtIndex(uint32_t idx) override;
25+
26+
lldb::ChildCacheState Update() override;
27+
28+
llvm::Expected<size_t> GetIndexOfChildWithName(ConstString name) override;
29+
30+
private:
31+
ValueObject *m_storage = nullptr;
32+
CompilerType m_element_type;
33+
};
34+
35+
} // namespace formatters
36+
} // namespace lldb_private
37+
38+
lldb_private::formatters::MsvcStlAtomicSyntheticFrontEnd::
39+
MsvcStlAtomicSyntheticFrontEnd(lldb::ValueObjectSP valobj_sp)
40+
: SyntheticChildrenFrontEnd(*valobj_sp), m_element_type() {
41+
if (valobj_sp)
42+
Update();
43+
}
44+
45+
llvm::Expected<uint32_t> lldb_private::formatters::
46+
MsvcStlAtomicSyntheticFrontEnd::CalculateNumChildren() {
47+
return m_storage ? 1 : 0;
48+
}
49+
50+
lldb::ValueObjectSP
51+
lldb_private::formatters::MsvcStlAtomicSyntheticFrontEnd::GetChildAtIndex(
52+
uint32_t idx) {
53+
if (idx == 0)
54+
return m_storage->Cast(m_element_type)->Clone(ConstString("Value"));
55+
return nullptr;
56+
}
57+
58+
lldb::ChildCacheState
59+
lldb_private::formatters::MsvcStlAtomicSyntheticFrontEnd::Update() {
60+
m_storage = nullptr;
61+
m_element_type.Clear();
62+
63+
ValueObjectSP storage_sp = m_backend.GetChildMemberWithName("_Storage");
64+
if (!storage_sp)
65+
return lldb::ChildCacheState::eRefetch;
66+
67+
m_element_type = m_backend.GetCompilerType().GetTypeTemplateArgument(0);
68+
if (!m_element_type)
69+
return lldb::ChildCacheState::eRefetch;
70+
71+
m_storage = storage_sp.get();
72+
return lldb::ChildCacheState::eRefetch;
73+
}
74+
75+
llvm::Expected<size_t> lldb_private::formatters::
76+
MsvcStlAtomicSyntheticFrontEnd::GetIndexOfChildWithName(ConstString name) {
77+
if (name == "Value")
78+
return 0;
79+
return llvm::createStringError("Type has no child named '%s'",
80+
name.AsCString());
81+
}
82+
83+
lldb_private::SyntheticChildrenFrontEnd *
84+
lldb_private::formatters::MsvcStlAtomicSyntheticFrontEndCreator(
85+
CXXSyntheticChildren *, lldb::ValueObjectSP valobj_sp) {
86+
return new MsvcStlAtomicSyntheticFrontEnd(valobj_sp);
87+
}
88+
89+
bool lldb_private::formatters::MsvcStlAtomicSummaryProvider(
90+
ValueObject &valobj, Stream &stream, const TypeSummaryOptions &options) {
91+
auto synth_sp = valobj.GetSyntheticValue();
92+
if (!synth_sp)
93+
return false;
94+
95+
auto value_sp = synth_sp->GetChildAtIndex(0);
96+
std::string summary;
97+
if (value_sp->GetSummaryAsCString(summary, options) && !summary.empty()) {
98+
stream << summary;
99+
return true;
100+
}
101+
return false;
102+
}

lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic/atomic/TestDataFormatterStdAtomic.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,3 +67,9 @@ def do_test(self):
6767
def test_libcxx(self):
6868
self.build(dictionary={"USE_LIBCPP": 1})
6969
self.do_test()
70+
71+
@add_test_categories(["msvcstl"])
72+
def test_msvcstl(self):
73+
# No flags, because the "msvcstl" category checks that the MSVC STL is used by default.
74+
self.build()
75+
self.do_test()

0 commit comments

Comments
 (0)