llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT--> @llvm/pr-subscribers-lldb Author: nerix (Nerixyz) <details> <summary>Changes</summary> Adds formatters for MSVC STL's unordered containers. This one is relatively simple, because it can reuse the `std::list` synthetic children. The unordered containers (aka [`_Hash`](https://github.com/microsoft/STL/blob/313964b78a8fd5a52e7965e13781f735bcce13c5/stl/inc/xhash#L327)) contain a [`_List`](https://github.com/microsoft/STL/blob/313964b78a8fd5a52e7965e13781f735bcce13c5/stl/inc/xhash#L2012) which contains all elements (and is used for iterating through the container). Towards https://github.com/llvm/llvm-project/issues/24834. --- Full diff: https://github.com/llvm/llvm-project/pull/149519.diff 5 Files Affected: - (modified) lldb/source/Plugins/Language/CPlusPlus/CMakeLists.txt (+1) - (modified) lldb/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.cpp (+24-4) - (modified) lldb/source/Plugins/Language/CPlusPlus/MsvcStl.h (+6) - (added) lldb/source/Plugins/Language/CPlusPlus/MsvcStlUnordered.cpp (+69) - (modified) lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic/unordered/TestDataFormatterGenericUnordered.py (+11-7) ``````````diff diff --git a/lldb/source/Plugins/Language/CPlusPlus/CMakeLists.txt b/lldb/source/Plugins/Language/CPlusPlus/CMakeLists.txt index 5905d9b9a6d03..c356a764d0717 100644 --- a/lldb/source/Plugins/Language/CPlusPlus/CMakeLists.txt +++ b/lldb/source/Plugins/Language/CPlusPlus/CMakeLists.txt @@ -37,6 +37,7 @@ add_lldb_library(lldbPluginCPlusPlusLanguage PLUGIN MsvcStlSmartPointer.cpp MsvcStlTuple.cpp MsvcStlVector.cpp + MsvcStlUnordered.cpp MSVCUndecoratedNameParser.cpp LINK_COMPONENTS diff --git a/lldb/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.cpp b/lldb/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.cpp index a8ebde0b55815..1800ec16656bb 100644 --- a/lldb/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.cpp +++ b/lldb/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.cpp @@ -1434,8 +1434,7 @@ static void LoadLibStdcppFormatters(lldb::TypeCategoryImplSP cpp_category_sp) { stl_deref_flags, "lldb.formatters.cpp.gnu_libstdcpp.StdMapLikeSynthProvider"))); cpp_category_sp->AddTypeSynthetic( - "^std::(__debug::)?unordered_(multi)?(map|set)<.+> >$", - eFormatterMatchRegex, + "^std::__debug::unordered_(multi)?(map|set)<.+> >$", eFormatterMatchRegex, SyntheticChildrenSP(new ScriptedSyntheticChildren( stl_deref_flags, "lldb.formatters.cpp.gnu_libstdcpp.StdUnorderedMapSynthProvider"))); @@ -1495,8 +1494,8 @@ static void LoadLibStdcppFormatters(lldb::TypeCategoryImplSP cpp_category_sp) { AddCXXSummary(cpp_category_sp, lldb_private::formatters::ContainerSizeSummaryProvider, - "libstdc++ std unordered container summary provider", - "^std::(__debug::)?unordered_(multi)?(map|set)<.+> >$", + "libstdc++ debug std unordered container summary provider", + "^std::__debug::unordered_(multi)?(map|set)<.+> >$", stl_summary_flags, true); AddCXXSummary( @@ -1648,6 +1647,19 @@ GenericForwardListSyntheticFrontEndCreator(CXXSyntheticChildren *children, *valobj_sp); } +static SyntheticChildrenFrontEnd * +GenericUnorderedSyntheticFrontEndCreator(CXXSyntheticChildren *children, + ValueObjectSP valobj_sp) { + if (!valobj_sp) + return nullptr; + + if (IsMsvcStlUnordered(*valobj_sp)) + return MsvcStlUnorderedSyntheticFrontEndCreator(children, valobj_sp); + return new ScriptedSyntheticChildren::FrontEnd( + "lldb.formatters.cpp.gnu_libstdcpp.StdUnorderedMapSynthProvider", + *valobj_sp); +} + /// Load formatters that are formatting types from more than one STL static void LoadCommonStlFormatters(lldb::TypeCategoryImplSP cpp_category_sp) { if (!cpp_category_sp) @@ -1712,6 +1724,10 @@ static void LoadCommonStlFormatters(lldb::TypeCategoryImplSP cpp_category_sp) { AddCXXSynthetic(cpp_category_sp, GenericForwardListSyntheticFrontEndCreator, "std::forward_list synthetic children", "^std::forward_list<.+>(( )?&)?$", stl_synth_flags, true); + AddCXXSynthetic(cpp_category_sp, GenericUnorderedSyntheticFrontEndCreator, + "std::unordered container synthetic children", + "^std::unordered_(multi)?(map|set)<.+> ?>$", stl_synth_flags, + true); AddCXXSummary(cpp_category_sp, GenericSmartPointerSummaryProvider, "MSVC STL/libstdc++ std::shared_ptr summary provider", @@ -1739,6 +1755,10 @@ static void LoadCommonStlFormatters(lldb::TypeCategoryImplSP cpp_category_sp) { TypeSummaryImplSP(new ScriptSummaryFormat( stl_summary_flags, "lldb.formatters.cpp.gnu_libstdcpp.ForwardListSummaryProvider"))); + AddCXXSummary(cpp_category_sp, ContainerSizeSummaryProvider, + "MSVC STL/libstdc++ std unordered container summary provider", + "^std::unordered_(multi)?(map|set)<.+> ?>$", stl_summary_flags, + true); } static void LoadMsvcStlFormatters(lldb::TypeCategoryImplSP cpp_category_sp) { diff --git a/lldb/source/Plugins/Language/CPlusPlus/MsvcStl.h b/lldb/source/Plugins/Language/CPlusPlus/MsvcStl.h index 0f3db4b50eeaf..4ea23d0310747 100644 --- a/lldb/source/Plugins/Language/CPlusPlus/MsvcStl.h +++ b/lldb/source/Plugins/Language/CPlusPlus/MsvcStl.h @@ -65,6 +65,12 @@ SyntheticChildrenFrontEnd * MsvcStlListSyntheticFrontEndCreator(CXXSyntheticChildren *, lldb::ValueObjectSP valobj_sp); +// MSVC STL std::unordered_(multi){map|set}<> +bool IsMsvcStlUnordered(ValueObject &valobj); +SyntheticChildrenFrontEnd * +MsvcStlUnorderedSyntheticFrontEndCreator(CXXSyntheticChildren *, + lldb::ValueObjectSP valobj_sp); + } // namespace formatters } // namespace lldb_private diff --git a/lldb/source/Plugins/Language/CPlusPlus/MsvcStlUnordered.cpp b/lldb/source/Plugins/Language/CPlusPlus/MsvcStlUnordered.cpp new file mode 100644 index 0000000000000..0472e0f5ad681 --- /dev/null +++ b/lldb/source/Plugins/Language/CPlusPlus/MsvcStlUnordered.cpp @@ -0,0 +1,69 @@ +//===-- MsvcStlUnordered.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; +using namespace lldb_private; + +namespace { + +class UnorderedFrontEnd : public SyntheticChildrenFrontEnd { +public: + UnorderedFrontEnd(ValueObject &valobj) : SyntheticChildrenFrontEnd(valobj) { + Update(); + } + + llvm::Expected<size_t> GetIndexOfChildWithName(ConstString name) override { + if (!m_list_sp) + return llvm::createStringError("Missing _List"); + return m_list_sp->GetIndexOfChildWithName(name); + } + + lldb::ChildCacheState Update() override; + + llvm::Expected<uint32_t> CalculateNumChildren() override { + if (!m_list_sp) + return llvm::createStringError("Missing _List"); + return m_list_sp->GetNumChildren(); + } + + ValueObjectSP GetChildAtIndex(uint32_t idx) override { + if (!m_list_sp) + return nullptr; + return m_list_sp->GetChildAtIndex(idx); + } + +private: + ValueObjectSP m_list_sp; +}; + +} // namespace + +lldb::ChildCacheState UnorderedFrontEnd::Update() { + m_list_sp = nullptr; + ValueObjectSP list_sp = m_backend.GetChildMemberWithName("_List"); + if (!list_sp) + return lldb::ChildCacheState::eRefetch; + m_list_sp = list_sp->GetSyntheticValue(); + return lldb::ChildCacheState::eRefetch; +} + +bool formatters::IsMsvcStlUnordered(ValueObject &valobj) { + if (auto valobj_sp = valobj.GetNonSyntheticValue()) + return valobj_sp->GetChildMemberWithName("_List") != nullptr; + return false; +} + +SyntheticChildrenFrontEnd *formatters::MsvcStlUnorderedSyntheticFrontEndCreator( + CXXSyntheticChildren *, lldb::ValueObjectSP valobj_sp) { + if (valobj_sp) + return new UnorderedFrontEnd(*valobj_sp); + return nullptr; +} diff --git a/lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic/unordered/TestDataFormatterGenericUnordered.py b/lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic/unordered/TestDataFormatterGenericUnordered.py index a4209ae069790..d23212443f1fb 100644 --- a/lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic/unordered/TestDataFormatterGenericUnordered.py +++ b/lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic/unordered/TestDataFormatterGenericUnordered.py @@ -2,17 +2,13 @@ from lldbsuite.test.lldbtest import * from lldbsuite.test import lldbutil -USE_LIBSTDCPP = "USE_LIBSTDCPP" -USE_LIBCPP = "USE_LIBCPP" - class GenericUnorderedDataFormatterTestCase(TestBase): def setUp(self): TestBase.setUp(self) self.namespace = "std" - def do_test_with_run_command(self, stdlib_type): - self.build(dictionary={stdlib_type: "1"}) + def do_test_with_run_command(self): self.runCmd("file " + self.getBuildArtifact("a.out"), CURRENT_EXECUTABLE_SET) lldbutil.run_break_set_by_source_regexp(self, "Set break point at this line.") @@ -127,8 +123,16 @@ def look_for_content_and_continue(self, var_name, patterns): @add_test_categories(["libstdcxx"]) def test_with_run_command_libstdcpp(self): - self.do_test_with_run_command(USE_LIBSTDCPP) + self.build(dictionary={"USE_LIBSTDCPP": 1}) + self.do_test_with_run_command() @add_test_categories(["libc++"]) def test_with_run_command_libcpp(self): - self.do_test_with_run_command(USE_LIBCPP) + self.build(dictionary={"USE_LIBCPP": 1}) + self.do_test_with_run_command() + + @add_test_categories(["msvcstl"]) + def test_with_run_command_msvcstl(self): + # No flags, because the "msvcstl" category checks that the MSVC STL is used by default. + self.build() + self.do_test_with_run_command() `````````` </details> https://github.com/llvm/llvm-project/pull/149519 _______________________________________________ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits