https://github.com/Nerixyz created https://github.com/llvm/llvm-project/pull/150513
Some formatters for the MSVC STL didn't work with the PDB symbol file plugins. They were only tested with DWARF. The individual changes are quite small (except for variant), so I'm not sure if they should be separate PRs. The changes are broadly: - Account for different type names (NativePDB has spaces after commas, but not after closing angle brackets) - Fall back to types of members if templates are not available - Account for anonymous unions being "flattened" into the parent type with DIA PDB It also adds tests for both plugins. They are shell tests, because API tests currently only test with DWARF and after #149305 they'd only test with one plugin. They're not as exhaustive as the API tests - their goal is to show that when using PDB, the STL types are still properly shown. For Native PDB I found two bugs which I haven't inspected closer: - For `std::optional`, [`_Has_value`](https://github.com/microsoft/STL/blob/f015db5833e8daf3a5534c4ce2b6c9acc9689b0c/stl/inc/optional#L75) got put into the union into a new struct that contained `_Value` and `_Has_value`. - `std::deque` uses a static constexpr `_Block_size` which doesn't have a value with native PDB (works with DIA). >From 709ca11c5393864867812d26df7fcd7ee4462557 Mon Sep 17 00:00:00 2001 From: Nerixyz <nerix...@outlook.de> Date: Thu, 24 Jul 2025 21:38:26 +0200 Subject: [PATCH 1/7] fix(string): make spaces in matcher optional --- .../Language/CPlusPlus/CPlusPlusLanguage.cpp | 32 ++++++++----------- 1 file changed, 13 insertions(+), 19 deletions(-) diff --git a/lldb/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.cpp b/lldb/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.cpp index e69f2f677e9ab..cd7cda4c91f04 100644 --- a/lldb/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.cpp +++ b/lldb/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.cpp @@ -1335,31 +1335,25 @@ static void LoadLibCxxFormatters(lldb::TypeCategoryImplSP cpp_category_sp) { static void RegisterStdStringSummaryProvider( const lldb::TypeCategoryImplSP &category_sp, llvm::StringRef string_ty, llvm::StringRef char_ty, lldb::TypeSummaryImplSP summary_sp) { - auto makeSpecifier = [](llvm::StringRef name) { - return std::make_shared<lldb_private::TypeNameSpecifierImpl>( - name, eFormatterMatchExact); - }; - - category_sp->AddTypeSummary(makeSpecifier(string_ty), summary_sp); - - // std::basic_string<char> category_sp->AddTypeSummary( - makeSpecifier(llvm::formatv("std::basic_string<{}>", char_ty).str()), + std::make_shared<lldb_private::TypeNameSpecifierImpl>( + string_ty, eFormatterMatchExact), summary_sp); - // std::basic_string<char,std::char_traits<char>,std::allocator<char> > + + // std::basic_string<char> category_sp->AddTypeSummary( - makeSpecifier(llvm::formatv("std::basic_string<{0},std::char_traits<{0}>," - "std::allocator<{0}> >", - char_ty) - .str()), + std::make_shared<lldb_private::TypeNameSpecifierImpl>( + llvm::formatv("std::basic_string<{}>", char_ty).str(), + eFormatterMatchExact), summary_sp); - // std::basic_string<char, std::char_traits<char>, std::allocator<char> > + // std::basic_string<char, std::char_traits<char>, std::allocator<char>> category_sp->AddTypeSummary( - makeSpecifier( - llvm::formatv("std::basic_string<{0}, std::char_traits<{0}>, " - "std::allocator<{0}> >", + std::make_shared<lldb_private::TypeNameSpecifierImpl>( + llvm::formatv("std::basic_string<{0}, ?std::char_traits<{0}>, " + "?std::allocator<{0}> ?>", char_ty) - .str()), + .str(), + eFormatterMatchRegex), summary_sp); } >From 119861a03b673ebeb0830cb3ddb7fe3fa069fefa Mon Sep 17 00:00:00 2001 From: Nerixyz <nerix...@outlook.de> Date: Thu, 24 Jul 2025 21:39:29 +0200 Subject: [PATCH 2/7] fix(list): fallback to type of value if templates are unavailable --- .../Language/CPlusPlus/GenericList.cpp | 20 ++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-) diff --git a/lldb/source/Plugins/Language/CPlusPlus/GenericList.cpp b/lldb/source/Plugins/Language/CPlusPlus/GenericList.cpp index ea1edbfd3ac9b..3d4dcfa3b4ff5 100644 --- a/lldb/source/Plugins/Language/CPlusPlus/GenericList.cpp +++ b/lldb/source/Plugins/Language/CPlusPlus/GenericList.cpp @@ -526,9 +526,17 @@ ValueObjectSP MsvcStlForwardListFrontEnd::GetChildAtIndex(uint32_t idx) { lldb::ChildCacheState MsvcStlForwardListFrontEnd::Update() { AbstractListFrontEnd::Update(); - if (auto head_sp = - m_backend.GetChildAtNamePath({"_Mypair", "_Myval2", "_Myhead"})) - m_head = head_sp.get(); + auto head_sp = + m_backend.GetChildAtNamePath({"_Mypair", "_Myval2", "_Myhead"}); + if (!head_sp) + return ChildCacheState::eRefetch; + + m_head = head_sp.get(); + if (!m_element_type) { + auto val_sp = head_sp->GetChildMemberWithName("_Myval"); + if (val_sp) + m_element_type = val_sp->GetCompilerType(); + } return ChildCacheState::eRefetch; } @@ -606,6 +614,12 @@ lldb::ChildCacheState MsvcStlListFrontEnd::Update() { m_head = first.get(); m_tail = last.get(); + if (!m_element_type) { + auto val_sp = m_head->GetChildMemberWithName("_Myval"); + if (val_sp) + m_element_type = val_sp->GetCompilerType(); + } + return lldb::ChildCacheState::eRefetch; } >From 12b4e322ddf54ae3f7eb72a89dbe5d62a9ddfc8b Mon Sep 17 00:00:00 2001 From: Nerixyz <nerix...@outlook.de> Date: Thu, 24 Jul 2025 21:41:13 +0200 Subject: [PATCH 3/7] fix(optional): try searching for _Value first --- .../Language/CPlusPlus/GenericOptional.cpp | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/lldb/source/Plugins/Language/CPlusPlus/GenericOptional.cpp b/lldb/source/Plugins/Language/CPlusPlus/GenericOptional.cpp index 7fc6eb55d4e3e..f9c8c0be7420d 100644 --- a/lldb/source/Plugins/Language/CPlusPlus/GenericOptional.cpp +++ b/lldb/source/Plugins/Language/CPlusPlus/GenericOptional.cpp @@ -117,12 +117,16 @@ ValueObjectSP GenericOptionalFrontend::GetChildAtIndex(uint32_t _idx) { ValueObjectSP candidate = val_sp->GetChildMemberWithName("_M_value"); if (candidate) val_sp = candidate; - } else if (m_stdlib == StdLib::MsvcStl) - // Same issue as with LibCxx - val_sp = m_backend.GetChildMemberWithName("_Has_value") - ->GetParent() - ->GetChildAtIndex(0) - ->GetChildMemberWithName("_Value"); + } else if (m_stdlib == StdLib::MsvcStl) { + // PDB flattens anonymous unions to the parent + val_sp = m_backend.GetChildMemberWithName("_Value"); + // With DWARF and NativePDB, same issue as with LibCxx + if (!val_sp) + val_sp = m_backend.GetChildMemberWithName("_Has_value") + ->GetParent() + ->GetChildAtIndex(0) + ->GetChildMemberWithName("_Value"); + } if (!val_sp) return ValueObjectSP(); >From e6fda6a3920cd262eb2c89125823f31e6503549b Mon Sep 17 00:00:00 2001 From: Nerixyz <nerix...@outlook.de> Date: Thu, 24 Jul 2025 21:41:40 +0200 Subject: [PATCH 4/7] fix(deque): fall back to element type if templates are unvailable --- .../Plugins/Language/CPlusPlus/MsvcStlDeque.cpp | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/lldb/source/Plugins/Language/CPlusPlus/MsvcStlDeque.cpp b/lldb/source/Plugins/Language/CPlusPlus/MsvcStlDeque.cpp index 873354381a6da..aa313abb04be2 100644 --- a/lldb/source/Plugins/Language/CPlusPlus/MsvcStlDeque.cpp +++ b/lldb/source/Plugins/Language/CPlusPlus/MsvcStlDeque.cpp @@ -111,13 +111,6 @@ lldb_private::formatters::MsvcStlDequeSyntheticFrontEnd::Update() { if (!block_size.IsValid()) return lldb::eRefetch; - auto element_type = deque_type.GetTypeTemplateArgument(0); - if (!element_type) - return lldb::eRefetch; - auto element_size = element_type.GetByteSize(nullptr); - if (!element_size) - return lldb::eRefetch; - auto offset_sp = storage_sp->GetChildMemberWithName("_Myoff"); auto map_size_sp = storage_sp->GetChildMemberWithName("_Mapsize"); auto map_sp = storage_sp->GetChildMemberWithName("_Map"); @@ -138,6 +131,16 @@ lldb_private::formatters::MsvcStlDequeSyntheticFrontEnd::Update() { if (!ok) return lldb::eRefetch; + auto element_type = deque_type.GetTypeTemplateArgument(0); + if (!element_type) { + element_type = map_sp->GetCompilerType().GetPointeeType().GetPointeeType(); + if (!element_type) + return lldb::eRefetch; + } + auto element_size = element_type.GetByteSize(nullptr); + if (!element_size) + return lldb::eRefetch; + m_map = map_sp.get(); m_exe_ctx_ref = m_backend.GetExecutionContextRef(); m_block_size = block_size.ULongLong(); >From eeef5f3cca3f51a0e02e0117017c4bbf13ae4070 Mon Sep 17 00:00:00 2001 From: Nerixyz <nerix...@outlook.de> Date: Thu, 24 Jul 2025 21:42:52 +0200 Subject: [PATCH 5/7] fix(variant): support DIA PDB --- .../Plugins/Language/CPlusPlus/MsvcStlVariant.cpp | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/lldb/source/Plugins/Language/CPlusPlus/MsvcStlVariant.cpp b/lldb/source/Plugins/Language/CPlusPlus/MsvcStlVariant.cpp index 52a3d98d2af4b..093726bb10595 100644 --- a/lldb/source/Plugins/Language/CPlusPlus/MsvcStlVariant.cpp +++ b/lldb/source/Plugins/Language/CPlusPlus/MsvcStlVariant.cpp @@ -42,7 +42,11 @@ namespace { // } ValueObjectSP GetStorageMember(ValueObject &valobj, llvm::StringRef name) { - // Find the union + // DIA PDB flattens the union into the storage + if (valobj.GetNumChildrenIgnoringErrors(3) >= 2) + return valobj.GetChildMemberWithName(name); + + // DWARF and NativePDB: Find the union ValueObjectSP union_sp = valobj.GetChildAtIndex(0); if (!union_sp) return nullptr; @@ -119,8 +123,12 @@ bool formatters::MsvcStlVariantSummaryProvider( storage_type = storage_type.GetTypedefedType(); CompilerType active_type = storage_type.GetTypeTemplateArgument(1, true); - if (!active_type) - return false; + if (!active_type) { + ValueObjectSP head = GetHead(*storage); + active_type = head->GetCompilerType(); + if (!active_type) + return false; + } stream << " Active Type = " << active_type.GetDisplayTypeName() << " "; return true; >From 66ab512bc28995d9e49caa233b8589d670938ab9 Mon Sep 17 00:00:00 2001 From: Nerixyz <nerix...@outlook.de> Date: Thu, 24 Jul 2025 21:43:19 +0200 Subject: [PATCH 6/7] fix(variant): support non-trivially destructable types --- .../Language/CPlusPlus/MsvcStlVariant.cpp | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/lldb/source/Plugins/Language/CPlusPlus/MsvcStlVariant.cpp b/lldb/source/Plugins/Language/CPlusPlus/MsvcStlVariant.cpp index 093726bb10595..b3a93a0786740 100644 --- a/lldb/source/Plugins/Language/CPlusPlus/MsvcStlVariant.cpp +++ b/lldb/source/Plugins/Language/CPlusPlus/MsvcStlVariant.cpp @@ -69,14 +69,18 @@ std::optional<int64_t> GetIndexValue(ValueObject &valobj) { } ValueObjectSP GetNthStorage(ValueObject &outer, int64_t index) { - // We need to find the std::_Variant_storage base class. - - // -> std::_SMF_control (typedef to std::_Variant_base) - ValueObjectSP container_sp = outer.GetSP()->GetChildAtIndex(0); - if (!container_sp) + // navigate "down" to std::_SMF_control/std::_Variant_base + // by finding the holder of "_Which". This might be down a few levels if a + // variant member isn't trivally destructible/copyable/etc. + ValueObjectSP which_sp = outer.GetChildMemberWithName("_Which"); + if (!which_sp) return nullptr; - // -> std::_Variant_storage - container_sp = container_sp->GetChildAtIndex(0); + ValueObject *parent = which_sp->GetParent(); + if (!parent) + return nullptr; + + // Now go to std::_Variant_storage + ValueObjectSP container_sp = parent->GetChildAtIndex(0); if (!container_sp) return nullptr; >From 25baf3501bcb052f39aaeca3192c9c200c25fec1 Mon Sep 17 00:00:00 2001 From: Nerixyz <nerix...@outlook.de> Date: Thu, 24 Jul 2025 21:44:29 +0200 Subject: [PATCH 7/7] test(STL): add shell tests for STL types with PDB and NativePDB --- .../Shell/SymbolFile/NativePDB/stl_types.test | 188 +++++++++++++++++ lldb/test/Shell/SymbolFile/PDB/stl_types.test | 197 ++++++++++++++++++ 2 files changed, 385 insertions(+) create mode 100644 lldb/test/Shell/SymbolFile/NativePDB/stl_types.test create mode 100644 lldb/test/Shell/SymbolFile/PDB/stl_types.test diff --git a/lldb/test/Shell/SymbolFile/NativePDB/stl_types.test b/lldb/test/Shell/SymbolFile/NativePDB/stl_types.test new file mode 100644 index 0000000000000..45960a80211e0 --- /dev/null +++ b/lldb/test/Shell/SymbolFile/NativePDB/stl_types.test @@ -0,0 +1,188 @@ +# REQUIRES: target-windows + +# Test that LLDB can format types from MSVC's STL +# RUN: split-file %s %t +# RUN: %build --compiler=clang-cl --std c++20 -o %t.exe -- %t/main.cpp +# RUN: %lldb -f %t.exe -s \ +# RUN: %t/commands.input 2>&1 | FileCheck %s + +#--- main.cpp + +#include <bitset> +#include <coroutine> +#include <deque> +#include <forward_list> +#include <list> +#include <map> +#include <memory> +#include <optional> +#include <set> +#include <string> +#include <tuple> +#include <unordered_map> +#include <unordered_set> +#include <variant> +#include <vector> + +int main() { + std::shared_ptr<int> sp = std::make_shared<int>(41); + std::weak_ptr<int> wp = sp; + std::unique_ptr<int> unique(new int(42)); + std::optional<std::u16string> opt = u"abc"; + std::string str = "str"; + std::u8string u8str = u8"str"; + std::wstring wStr = L"wstr"; + std::tuple<int, bool, float> tuple{1, false, 4.2}; + std::coroutine_handle<> coroHandle; + std::bitset<16> bitset(123); + + std::map<int, int> map{{1, 2}, {2, 4}, {3, 6}}; + auto mapIt = map.find(3); + std::set<int> set{1, 2, 3}; + std::multimap<int, int> mMap{{1, 2}, {1, 1}, {2, 4}}; + std::multiset<int> mSet{1, 2, 3}; + + std::variant<int, float, std::string, std::monostate> variant = "wow"; + std::list<int> list{1, 2, 3}; + std::forward_list<int> fwList{1, 2, 3}; + + std::unordered_map<int, int> uMap{{1, 2}, {2, 4}, {3, 6}}; + std::unordered_set<int> uSet{1, 2, 4}; + std::unordered_multimap<int, int> uMMap{{1, 2}, {1, 1}, {2, 4}}; + std::unordered_multiset<int> uMSet{1, 1, 2}; + std::deque<int> deque{1, 2, 3}; + std::vector<int> vec{1, 2, 3}; + return 0; // break here +} + +#--- commands.input + +br s -p "break here" +r + +fr v sp +fr v wp +fr v unique +# FIXME: _Has_value is put into the anonymous union along with _Value +# fr v opt +fr v str +fr v u8str +fr v wStr +fr v tuple +fr v map +fr v mapIt +fr v set +fr v mMap +fr v mSet +fr v variant +fr v list +fr v fwList +fr v uMap +fr v uSet +fr v uMMap +fr v uMSet +# FIXME: Static _Block_size is found but doesn't have a value +# fr v deque +fr v vec + +quit + +# CHECK: (lldb) fr v sp +# CHECK-NEXT: (std::shared_ptr<int>) sp = 41 strong=1 weak=1 { +# CHECK-NEXT: pointer = 0x{{.*}} +# CHECK-NEXT: } +# CHECK-NEXT: (lldb) fr v wp +# CHECK-NEXT: (std::weak_ptr<int>) wp = 41 strong=1 weak=1 { +# CHECK-NEXT: pointer = 0x{{.*}} +# CHECK-NEXT: } +# CHECK-NEXT: (lldb) fr v unique +# CHECK-NEXT: (std::unique_ptr<int, std::default_delete<int>>) unique = 42 { +# CHECK-NEXT: pointer = 0x{{.*}} +# CHECK-NEXT: } +# CHECK-NEXT: (lldb) fr v str +# CHECK-NEXT: (std::basic_string<char, std::char_traits<char>, std::allocator<char>>) str = "str" +# CHECK-NEXT: (lldb) fr v u8str +# CHECK-NEXT: (std::basic_string<char8_t, std::char_traits<char8_t>, std::allocator<char8_t>>) u8str = u8"str" +# CHECK-NEXT: (lldb) fr v wStr +# CHECK-NEXT: (std::basic_string<wchar_t, std::char_traits<wchar_t>, std::allocator<wchar_t>>) wStr = L"wstr" +# CHECK-NEXT: (lldb) fr v tuple +# CHECK-NEXT: (std::tuple<int, bool, float>) tuple = size=3 { +# CHECK-NEXT: [0] = 1 +# CHECK-NEXT: [1] = false +# CHECK-NEXT: [2] = 4.{{.*}} +# CHECK-NEXT: } +# CHECK-NEXT: (lldb) fr v map +# CHECK-NEXT: (std::map<int, int, std::less<int>, std::allocator<std::pair<int const, int>>>) map = size=3 { +# CHECK-NEXT: [0] = (first = 1, second = 2) +# CHECK-NEXT: [1] = (first = 2, second = 4) +# CHECK-NEXT: [2] = (first = 3, second = 6) +# CHECK-NEXT: } +# CHECK-NEXT: (lldb) fr v mapIt +# CHECK-NEXT: (std::_Tree_iterator<std::_Tree_val<std::_Tree_simple_types<std::pair<int const, int>>>>) mapIt = { +# CHECK-NEXT: first = 3 +# CHECK-NEXT: second = 6 +# CHECK-NEXT: } +# CHECK-NEXT: (lldb) fr v set +# CHECK-NEXT: (std::set<int, std::less<int>, std::allocator<int>>) set = size=3 { +# CHECK-NEXT: [0] = 1 +# CHECK-NEXT: [1] = 2 +# CHECK-NEXT: [2] = 3 +# CHECK-NEXT: } +# CHECK-NEXT: (lldb) fr v mMap +# CHECK-NEXT: (std::multimap<int, int, std::less<int>, std::allocator<std::pair<int const, int>>>) mMap = size=3 { +# CHECK-NEXT: [0] = (first = 1, second = 2) +# CHECK-NEXT: [1] = (first = 1, second = 1) +# CHECK-NEXT: [2] = (first = 2, second = 4) +# CHECK-NEXT: } +# CHECK-NEXT: (lldb) fr v mSet +# CHECK-NEXT: (std::multiset<int, std::less<int>, std::allocator<int>>) mSet = size=3 { +# CHECK-NEXT: [0] = 1 +# CHECK-NEXT: [1] = 2 +# CHECK-NEXT: [2] = 3 +# CHECK-NEXT: } +# CHECK-NEXT: (lldb) fr v variant +# CHECK-NEXT: (std::variant<int, float, std::basic_string<char, std::char_traits<char>, std::allocator<char>>, std::monostate>) variant = Active Type = std::basic_string<char, std::char_traits<char>, std::allocator<char>> { +# CHECK-NEXT: Value = "wow" +# CHECK-NEXT: } +# CHECK-NEXT: (lldb) fr v list +# CHECK-NEXT: (std::list<int, std::allocator<int>>) list = size=3 { +# CHECK-NEXT: [0] = 1 +# CHECK-NEXT: [1] = 2 +# CHECK-NEXT: [2] = 3 +# CHECK-NEXT: } +# CHECK-NEXT: (lldb) fr v fwList +# CHECK-NEXT: (std::forward_list<int, std::allocator<int>>) fwList = size=3 { +# CHECK-NEXT: [0] = 1 +# CHECK-NEXT: [1] = 2 +# CHECK-NEXT: [2] = 3 +# CHECK-NEXT: } +# CHECK-NEXT: (lldb) fr v uMap +# CHECK-NEXT: (std::unordered_map<int, int, std::hash<int>, std::equal_to<int>, std::allocator<std::pair<int const, int>>>) uMap = size=3 { +# CHECK-NEXT: [0] = (first = 1, second = 2) +# CHECK-NEXT: [1] = (first = 2, second = 4) +# CHECK-NEXT: [2] = (first = 3, second = 6) +# CHECK-NEXT: } +# CHECK-NEXT: (lldb) fr v uSet +# CHECK-NEXT: (std::unordered_set<int, std::hash<int>, std::equal_to<int>, std::allocator<int>>) uSet = size=3 { +# CHECK-NEXT: [0] = 1 +# CHECK-NEXT: [1] = 2 +# CHECK-NEXT: [2] = 4 +# CHECK-NEXT: } +# CHECK-NEXT: (lldb) fr v uMMap +# CHECK-NEXT: (std::unordered_multimap<int, int, std::hash<int>, std::equal_to<int>, std::allocator<std::pair<int const, int>>>) uMMap = size=3 { +# CHECK-NEXT: [0] = (first = 1, second = 2) +# CHECK-NEXT: [1] = (first = 1, second = 1) +# CHECK-NEXT: [2] = (first = 2, second = 4) +# CHECK-NEXT: } +# CHECK-NEXT: (lldb) fr v uMSet +# CHECK-NEXT: (std::unordered_multiset<int, std::hash<int>, std::equal_to<int>, std::allocator<int>>) uMSet = size=3 { +# CHECK-NEXT: [0] = 1 +# CHECK-NEXT: [1] = 1 +# CHECK-NEXT: [2] = 2 +# CHECK-NEXT: } +# CHECK-NEXT: (lldb) fr v vec +# CHECK-NEXT: (std::vector<int, std::allocator<int>>) vec = size=3 { +# CHECK-NEXT: [0] = 1 +# CHECK-NEXT: [1] = 2 +# CHECK-NEXT: [2] = 3 +# CHECK-NEXT: } diff --git a/lldb/test/Shell/SymbolFile/PDB/stl_types.test b/lldb/test/Shell/SymbolFile/PDB/stl_types.test new file mode 100644 index 0000000000000..0472bf5f27f06 --- /dev/null +++ b/lldb/test/Shell/SymbolFile/PDB/stl_types.test @@ -0,0 +1,197 @@ +# REQUIRES: target-windows + +# Test that LLDB can format types from MSVC's STL +# RUN: split-file %s %t +# RUN: %build --compiler=clang-cl --std c++20 -o %t.exe -- %t/main.cpp +# RUN: %lldb -f %t.exe -s \ +# RUN: %t/commands.input 2>&1 | FileCheck %s + +#--- main.cpp + +#include <bitset> +#include <coroutine> +#include <deque> +#include <forward_list> +#include <list> +#include <map> +#include <memory> +#include <optional> +#include <set> +#include <string> +#include <tuple> +#include <unordered_map> +#include <unordered_set> +#include <variant> +#include <vector> + +int main() { + std::shared_ptr<int> sp = std::make_shared<int>(41); + std::weak_ptr<int> wp = sp; + std::unique_ptr<int> unique(new int(42)); + std::optional<std::u16string> opt = u"abc"; + std::string str = "str"; + std::u8string u8str = u8"str"; + std::wstring wStr = L"wstr"; + std::tuple<int, bool, float> tuple{1, false, 4.2}; + std::coroutine_handle<> coroHandle; + std::bitset<16> bitset(123); + + std::map<int, int> map{{1, 2}, {2, 4}, {3, 6}}; + auto mapIt = map.find(3); + std::set<int> set{1, 2, 3}; + std::multimap<int, int> mMap{{1, 2}, {1, 1}, {2, 4}}; + std::multiset<int> mSet{1, 2, 3}; + + std::variant<int, float, std::string, std::monostate> variant = "wow"; + std::list<int> list{1, 2, 3}; + std::forward_list<int> fwList{1, 2, 3}; + + std::unordered_map<int, int> uMap{{1, 2}, {2, 4}, {3, 6}}; + std::unordered_set<int> uSet{1, 2, 4}; + std::unordered_multimap<int, int> uMMap{{1, 2}, {1, 1}, {2, 4}}; + std::unordered_multiset<int> uMSet{1, 1, 2}; + std::deque<int> deque{1, 2, 3}; + std::vector<int> vec{1, 2, 3}; + return 0; // break here +} + +#--- commands.input + +br s -p "break here" +r + +fr v sp +fr v wp +fr v unique +fr v opt +fr v str +# FIXME: char8_t is not recognized as a type - +# the string has a void pointer/void array for SSO storage. +# fr v u8str +fr v wStr +fr v tuple +fr v map +fr v mapIt +fr v set +fr v mMap +fr v mSet +fr v variant +fr v list +fr v fwList +fr v uMap +fr v uSet +fr v uMMap +fr v uMSet +# FIXME: Static _Block_size is found but doesn't have a value +fr v deque +fr v vec + +quit + +# CHECK: (lldb) fr v sp +# CHECK-NEXT: (std::shared_ptr<int>) sp = 41 strong=1 weak=1 { +# CHECK-NEXT: pointer = 0x{{.*}} +# CHECK-NEXT: } +# CHECK-NEXT: (lldb) fr v wp +# CHECK-NEXT: (std::weak_ptr<int>) wp = 41 strong=1 weak=1 { +# CHECK-NEXT: pointer = 0x{{.*}} +# CHECK-NEXT: } +# CHECK-NEXT: (lldb) fr v unique +# CHECK-NEXT: (std::unique_ptr<int,std::default_delete<int> >) unique = 42 { +# CHECK-NEXT: pointer = 0x{{.*}} +# CHECK-NEXT: } +# CHECK-NEXT: (lldb) fr v opt +# CHECK-NEXT: (std::optional<std::basic_string<char16_t,std::char_traits<char16_t>,std::allocator<char16_t> > >) opt = Has Value=true { +# CHECK-NEXT: Value = u"abc" +# CHECK-NEXT: } +# CHECK-NEXT: (lldb) fr v str +# CHECK-NEXT: (std::basic_string<char,std::char_traits<char>,std::allocator<char> >) str = "str" +# CHECK-NEXT: (lldb) fr v wStr +# CHECK-NEXT: (std::basic_string<wchar_t,std::char_traits<wchar_t>,std::allocator<wchar_t> >) wStr = L"wstr" +# CHECK-NEXT: (lldb) fr v tuple +# CHECK-NEXT: (std::tuple<int,bool,float>) tuple = size=3 { +# CHECK-NEXT: [0] = 1 +# CHECK-NEXT: [1] = false +# CHECK-NEXT: [2] = 4.{{.*}} +# CHECK-NEXT: } +# CHECK-NEXT: (lldb) fr v map +# CHECK-NEXT: (std::map<int,int,std::less<int>,std::allocator<std::pair<const int,int> > >) map = size=3 { +# CHECK-NEXT: [0] = (first = 1, second = 2) +# CHECK-NEXT: [1] = (first = 2, second = 4) +# CHECK-NEXT: [2] = (first = 3, second = 6) +# CHECK-NEXT: } +# CHECK-NEXT: (lldb) fr v mapIt +# CHECK-NEXT: (std::_Tree_iterator<std::_Tree_val<std::_Tree_simple_types<std::pair<const int,int> > > >) mapIt = { +# CHECK-NEXT: first = 3 +# CHECK-NEXT: second = 6 +# CHECK-NEXT: } +# CHECK-NEXT: (lldb) fr v set +# CHECK-NEXT: (std::set<int,std::less<int>,std::allocator<int> >) set = size=3 { +# CHECK-NEXT: [0] = 1 +# CHECK-NEXT: [1] = 2 +# CHECK-NEXT: [2] = 3 +# CHECK-NEXT: } +# CHECK-NEXT: (lldb) fr v mMap +# CHECK-NEXT: (std::multimap<int,int,std::less<int>,std::allocator<std::pair<const int,int> > >) mMap = size=3 { +# CHECK-NEXT: [0] = (first = 1, second = 2) +# CHECK-NEXT: [1] = (first = 1, second = 1) +# CHECK-NEXT: [2] = (first = 2, second = 4) +# CHECK-NEXT: } +# CHECK-NEXT: (lldb) fr v mSet +# CHECK-NEXT: (std::multiset<int,std::less<int>,std::allocator<int> >) mSet = size=3 { +# CHECK-NEXT: [0] = 1 +# CHECK-NEXT: [1] = 2 +# CHECK-NEXT: [2] = 3 +# CHECK-NEXT: } +# CHECK-NEXT: (lldb) fr v variant +# CHECK-NEXT: (std::variant<int,float,std::basic_string<char,std::char_traits<char>,std::allocator<char> >,std::monostate>) variant = Active Type = std::basic_string<char,std::char_traits<char>,std::allocator<char> > { +# CHECK-NEXT: Value = "wow" +# CHECK-NEXT: } +# CHECK-NEXT: (lldb) fr v list +# CHECK-NEXT: (std::list<int,std::allocator<int> >) list = size=3 { +# CHECK-NEXT: [0] = 1 +# CHECK-NEXT: [1] = 2 +# CHECK-NEXT: [2] = 3 +# CHECK-NEXT: } +# CHECK-NEXT: (lldb) fr v fwList +# CHECK-NEXT: (std::forward_list<int,std::allocator<int> >) fwList = size=3 { +# CHECK-NEXT: [0] = 1 +# CHECK-NEXT: [1] = 2 +# CHECK-NEXT: [2] = 3 +# CHECK-NEXT: } +# CHECK-NEXT: (lldb) fr v uMap +# CHECK-NEXT: (std::unordered_map<int,int,std::hash<int>,std::equal_to<int>,std::allocator<std::pair<const int,int> > >) uMap = size=3 { +# CHECK-NEXT: [0] = (first = 1, second = 2) +# CHECK-NEXT: [1] = (first = 2, second = 4) +# CHECK-NEXT: [2] = (first = 3, second = 6) +# CHECK-NEXT: } +# CHECK-NEXT: (lldb) fr v uSet +# CHECK-NEXT: (std::unordered_set<int,std::hash<int>,std::equal_to<int>,std::allocator<int> >) uSet = size=3 { +# CHECK-NEXT: [0] = 1 +# CHECK-NEXT: [1] = 2 +# CHECK-NEXT: [2] = 4 +# CHECK-NEXT: } +# CHECK-NEXT: (lldb) fr v uMMap +# CHECK-NEXT: (std::unordered_multimap<int,int,std::hash<int>,std::equal_to<int>,std::allocator<std::pair<const int,int> > >) uMMap = size=3 { +# CHECK-NEXT: [0] = (first = 1, second = 2) +# CHECK-NEXT: [1] = (first = 1, second = 1) +# CHECK-NEXT: [2] = (first = 2, second = 4) +# CHECK-NEXT: } +# CHECK-NEXT: (lldb) fr v uMSet +# CHECK-NEXT: (std::unordered_multiset<int,std::hash<int>,std::equal_to<int>,std::allocator<int> >) uMSet = size=3 { +# CHECK-NEXT: [0] = 1 +# CHECK-NEXT: [1] = 1 +# CHECK-NEXT: [2] = 2 +# CHECK-NEXT: } +# CHECK-NEXT: (lldb) fr v deque +# CHECK-NEXT: (std::deque<int,std::allocator<int> >) deque = size=3 { +# CHECK-NEXT: [0] = 1 +# CHECK-NEXT: [1] = 2 +# CHECK-NEXT: [2] = 3 +# CHECK-NEXT: } +# CHECK-NEXT: (lldb) fr v vec +# CHECK-NEXT: (std::vector<int,std::allocator<int> >) vec = size=3 { +# CHECK-NEXT: [0] = 1 +# CHECK-NEXT: [1] = 2 +# CHECK-NEXT: [2] = 3 +# CHECK-NEXT: } _______________________________________________ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits