https://github.com/Nerixyz created https://github.com/llvm/llvm-project/pull/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 #24834. >From 679f4fae45cb25fbc16fc8117c287122afd219d2 Mon Sep 17 00:00:00 2001 From: Nerixyz <nerix...@outlook.de> Date: Mon, 21 Jul 2025 13:36:44 +0200 Subject: [PATCH] [LLDB] Add formatters for MSVC STL std::atomic --- .../Plugins/Language/CPlusPlus/CMakeLists.txt | 1 + .../Language/CPlusPlus/CPlusPlusLanguage.cpp | 14 +++ .../Plugins/Language/CPlusPlus/MsvcStl.h | 7 ++ .../Language/CPlusPlus/MsvcStlAtomic.cpp | 102 ++++++++++++++++++ .../atomic/TestDataFormatterStdAtomic.py | 6 ++ 5 files changed, 130 insertions(+) create mode 100644 lldb/source/Plugins/Language/CPlusPlus/MsvcStlAtomic.cpp diff --git a/lldb/source/Plugins/Language/CPlusPlus/CMakeLists.txt b/lldb/source/Plugins/Language/CPlusPlus/CMakeLists.txt index 5905d9b9a6d03..ce4e2d6f0f5af 100644 --- a/lldb/source/Plugins/Language/CPlusPlus/CMakeLists.txt +++ b/lldb/source/Plugins/Language/CPlusPlus/CMakeLists.txt @@ -34,6 +34,7 @@ add_lldb_library(lldbPluginCPlusPlusLanguage PLUGIN LibStdcppTuple.cpp LibStdcppUniquePointer.cpp MsvcStl.cpp + MsvcStlAtomic.cpp MsvcStlSmartPointer.cpp MsvcStlTuple.cpp MsvcStlVector.cpp diff --git a/lldb/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.cpp b/lldb/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.cpp index a0d5e1dfe3227..16b4d55d2db73 100644 --- a/lldb/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.cpp +++ b/lldb/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.cpp @@ -1763,6 +1763,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; @@ -1784,6 +1787,17 @@ 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); + stl_summary_flags.SetSkipPointers(false); + + 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) { diff --git a/lldb/source/Plugins/Language/CPlusPlus/MsvcStl.h b/lldb/source/Plugins/Language/CPlusPlus/MsvcStl.h index c08eecfdecee7..3ac12c17a96e1 100644 --- a/lldb/source/Plugins/Language/CPlusPlus/MsvcStl.h +++ b/lldb/source/Plugins/Language/CPlusPlus/MsvcStl.h @@ -71,6 +71,13 @@ SyntheticChildrenFrontEnd * MsvcStlOptionalSyntheticFrontEndCreator(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 diff --git a/lldb/source/Plugins/Language/CPlusPlus/MsvcStlAtomic.cpp b/lldb/source/Plugins/Language/CPlusPlus/MsvcStlAtomic.cpp new file mode 100644 index 0000000000000..3ec324577ac76 --- /dev/null +++ b/lldb/source/Plugins/Language/CPlusPlus/MsvcStlAtomic.cpp @@ -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; +} diff --git a/lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic/atomic/TestDataFormatterStdAtomic.py b/lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic/atomic/TestDataFormatterStdAtomic.py index 8186e1d66985b..bdf12ca3b86db 100644 --- a/lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic/atomic/TestDataFormatterStdAtomic.py +++ b/lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic/atomic/TestDataFormatterStdAtomic.py @@ -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() _______________________________________________ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits