https://github.com/Nerixyz updated https://github.com/llvm/llvm-project/pull/150513
>From 709ca11c5393864867812d26df7fcd7ee4462557 Mon Sep 17 00:00:00 2001 From: Nerixyz <[email protected]> Date: Thu, 24 Jul 2025 21:38:26 +0200 Subject: [PATCH 1/8] 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 <[email protected]> Date: Thu, 24 Jul 2025 21:39:29 +0200 Subject: [PATCH 2/8] 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 <[email protected]> Date: Thu, 24 Jul 2025 21:41:13 +0200 Subject: [PATCH 3/8] 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 <[email protected]> Date: Thu, 24 Jul 2025 21:41:40 +0200 Subject: [PATCH 4/8] 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 <[email protected]> Date: Thu, 24 Jul 2025 21:42:52 +0200 Subject: [PATCH 5/8] 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 <[email protected]> Date: Thu, 24 Jul 2025 21:43:19 +0200 Subject: [PATCH 6/8] 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 <[email protected]> Date: Thu, 24 Jul 2025 21:44:29 +0200 Subject: [PATCH 7/8] 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: } >From 81dac36ea620544a1862d671581611258228b1f8 Mon Sep 17 00:00:00 2001 From: Nerixyz <[email protected]> Date: Wed, 5 Nov 2025 22:58:51 +0100 Subject: [PATCH 8/8] refactor: use API tests --- .../Language/CPlusPlus/MsvcStlAtomic.cpp | 26 ++- .../NativePDB/UdtRecordCompleter.cpp | 8 +- .../atomic/TestDataFormatterStdAtomic.py | 2 + .../deque/TestDataFormatterGenericDeque.py | 2 + .../TestDataFormatterGenericForwardList.py | 2 + .../list/TestDataFormatterGenericList.py | 2 + .../generic/map/TestDataFormatterStdMap.py | 2 + .../TestDataFormatterGenericMultiMap.py | 2 + .../TestDataFormatterGenericMultiSet.py | 2 + .../TestDataFormatterGenericOptional.py | 14 +- .../set/TestDataFormatterGenericSet.py | 2 + .../TestDataFormatterStdSharedPtr.py | 14 +- .../string/TestDataFormatterStdString.py | 81 ++++--- .../TestDataFormatterStdStringView.py | 74 ++++--- .../tuple/TestDataFormatterStdTuple.py | 2 + .../u8string/TestDataFormatterStdU8String.py | 16 +- .../TestDataFormatterStdU8StringView.py | 16 +- .../TestDataFormatterStdUniquePtr.py | 12 +- .../TestDataFormatterGenericUnordered.py | 38 +++- .../variant/TestDataFormatterStdVariant.py | 2 + .../vbool/TestDataFormatterStdVBool.py | 2 + .../vector/TestDataFormatterStdVector.py | 22 +- .../Shell/SymbolFile/NativePDB/stl_types.test | 188 ----------------- lldb/test/Shell/SymbolFile/PDB/stl_types.test | 197 ------------------ 24 files changed, 260 insertions(+), 468 deletions(-) delete mode 100644 lldb/test/Shell/SymbolFile/NativePDB/stl_types.test delete mode 100644 lldb/test/Shell/SymbolFile/PDB/stl_types.test diff --git a/lldb/source/Plugins/Language/CPlusPlus/MsvcStlAtomic.cpp b/lldb/source/Plugins/Language/CPlusPlus/MsvcStlAtomic.cpp index 020ba10166231..fd700eee9e1a4 100644 --- a/lldb/source/Plugins/Language/CPlusPlus/MsvcStlAtomic.cpp +++ b/lldb/source/Plugins/Language/CPlusPlus/MsvcStlAtomic.cpp @@ -8,6 +8,7 @@ #include "MsvcStl.h" +#include "Plugins/TypeSystem/Clang/TypeSystemClang.h" #include "lldb/DataFormatters/TypeSynthetic.h" using namespace lldb; @@ -64,10 +65,31 @@ lldb_private::formatters::MsvcStlAtomicSyntheticFrontEnd::Update() { if (!storage_sp) return lldb::ChildCacheState::eRefetch; - m_element_type = m_backend.GetCompilerType().GetTypeTemplateArgument(0); - if (!m_element_type) + CompilerType backend_type = m_backend.GetCompilerType(); + if (!backend_type) return lldb::ChildCacheState::eRefetch; + m_element_type = backend_type.GetTypeTemplateArgument(0); + // PDB doesn't have info about templates, so this uses the return type of + // `load`. Which is equivalent to the template type. + if (!m_element_type) { + auto ast_ctx = backend_type.GetTypeSystem<TypeSystemClang>(); + if (!ast_ctx) + return lldb::ChildCacheState::eRefetch; + + clang::CXXRecordDecl *record_decl = + TypeSystemClang::GetAsCXXRecordDecl(backend_type.GetOpaqueQualType()); + for (const auto *method : record_decl->methods()) { + if (method->getDeclName().isIdentifier() && method->getName() == "load") { + m_element_type = ast_ctx->GetType(method->getReturnType()); + break; + } + } + + if (!m_element_type) + return lldb::ChildCacheState::eRefetch; + } + m_storage = storage_sp.get(); return lldb::ChildCacheState::eRefetch; } diff --git a/lldb/source/Plugins/SymbolFile/NativePDB/UdtRecordCompleter.cpp b/lldb/source/Plugins/SymbolFile/NativePDB/UdtRecordCompleter.cpp index 46cf9b8524ede..bfaba7f91b711 100644 --- a/lldb/source/Plugins/SymbolFile/NativePDB/UdtRecordCompleter.cpp +++ b/lldb/source/Plugins/SymbolFile/NativePDB/UdtRecordCompleter.cpp @@ -168,7 +168,13 @@ Error UdtRecordCompleter::visitKnownMember( // Static constant members may be a const[expr] declaration. // Query the symbol's value as the variable initializer if valid. if (member_ct.IsConst() && member_ct.IsCompleteType()) { - std::string qual_name = decl->getQualifiedNameAsString(); + std::string qual_name; + if (m_record.record.kind == Member::Struct) + qual_name = (m_cvr.cr.Name + "::" + static_data_member.Name).str(); + else if (m_record.record.kind == Member::Union) + qual_name = (m_cvr.ur.Name + "::" + static_data_member.Name).str(); + else + qual_name = decl->getQualifiedNameAsString(); auto results = m_index.globals().findRecordsByName(qual_name, m_index.symrecords()); 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 bdf12ca3b86db..67c2c359c9afb 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 @@ -10,6 +10,8 @@ class StdAtomicTestCase(TestBase): + TEST_WITH_PDB_DEBUG_INFO = True + def get_variable(self, name): var = self.frame().FindVariable(name) var.SetPreferDynamicValue(lldb.eDynamicCanRunTarget) diff --git a/lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic/deque/TestDataFormatterGenericDeque.py b/lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic/deque/TestDataFormatterGenericDeque.py index 2332eff7b10dd..2b22281a87318 100644 --- a/lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic/deque/TestDataFormatterGenericDeque.py +++ b/lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic/deque/TestDataFormatterGenericDeque.py @@ -5,6 +5,8 @@ class GenericDequeDataFormatterTestCase(TestBase): + TEST_WITH_PDB_DEBUG_INFO = True + def findVariable(self, name): var = self.frame().FindVariable(name) self.assertTrue(var.IsValid()) diff --git a/lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic/forward_list/TestDataFormatterGenericForwardList.py b/lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic/forward_list/TestDataFormatterGenericForwardList.py index 45695c43b42a9..1db0c489bc7f9 100644 --- a/lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic/forward_list/TestDataFormatterGenericForwardList.py +++ b/lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic/forward_list/TestDataFormatterGenericForwardList.py @@ -9,6 +9,8 @@ class TestDataFormatterGenericForwardList(TestBase): + TEST_WITH_PDB_DEBUG_INFO = True + def setUp(self): TestBase.setUp(self) self.line = line_number("main.cpp", "// break here") diff --git a/lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic/list/TestDataFormatterGenericList.py b/lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic/list/TestDataFormatterGenericList.py index c0207e6ab5911..fbd021190214b 100644 --- a/lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic/list/TestDataFormatterGenericList.py +++ b/lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic/list/TestDataFormatterGenericList.py @@ -10,6 +10,8 @@ class GenericListDataFormatterTestCase(TestBase): + TEST_WITH_PDB_DEBUG_INFO = True + def setUp(self): # Call super's setUp(). TestBase.setUp(self) diff --git a/lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic/map/TestDataFormatterStdMap.py b/lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic/map/TestDataFormatterStdMap.py index 07d6c963eb05d..ca2d2d6b49541 100644 --- a/lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic/map/TestDataFormatterStdMap.py +++ b/lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic/map/TestDataFormatterStdMap.py @@ -9,6 +9,8 @@ class StdMapDataFormatterTestCase(TestBase): + TEST_WITH_PDB_DEBUG_INFO = True + def setUp(self): TestBase.setUp(self) ns = "ndk" if lldbplatformutil.target_is_android() else "" diff --git a/lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic/multimap/TestDataFormatterGenericMultiMap.py b/lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic/multimap/TestDataFormatterGenericMultiMap.py index 7ac79714db88d..4b0854b180e0a 100644 --- a/lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic/multimap/TestDataFormatterGenericMultiMap.py +++ b/lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic/multimap/TestDataFormatterGenericMultiMap.py @@ -11,6 +11,8 @@ class GenericMultiMapDataFormatterTestCase(TestBase): + TEST_WITH_PDB_DEBUG_INFO = True + def setUp(self): TestBase.setUp(self) self.namespace = "std" diff --git a/lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic/multiset/TestDataFormatterGenericMultiSet.py b/lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic/multiset/TestDataFormatterGenericMultiSet.py index 7e922fccdf7d7..e846e072777f8 100644 --- a/lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic/multiset/TestDataFormatterGenericMultiSet.py +++ b/lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic/multiset/TestDataFormatterGenericMultiSet.py @@ -10,6 +10,8 @@ class GenericMultiSetDataFormatterTestCase(TestBase): + TEST_WITH_PDB_DEBUG_INFO = True + def setUp(self): TestBase.setUp(self) self.namespace = "std" diff --git a/lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic/optional/TestDataFormatterGenericOptional.py b/lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic/optional/TestDataFormatterGenericOptional.py index 7bb4f75de4e59..c88e83bb5b1f4 100644 --- a/lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic/optional/TestDataFormatterGenericOptional.py +++ b/lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic/optional/TestDataFormatterGenericOptional.py @@ -5,6 +5,8 @@ class GenericOptionalDataFormatterTestCase(TestBase): + TEST_WITH_PDB_DEBUG_INFO = True + def do_test_with_run_command(self): """Test that that file and class static variables display correctly.""" @@ -55,7 +57,11 @@ def cleanup(): self.expect( "frame var numbers", substrs=[ - "(optional_int_vect) numbers = Has Value=true {", + ( + "(std::optional<std::vector<int, std::allocator<int>>>) numbers = Has Value=true {" + if self.getDebugInfo() == "pdb" + else "(optional_int_vect) numbers = Has Value=true {" + ), "Value = size=4 {", "[0] = 1", "[1] = 2", @@ -69,7 +75,11 @@ def cleanup(): self.expect( "frame var ostring", substrs=[ - "(optional_string) ostring = Has Value=true {", + ( + "(std::optional<std::basic_string<char, std::char_traits<char>, std::allocator<char>>>) ostring = Has Value=true {" + if self.getDebugInfo() == "pdb" + else "(optional_string) ostring = Has Value=true {" + ), 'Value = "hello"', "}", ], diff --git a/lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic/set/TestDataFormatterGenericSet.py b/lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic/set/TestDataFormatterGenericSet.py index 1ac5e323e23e3..355f0c6edba19 100644 --- a/lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic/set/TestDataFormatterGenericSet.py +++ b/lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic/set/TestDataFormatterGenericSet.py @@ -10,6 +10,8 @@ class GenericSetDataFormatterTestCase(TestBase): + TEST_WITH_PDB_DEBUG_INFO = True + def setUp(self): TestBase.setUp(self) self.namespace = "std" diff --git a/lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic/shared_ptr/TestDataFormatterStdSharedPtr.py b/lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic/shared_ptr/TestDataFormatterStdSharedPtr.py index d71fbf8d5f81a..2574891a7df7e 100644 --- a/lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic/shared_ptr/TestDataFormatterStdSharedPtr.py +++ b/lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic/shared_ptr/TestDataFormatterStdSharedPtr.py @@ -9,6 +9,8 @@ class TestCase(TestBase): + TEST_WITH_PDB_DEBUG_INFO = True + def do_test(self): """Test `frame variable` output for `std::shared_ptr` types.""" (_, process, _, bkpt) = lldbutil.run_to_source_breakpoint( @@ -62,7 +64,7 @@ def do_test(self): valobj = self.expect_var_path("sp_user", type="std::shared_ptr<User>") self.assertRegex( valobj.summary, - "element_type @ 0x0*[1-9a-f][0-9a-f]+( strong=1)? weak=0", + f"{"User" if self.getDebugInfo() == "pdb" else "element_type"} @ 0x0*[1-9a-f][0-9a-f]+( strong=1)? weak=0", ) self.assertNotEqual(valobj.child[0].unsigned, 0) @@ -77,7 +79,15 @@ def do_test(self): self.assertEqual(str(valobj), '(User) *pointer = (id = 30, name = "steph")') self.expect_var_path("sp_user->id", type="int", value="30") - self.expect_var_path("sp_user->name", type="std::string", summary='"steph"') + self.expect_var_path( + "sp_user->name", + type=( + "std::basic_string<char, std::char_traits<char>, std::allocator<char>>" + if self.getDebugInfo() == "pdb" + else "std::string" + ), + summary='"steph"', + ) valobj = self.expect_var_path( "si", type="std::shared_ptr<int>", summary="47 strong=2 weak=0" diff --git a/lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic/string/TestDataFormatterStdString.py b/lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic/string/TestDataFormatterStdString.py index 6a27b5d2f0780..00047e419de37 100644 --- a/lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic/string/TestDataFormatterStdString.py +++ b/lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic/string/TestDataFormatterStdString.py @@ -11,6 +11,8 @@ class StdStringDataFormatterTestCase(TestBase): + TEST_WITH_PDB_DEBUG_INFO = True + def setUp(self): # Call super's setUp(). TestBase.setUp(self) @@ -18,6 +20,17 @@ def setUp(self): self.main_spec = lldb.SBFileSpec("main.cpp") self.namespace = "std" + def _makeStringName(self, typedef: str, char_type: str, allocator=None): + if allocator is None: + allocator = self.namespace + "::allocator" + + if self.getDebugInfo() == "pdb": + return f"{self.namespace}::basic_string<{char_type}, std::char_traits<{char_type}>, {allocator}<{char_type}>>" + + if typedef.startswith("::"): + return self.namespace + typedef + return typedef + def do_test(self): """Test that that file and class static variables display correctly.""" (target, process, thread, bkpt) = lldbutil.run_to_source_breakpoint( @@ -36,10 +49,17 @@ def cleanup(): # Execute the cleanup function during test case tear down. self.addTearDownHook(cleanup) - ns = self.namespace + string_name = self._makeStringName("::string", "char") + wstring_name = self._makeStringName("::wstring", "wchar_t") + custom_string_name = self._makeStringName( + "CustomString", "char", allocator="CustomAlloc" + ) + custom_wstring_name = self._makeStringName( + "CustomWString", "wchar_t", allocator="CustomAlloc" + ) # Check 'S' pre-assignment. - self.expect("frame variable S", substrs=['(%s::wstring) S = L"!!!!"' % ns]) + self.expect("frame variable S", substrs=[f'({wstring_name}) S = L"!!!!"']) thread.StepOver() @@ -54,34 +74,31 @@ def cleanup(): ) self.expect_expr( - "s", result_type=ns + "::wstring", result_summary='L"hello world! מזל טוב!"' + "s", result_type=wstring_name, result_summary='L"hello world! מזל טוב!"' ) - self.expect_expr( - "q", result_type=ns + "::string", result_summary='"hello world"' - ) + self.expect_expr("q", result_type=string_name, result_summary='"hello world"') self.expect_expr( "Q", - result_type=ns + "::string", + result_type=string_name, result_summary='"quite a long std::strin with lots of info inside it"', ) self.expect( "frame variable", substrs=[ - '(%s::wstring) wempty = L""' % ns, - '(%s::wstring) s = L"hello world! מזל טוב!"' % ns, - '(%s::wstring) S = L"!!!!!"' % ns, + f'({wstring_name}) wempty = L""', + f'({wstring_name}) s = L"hello world! מזל טוב!"', + f'({wstring_name}) S = L"!!!!!"', "(const wchar_t *) mazeltov = 0x", 'L"מזל טוב"', - '(%s::string) empty = ""' % ns, - '(%s::string) q = "hello world"' % ns, - '(%s::string) Q = "quite a long std::strin with lots of info inside it"' - % ns, - "(%s::string *) null_str = nullptr" % ns, - '(CustomString) custom_str = "hello!"', - '(CustomWString) custom_wstr = L"hello!"', + f'({string_name}) empty = ""', + f'({string_name}) q = "hello world"', + f'({string_name}) Q = "quite a long std::strin with lots of info inside it"', + f"({string_name} *) null_str = nullptr", + f'({custom_string_name}) custom_str = "hello!"', + f'({custom_wstring_name}) custom_wstr = L"hello!"', ], ) @@ -136,19 +153,26 @@ def do_test_multibyte(self): self, "Set break point at this line.", self.main_spec ) - ns = self.namespace + u16string_name = self._makeStringName("::u16string", "char16_t") + u32string_name = self._makeStringName("::u32string", "char32_t") + custom_u16string_name = self._makeStringName( + "CustomStringU16", "char16_t", allocator="CustomAlloc" + ) + custom_u32string_name = self._makeStringName( + "CustomStringU32", "char32_t", allocator="CustomAlloc" + ) self.expect( "frame variable", substrs=[ - '(%s::u16string) u16_string = u"ß水氶"' % ns, - '(%s::u16string) u16_empty = u""' % ns, - '(%s::u32string) u32_string = U"🍄🍅🍆🍌"' % ns, - '(%s::u32string) u32_empty = U""' % ns, - '(CustomStringU16) custom_u16 = u"ß水氶"', - '(CustomStringU16) custom_u16_empty = u""', - '(CustomStringU32) custom_u32 = U"🍄🍅🍆🍌"', - '(CustomStringU32) custom_u32_empty = U""', + f'({u16string_name}) u16_string = u"ß水氶"', + f'({u16string_name}) u16_empty = u""', + f'({u32string_name}) u32_string = U"🍄🍅🍆🍌"', + f'({u32string_name}) u32_empty = U""', + f'({custom_u16string_name}) custom_u16 = u"ß水氶"', + f'({custom_u16string_name}) custom_u16_empty = u""', + f'({custom_u32string_name}) custom_u32 = U"🍄🍅🍆🍌"', + f'({custom_u32string_name}) custom_u32_empty = U""', ], ) @@ -271,9 +295,8 @@ def do_test_embedded_null(self): self.expect( "frame variable", substrs=[ - '(%s::string) IHaveEmbeddedZeros = "a\\0b\\0c\\0d"' % ns, - '(%s::wstring) IHaveEmbeddedZerosToo = L"hello world!\\0てざ ル゜䋨ミ㠧槊 きゅへ狦穤襩 じゃ馩リョ 䤦監"' - % ns, + f'({self._makeStringName("::string", "char")}) IHaveEmbeddedZeros = "a\\0b\\0c\\0d"', + f'({self._makeStringName("::wstring", "wchar_t")}) IHaveEmbeddedZerosToo = L"hello world!\\0てざ ル゜䋨ミ㠧槊 きゅへ狦穤襩 じゃ馩リョ 䤦監"', ], ) diff --git a/lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic/string_view/TestDataFormatterStdStringView.py b/lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic/string_view/TestDataFormatterStdStringView.py index 181141886c5a2..884e689c21655 100644 --- a/lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic/string_view/TestDataFormatterStdStringView.py +++ b/lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic/string_view/TestDataFormatterStdStringView.py @@ -11,6 +11,8 @@ class StdStringViewDataFormatterTestCase(TestBase): + TEST_WITH_PDB_DEBUG_INFO = True + def setUp(self): # Call super's setUp(). TestBase.setUp(self) @@ -20,6 +22,12 @@ def setUp(self): "main.cpp", "// Break here to look at bad string view." ) + def _makeStringName(self, typedef: str, char_type: str): + if self.getDebugInfo() == "pdb": + return f"std::basic_string_view<{char_type}, std::char_traits<{char_type}>>" + + return typedef + def do_test(self): """Test that that file and class static variables display correctly.""" self.runCmd("file " + self.getBuildArtifact("a.out"), CURRENT_EXECUTABLE_SET) @@ -51,39 +59,49 @@ def cleanup(): # Execute the cleanup function during test case tear down. self.addTearDownHook(cleanup) - self.expect_var_path("wempty", type="std::wstring_view", summary='L""') + string_view_name = self._makeStringName("std::string_view", "char") + wstring_view_name = self._makeStringName("std::wstring_view", "wchar_t") + u16string_view_name = self._makeStringName("std::u16string_view", "char16_t") + u32string_view_name = self._makeStringName("std::u32string_view", "char32_t") + string_name = ( + "std::basic_string<char, std::char_traits<char>, std::allocator<char>>" + if self.getDebugInfo() == "pdb" + else "std::string" + ) + + self.expect_var_path("wempty", type=wstring_view_name, summary='L""') self.expect_var_path( - "s", type="std::wstring_view", summary='L"hello world! מזל טוב!"' + "s", type=wstring_view_name, summary='L"hello world! מזל טוב!"' ) - self.expect_var_path("S", type="std::wstring_view", summary='L"!!!!"') - self.expect_var_path("empty", type="std::string_view", summary='""') - self.expect_var_path("q_source", type="std::string", summary='"hello world"') - self.expect_var_path("q", type="std::string_view", summary='"hello world"') + self.expect_var_path("S", type=wstring_view_name, summary='L"!!!!"') + self.expect_var_path("empty", type=string_view_name, summary='""') + self.expect_var_path("q_source", type=string_name, summary='"hello world"') + self.expect_var_path("q", type=string_view_name, summary='"hello world"') self.expect_var_path( "Q", - type="std::string_view", + type=string_view_name, summary='"quite a long std::strin with lots of info inside it"', ) self.expect_var_path( - "IHaveEmbeddedZeros", type="std::string_view", summary='"a\\0b\\0c\\0d"' + "IHaveEmbeddedZeros", type=string_view_name, summary='"a\\0b\\0c\\0d"' ) self.expect_var_path( "IHaveEmbeddedZerosToo", - type="std::wstring_view", + type=wstring_view_name, summary='L"hello world!\\0てざ ル゜䋨ミ㠧槊 きゅへ狦穤襩 じゃ馩リョ 䤦監"', ) - self.expect_var_path("u16_string", type="std::u16string_view", summary='u"ß水氶"') - self.expect_var_path("u16_empty", type="std::u16string_view", summary='u""') + self.expect_var_path("u16_string", type=u16string_view_name, summary='u"ß水氶"') + self.expect_var_path("u16_empty", type=u16string_view_name, summary='u""') self.expect_var_path( - "u32_string", type="std::u32string_view", summary='U"🍄🍅🍆🍌"' + "u32_string", type=u32string_view_name, summary='U"🍄🍅🍆🍌"' ) - self.expect_var_path("u32_empty", type="std::u32string_view", summary='U""') + self.expect_var_path("u32_empty", type=u32string_view_name, summary='U""') # GetSummary returns None so can't be checked by expect_var_path, so we # use the str representation instead null_obj = self.frame().GetValueForVariablePath("null_str") self.assertEqual(null_obj.GetSummary(), "Summary Unavailable") - self.assertEqual(str(null_obj), "(std::string_view *) null_str = nullptr") + self.assertEqual(str(null_obj), f"({string_view_name} *) null_str = nullptr") self.runCmd("n") @@ -108,37 +126,37 @@ def cleanup(): self.expect_expr( "s", - result_type="std::wstring_view", + result_type=wstring_view_name, result_summary='L"hello world! מזל טוב!"', ) - self.expect_var_path("wempty", type="std::wstring_view", summary='L""') + self.expect_var_path("wempty", type=wstring_view_name, summary='L""') self.expect_var_path( - "s", type="std::wstring_view", summary='L"hello world! מזל טוב!"' + "s", type=wstring_view_name, summary='L"hello world! מזל טוב!"' ) - self.expect_var_path("S", type="std::wstring_view", summary='L"!!!!"') - self.expect_var_path("empty", type="std::string_view", summary='""') - self.expect_var_path("q_source", type="std::string", summary='"Hello world"') - self.expect_var_path("q", type="std::string_view", summary='"Hello world"') + self.expect_var_path("S", type=wstring_view_name, summary='L"!!!!"') + self.expect_var_path("empty", type=string_view_name, summary='""') + self.expect_var_path("q_source", type=string_name, summary='"Hello world"') + self.expect_var_path("q", type=string_view_name, summary='"Hello world"') self.expect_var_path( "Q", - type="std::string_view", + type=string_view_name, summary='"quite a long std::strin with lots of info inside it"', ) self.expect_var_path( - "IHaveEmbeddedZeros", type="std::string_view", summary='"a\\0b\\0c\\0d"' + "IHaveEmbeddedZeros", type=string_view_name, summary='"a\\0b\\0c\\0d"' ) self.expect_var_path( "IHaveEmbeddedZerosToo", - type="std::wstring_view", + type=wstring_view_name, summary='L"hello world!\\0てざ ル゜䋨ミ㠧槊 きゅへ狦穤襩 じゃ馩リョ 䤦監"', ) - self.expect_var_path("u16_string", type="std::u16string_view", summary='u"ß水氶"') - self.expect_var_path("u16_empty", type="std::u16string_view", summary='u""') + self.expect_var_path("u16_string", type=u16string_view_name, summary='u"ß水氶"') + self.expect_var_path("u16_empty", type=u16string_view_name, summary='u""') self.expect_var_path( - "u32_string", type="std::u32string_view", summary='U"🍄🍅🍆🍌"' + "u32_string", type=u32string_view_name, summary='U"🍄🍅🍆🍌"' ) - self.expect_var_path("u32_empty", type="std::u32string_view", summary='U""') + self.expect_var_path("u32_empty", type=u32string_view_name, summary='U""') self.runCmd("cont") self.expect( diff --git a/lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic/tuple/TestDataFormatterStdTuple.py b/lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic/tuple/TestDataFormatterStdTuple.py index b23d549fe4c18..898438729ff8f 100644 --- a/lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic/tuple/TestDataFormatterStdTuple.py +++ b/lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic/tuple/TestDataFormatterStdTuple.py @@ -9,6 +9,8 @@ class TestDataFormatterStdTuple(TestBase): + TEST_WITH_PDB_DEBUG_INFO = True + def setUp(self): TestBase.setUp(self) self.line = line_number("main.cpp", "// break here") diff --git a/lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic/u8string/TestDataFormatterStdU8String.py b/lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic/u8string/TestDataFormatterStdU8String.py index b983ee175d389..dda97945f9b23 100644 --- a/lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic/u8string/TestDataFormatterStdU8String.py +++ b/lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic/u8string/TestDataFormatterStdU8String.py @@ -11,18 +11,26 @@ class StdU8StringDataFormatterTestCase(TestBase): + TEST_WITH_PDB_DEBUG_INFO = True + def do_test(self): lldbutil.run_to_source_breakpoint( self, "Set break point at this line.", lldb.SBFileSpec("main.cpp") ) + string_name = ( + "std::basic_string<char8_t, std::char_traits<char8_t>, std::allocator<char8_t>>" + if self.getDebugInfo() == "pdb" + else "std::u8string" + ) + self.expect( "frame variable", substrs=[ - '(std::u8string) u8_string_small = u8"🍄"', - '(std::u8string) u8_string = u8"❤️👍📄📁😃🧑🌾"', - '(std::u8string) u8_empty = u8""', - '(std::u8string) u8_text = u8"ABCd"', + f'({string_name}) u8_string_small = u8"🍄"', + f'({string_name}) u8_string = u8"❤️👍📄📁😃🧑🌾"', + f'({string_name}) u8_empty = u8""', + f'({string_name}) u8_text = u8"ABCd"', ], ) diff --git a/lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic/u8string_view/TestDataFormatterStdU8StringView.py b/lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic/u8string_view/TestDataFormatterStdU8StringView.py index 1e35a0f6bb040..6cf72d18a864f 100644 --- a/lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic/u8string_view/TestDataFormatterStdU8StringView.py +++ b/lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic/u8string_view/TestDataFormatterStdU8StringView.py @@ -11,18 +11,26 @@ class StdU8StringViewDataFormatterTestCase(TestBase): + TEST_WITH_PDB_DEBUG_INFO = True + def do_test(self): lldbutil.run_to_source_breakpoint( self, "Set break point at this line.", lldb.SBFileSpec("main.cpp") ) + string_view_name = ( + "std::basic_string_view<char8_t, std::char_traits<char8_t>>" + if self.getDebugInfo() == "pdb" + else "std::u8string_view" + ) + self.expect( "frame variable", substrs=[ - '(std::u8string_view) u8_string_small = u8"🍄"', - '(std::u8string_view) u8_string = u8"❤️👍📄📁😃🧑🌾"', - '(std::u8string_view) u8_empty = u8""', - '(std::u8string_view) u8_text = u8"ABCd"', + f'({string_view_name}) u8_string_small = u8"🍄"', + f'({string_view_name}) u8_string = u8"❤️👍📄📁😃🧑🌾"', + f'({string_view_name}) u8_empty = u8""', + f'({string_view_name}) u8_text = u8"ABCd"', ], ) diff --git a/lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic/unique_ptr/TestDataFormatterStdUniquePtr.py b/lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic/unique_ptr/TestDataFormatterStdUniquePtr.py index 0b68b1b532bb0..1516db698798d 100644 --- a/lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic/unique_ptr/TestDataFormatterStdUniquePtr.py +++ b/lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic/unique_ptr/TestDataFormatterStdUniquePtr.py @@ -9,6 +9,8 @@ class TestCase(TestBase): + TEST_WITH_PDB_DEBUG_INFO = True + def do_test(self): """Test `frame variable` output for `std::unique_ptr` types.""" @@ -84,7 +86,15 @@ def do_test(self): self.assertNotEqual(valobj.child[0].unsigned, 0) self.expect_var_path("up_user->id", type="int", value="30") - self.expect_var_path("up_user->name", type="std::string", summary='"steph"') + self.expect_var_path( + "up_user->name", + type=( + "std::basic_string<char, std::char_traits<char>, std::allocator<char>>" + if self.getDebugInfo() == "pdb" + else "std::string" + ), + summary='"steph"', + ) self.runCmd("settings set target.experimental.use-DIL true") self.expect_var_path("ptr_node->value", value="1") 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 dd740bd43b063..239ffa2f6149b 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 @@ -4,6 +4,8 @@ class GenericUnorderedDataFormatterTestCase(TestBase): + TEST_WITH_PDB_DEBUG_INFO = True + def setUp(self): TestBase.setUp(self) self.namespace = "std" @@ -49,7 +51,11 @@ def cleanup(): self.look_for_content_and_continue( "map", [ - "UnorderedMap", + ( + "std::unordered_map<int, std::basic_string<char, std::char_traits<char>, std::allocator<char>>, std::hash" # ... + if self.getDebugInfo() == "pdb" + else "UnorderedMap" + ), children_are_key_value, "size=5 {", "hello", @@ -63,7 +69,11 @@ def cleanup(): self.look_for_content_and_continue( "mmap", [ - "UnorderedMultiMap", + ( + "std::unordered_multimap<int, std::basic_string<char, std::char_traits<char>, std::allocator<char>>, std::hash" # ... + if self.getDebugInfo() == "pdb" + else "UnorderedMultiMap" + ), children_are_key_value, "size=6 {", "first = 3", @@ -76,7 +86,11 @@ def cleanup(): self.look_for_content_and_continue( "iset", [ - "IntsUnorderedSet", + ( + "std::unordered_set<int, std::hash<int>, std::equal_to<int>, std::allocator<int>>" + if self.getDebugInfo() == "pdb" + else "IntsUnorderedSet" + ), "size=5 {", r"\[\d\] = 5", r"\[\d\] = 3", @@ -87,7 +101,11 @@ def cleanup(): self.look_for_content_and_continue( "sset", [ - "StringsUnorderedSet", + ( + "std::unordered_set<std::basic_string<char, std::char_traits<char>, std::allocator<char>>, std::hash" # ... + if self.getDebugInfo() == "pdb" + else "StringsUnorderedSet" + ), "size=5 {", r'\[\d\] = "is"', r'\[\d\] = "world"', @@ -98,7 +116,11 @@ def cleanup(): self.look_for_content_and_continue( "imset", [ - "IntsUnorderedMultiSet", + ( + "std::unordered_multiset<int, std::hash<int>, std::equal_to<int>, std::allocator<int>>" + if self.getDebugInfo() == "pdb" + else "IntsUnorderedMultiSet" + ), "size=6 {", "(\\[\\d\\] = 3(\\n|.)+){3}", r"\[\d\] = 2", @@ -109,7 +131,11 @@ def cleanup(): self.look_for_content_and_continue( "smset", [ - "StringsUnorderedMultiSet", + ( + "std::unordered_multiset<std::basic_string<char, std::char_traits<char>, std::allocator<char>>, std::hash" # ... + if self.getDebugInfo() == "pdb" + else "StringsUnorderedMultiSet" + ), "size=5 {", '(\\[\\d\\] = "is"(\\n|.)+){2}', '(\\[\\d\\] = "world"(\\n|.)+){2}', diff --git a/lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic/variant/TestDataFormatterStdVariant.py b/lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic/variant/TestDataFormatterStdVariant.py index 9f32ad97c1f0a..1ae07a91dfe3d 100644 --- a/lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic/variant/TestDataFormatterStdVariant.py +++ b/lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic/variant/TestDataFormatterStdVariant.py @@ -9,6 +9,8 @@ class StdVariantDataFormatterTestCase(TestBase): + TEST_WITH_PDB_DEBUG_INFO = True + def do_test(self): """Test that that file and class static variables display correctly.""" diff --git a/lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic/vbool/TestDataFormatterStdVBool.py b/lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic/vbool/TestDataFormatterStdVBool.py index dd142d2be193b..f74092ca3a0b8 100644 --- a/lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic/vbool/TestDataFormatterStdVBool.py +++ b/lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic/vbool/TestDataFormatterStdVBool.py @@ -9,6 +9,8 @@ class StdVBoolDataFormatterTestCase(TestBase): + TEST_WITH_PDB_DEBUG_INFO = True + def setUp(self): # Call super's setUp(). TestBase.setUp(self) diff --git a/lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic/vector/TestDataFormatterStdVector.py b/lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic/vector/TestDataFormatterStdVector.py index d4da60f86a315..ab2e8a7ceb37d 100644 --- a/lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic/vector/TestDataFormatterStdVector.py +++ b/lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic/vector/TestDataFormatterStdVector.py @@ -9,6 +9,8 @@ class StdVectorDataFormatterTestCase(TestBase): + TEST_WITH_PDB_DEBUG_INFO = True + def check_numbers(self, var_name, show_ptr=False): patterns = [] substrs = [ @@ -106,19 +108,25 @@ def cleanup(): ], ) + int_vect = ( + "std::vector<int, std::allocator<int>>" + if self.getDebugInfo() == "pdb" + else "int_vect" + ) + # check access to synthetic children self.runCmd( - 'type summary add --summary-string "item 0 is ${var[0]}" std::int_vect int_vect' + f'type summary add --summary-string "item 0 is ${{var[0]}}" std::int_vect "{int_vect}"' ) self.expect("frame variable numbers", substrs=["item 0 is 1"]) self.runCmd( - 'type summary add --summary-string "item 0 is ${svar[0]}" std::int_vect int_vect' + f'type summary add --summary-string "item 0 is ${{svar[0]}}" std::int_vect "{int_vect}"' ) self.expect("frame variable numbers", substrs=["item 0 is 1"]) # move on with synths self.runCmd("type summary delete std::int_vect") - self.runCmd("type summary delete int_vect") + self.runCmd(f'type summary delete "{int_vect}"') # add some more data lldbutil.continue_to_breakpoint(process, bkpt) @@ -142,9 +150,15 @@ def cleanup(): self.expect("expression strings", substrs=["goofy", "is", "smart"]) + string_vect = ( + "std::vector<std::basic_string<char, std::char_traits<char>, std::allocator<char>>, std::allocator<std::basic_string<char, std::char_traits<char>, std::allocator<char>>>>" + if self.getDebugInfo() == "pdb" + else "string_vect" + ) + # test summaries based on synthetic children self.runCmd( - 'type summary add std::string_vect string_vect --summary-string "vector has ${svar%#} items" -e' + f'type summary add std::string_vect "{string_vect}" --summary-string "vector has ${{svar%#}} items" -e' ) self.expect( "frame variable strings", diff --git a/lldb/test/Shell/SymbolFile/NativePDB/stl_types.test b/lldb/test/Shell/SymbolFile/NativePDB/stl_types.test deleted file mode 100644 index 45960a80211e0..0000000000000 --- a/lldb/test/Shell/SymbolFile/NativePDB/stl_types.test +++ /dev/null @@ -1,188 +0,0 @@ -# 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 deleted file mode 100644 index 0472bf5f27f06..0000000000000 --- a/lldb/test/Shell/SymbolFile/PDB/stl_types.test +++ /dev/null @@ -1,197 +0,0 @@ -# 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 [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
