https://github.com/Michael137 updated https://github.com/llvm/llvm-project/pull/96538
>From 3b4d9629a68c9e75dfd139ee2745bf00db979ecd Mon Sep 17 00:00:00 2001 From: Michael Buch <michaelbuc...@gmail.com> Date: Mon, 29 Jan 2024 16:23:16 +0000 Subject: [PATCH 1/2] [lldb] Support new libc++ __compressed_pair layout This patch is in preparation for the `__compressed_pair` refactor in https://github.com/llvm/llvm-project/pull/76756. This gets the formatter tests to at least pass. Currently in draft because there's still some cleanup to be done. --- lldb/examples/synthetic/libcxx.py | 26 ++++-- .../Plugins/Language/CPlusPlus/LibCxx.cpp | 61 ++++++++++---- .../Plugins/Language/CPlusPlus/LibCxxList.cpp | 83 ++++++++++++------- .../Plugins/Language/CPlusPlus/LibCxxMap.cpp | 68 +++++++++++---- .../Language/CPlusPlus/LibCxxUnorderedMap.cpp | 73 +++++++++++----- .../Language/CPlusPlus/LibCxxVector.cpp | 40 +++++---- .../list/TestDataFormatterGenericList.py | 3 +- .../libcxx/string/simulator/main.cpp | 1 + .../TestDataFormatterLibcxxUniquePtr.py | 7 +- 9 files changed, 256 insertions(+), 106 deletions(-) diff --git a/lldb/examples/synthetic/libcxx.py b/lldb/examples/synthetic/libcxx.py index 474aaa428fa23..060ff90100849 100644 --- a/lldb/examples/synthetic/libcxx.py +++ b/lldb/examples/synthetic/libcxx.py @@ -721,6 +721,12 @@ def _get_value_of_compressed_pair(self, pair): def update(self): logger = lldb.formatters.Logger.Logger() try: + has_compressed_pair_layout = True + alloc_valobj = self.valobj.GetChildMemberWithName("__alloc_") + size_valobj = self.valobj.GetChildMemberWithName("__size_") + if alloc_valobj.IsValid() and size_valobj.IsValid(): + has_compressed_pair_layout = False + # A deque is effectively a two-dim array, with fixed width. # 'map' contains pointers to the rows of this array. The # full memory area allocated by the deque is delimited @@ -734,9 +740,13 @@ def update(self): # variable tells which element in this NxM array is the 0th # one, and the 'size' element gives the number of elements # in the deque. - count = self._get_value_of_compressed_pair( - self.valobj.GetChildMemberWithName("__size_") - ) + if has_compressed_pair_layout: + count = self._get_value_of_compressed_pair( + self.valobj.GetChildMemberWithName("__size_") + ) + else: + count = size_valobj.GetValueAsUnsigned(0) + # give up now if we cant access memory reliably if self.block_size < 0: logger.write("block_size < 0") @@ -748,9 +758,13 @@ def update(self): self.map_begin = map_.GetChildMemberWithName("__begin_") map_begin = self.map_begin.GetValueAsUnsigned(0) map_end = map_.GetChildMemberWithName("__end_").GetValueAsUnsigned(0) - map_endcap = self._get_value_of_compressed_pair( - map_.GetChildMemberWithName("__end_cap_") - ) + + if has_compressed_pair_layout: + map_endcap = self._get_value_of_compressed_pair( + map_.GetChildMemberWithName("__end_cap_") + ) + else: + map_endcap = map_.GetChildMemberWithName("__end_cap_").GetValueAsUnsigned(0) # check consistency if not map_first <= map_begin <= map_end <= map_endcap: diff --git a/lldb/source/Plugins/Language/CPlusPlus/LibCxx.cpp b/lldb/source/Plugins/Language/CPlusPlus/LibCxx.cpp index b0e6fb7d6f5af..928b790317b6e 100644 --- a/lldb/source/Plugins/Language/CPlusPlus/LibCxx.cpp +++ b/lldb/source/Plugins/Language/CPlusPlus/LibCxx.cpp @@ -27,6 +27,7 @@ #include "Plugins/LanguageRuntime/CPlusPlus/CPPLanguageRuntime.h" #include "Plugins/TypeSystem/Clang/TypeSystemClang.h" #include "lldb/lldb-enumerations.h" +#include "lldb/lldb-forward.h" #include <optional> #include <tuple> @@ -176,9 +177,9 @@ bool lldb_private::formatters::LibcxxUniquePointerSummaryProvider( if (!ptr_sp) return false; - ptr_sp = GetFirstValueOfLibCXXCompressedPair(*ptr_sp); - if (!ptr_sp) - return false; + if (ValueObjectSP compressed_pair_value__sp = + GetFirstValueOfLibCXXCompressedPair(*ptr_sp)) + ptr_sp = std::move(compressed_pair_value__sp); if (ptr_sp->GetValueAsUnsigned(0) == 0) { stream.Printf("nullptr"); @@ -701,15 +702,28 @@ lldb_private::formatters::LibcxxUniquePtrSyntheticFrontEnd::Update() { if (!ptr_sp) return lldb::ChildCacheState::eRefetch; + bool has_compressed_pair_layout = true; + ValueObjectSP deleter_sp(valobj_sp->GetChildMemberWithName("__deleter_")); + if (deleter_sp) + has_compressed_pair_layout = false; + // Retrieve the actual pointer and the deleter, and clone them to give them // user-friendly names. - ValueObjectSP value_pointer_sp = GetFirstValueOfLibCXXCompressedPair(*ptr_sp); - if (value_pointer_sp) - m_value_ptr_sp = value_pointer_sp->Clone(ConstString("pointer")); - - ValueObjectSP deleter_sp = GetSecondValueOfLibCXXCompressedPair(*ptr_sp); - if (deleter_sp) + if (has_compressed_pair_layout) { + ValueObjectSP value_pointer_sp = + GetFirstValueOfLibCXXCompressedPair(*ptr_sp); + if (value_pointer_sp) + m_value_ptr_sp = value_pointer_sp->Clone(ConstString("pointer")); + + ValueObjectSP deleter_sp = GetSecondValueOfLibCXXCompressedPair(*ptr_sp); + if (deleter_sp) + m_deleter_sp = deleter_sp->Clone(ConstString("deleter")); + } else { + // TODO: with the new layout, deleter is always a member, so empty deleters + // will be displayed + m_value_ptr_sp = ptr_sp->Clone(ConstString("pointer")); m_deleter_sp = deleter_sp->Clone(ConstString("deleter")); + } return lldb::ChildCacheState::eRefetch; } @@ -747,11 +761,7 @@ namespace { enum class StringLayout { CSD, DSC }; } -/// Determine the size in bytes of \p valobj (a libc++ std::string object) and -/// extract its data payload. Return the size + payload pair. -// TODO: Support big-endian architectures. -static std::optional<std::pair<uint64_t, ValueObjectSP>> -ExtractLibcxxStringInfo(ValueObject &valobj) { +static ValueObjectSP ExtractLibCxxStringDataV1(ValueObject &valobj) { ValueObjectSP valobj_r_sp = valobj.GetChildMemberWithName("__r_"); if (!valobj_r_sp || !valobj_r_sp->GetError().Success()) return {}; @@ -767,6 +777,29 @@ ExtractLibcxxStringInfo(ValueObject &valobj) { if (!valobj_rep_sp) return {}; + return valobj_rep_sp; +} + +static ValueObjectSP ExtractLibCxxStringDataV2(ValueObject &valobj) { + return valobj.GetChildMemberWithName("__rep_"); +} + +static ValueObjectSP ExtractLibCxxStringData(ValueObject &valobj) { + if (ValueObjectSP ret = ExtractLibCxxStringDataV1(valobj)) + return ret; + + return ExtractLibCxxStringDataV2(valobj); +} + +/// Determine the size in bytes of \p valobj (a libc++ std::string object) and +/// extract its data payload. Return the size + payload pair. +// TODO: Support big-endian architectures. +static std::optional<std::pair<uint64_t, ValueObjectSP>> +ExtractLibcxxStringInfo(ValueObject &valobj) { + ValueObjectSP valobj_rep_sp = ExtractLibCxxStringData(valobj); + if (!valobj_rep_sp || !valobj_rep_sp->GetError().Success()) + return {}; + ValueObjectSP l = valobj_rep_sp->GetChildMemberWithName("__l"); if (!l) return {}; diff --git a/lldb/source/Plugins/Language/CPlusPlus/LibCxxList.cpp b/lldb/source/Plugins/Language/CPlusPlus/LibCxxList.cpp index d7cfeb30557c3..0013ccb1bab60 100644 --- a/lldb/source/Plugins/Language/CPlusPlus/LibCxxList.cpp +++ b/lldb/source/Plugins/Language/CPlusPlus/LibCxxList.cpp @@ -17,6 +17,7 @@ #include "lldb/Utility/Endian.h" #include "lldb/Utility/Status.h" #include "lldb/Utility/Stream.h" +#include "lldb/lldb-enumerations.h" using namespace lldb; using namespace lldb_private; @@ -294,12 +295,19 @@ lldb::ChildCacheState ForwardListFrontEnd::Update() { ValueObjectSP impl_sp(m_backend.GetChildMemberWithName("__before_begin_")); if (!impl_sp) - return lldb::ChildCacheState::eRefetch; - impl_sp = GetFirstValueOfLibCXXCompressedPair(*impl_sp); - if (!impl_sp) - return lldb::ChildCacheState::eRefetch; + return ChildCacheState::eRefetch; + m_head = impl_sp->GetChildMemberWithName("__next_").get(); - return lldb::ChildCacheState::eRefetch; + + // TODO: we have to do this in this order because __before_begin_ has a + // __value_ member, as does compressed_pair. Is this a problem elsewhere too? + if (!m_head) { + impl_sp = GetFirstValueOfLibCXXCompressedPair(*impl_sp); + if (impl_sp) + m_head = impl_sp->GetChildMemberWithName("__next_").get(); + } + + return ChildCacheState::eRefetch; } ListFrontEnd::ListFrontEnd(lldb::ValueObjectSP valobj_sp) @@ -313,34 +321,49 @@ llvm::Expected<uint32_t> ListFrontEnd::CalculateNumChildren() { return m_count; if (!m_head || !m_tail || m_node_address == 0) return 0; - ValueObjectSP size_alloc(m_backend.GetChildMemberWithName("__size_alloc_")); - if (size_alloc) { - ValueObjectSP value = GetFirstValueOfLibCXXCompressedPair(*size_alloc); - if (value) { - m_count = value->GetValueAsUnsigned(UINT32_MAX); - } + + bool has_compressed_pair_layout = false; + // ValueObjectSP + // node_alloc(m_backend.GetChildMemberWithName("__node_alloc_")); if + // (!node_alloc) + // has_compressed_pair_layout = true; + + ValueObjectSP size_node(m_backend.GetChildMemberWithName("__size_")); + if (!size_node) { + size_node = m_backend.GetChildMemberWithName( + "__size_alloc_"); // pre-compressed_pair rework + if (size_node) + has_compressed_pair_layout = true; } - if (m_count != UINT32_MAX) { + + if (size_node) { + if (has_compressed_pair_layout) + if (ValueObjectSP value = GetFirstValueOfLibCXXCompressedPair(*size_node)) + size_node = std::move(value); + + m_count = size_node->GetValueAsUnsigned(UINT32_MAX); + } + + if (m_count != UINT32_MAX) return m_count; - } else { - uint64_t next_val = m_head->GetValueAsUnsigned(0); - uint64_t prev_val = m_tail->GetValueAsUnsigned(0); - if (next_val == 0 || prev_val == 0) - return 0; - if (next_val == m_node_address) - return 0; - if (next_val == prev_val) - return 1; - uint64_t size = 2; - ListEntry current(m_head); - while (current.next() && current.next().value() != m_node_address) { - size++; - current = current.next(); - if (size > m_list_capping_size) - break; - } - return m_count = (size - 1); + + uint64_t next_val = m_head->GetValueAsUnsigned(0); + uint64_t prev_val = m_tail->GetValueAsUnsigned(0); + if (next_val == 0 || prev_val == 0) + return 0; + if (next_val == m_node_address) + return 0; + if (next_val == prev_val) + return 1; + uint64_t size = 2; + ListEntry current(m_head); + while (current.next() && current.next().value() != m_node_address) { + size++; + current = current.next(); + if (size > m_list_capping_size) + break; } + return m_count = (size - 1); } lldb::ValueObjectSP ListFrontEnd::GetChildAtIndex(uint32_t idx) { diff --git a/lldb/source/Plugins/Language/CPlusPlus/LibCxxMap.cpp b/lldb/source/Plugins/Language/CPlusPlus/LibCxxMap.cpp index 0929d49e55eac..1f08225fe00f2 100644 --- a/lldb/source/Plugins/Language/CPlusPlus/LibCxxMap.cpp +++ b/lldb/source/Plugins/Language/CPlusPlus/LibCxxMap.cpp @@ -188,6 +188,9 @@ class LibcxxStdMapSyntheticFrontEnd : public SyntheticChildrenFrontEnd { size_t GetIndexOfChildWithName(ConstString name) override; private: + size_t CalculateNumChildrenV1(); + size_t CalculateNumChildrenV2(); + bool GetDataType(); void GetValueOffset(const lldb::ValueObjectSP &node); @@ -198,6 +201,7 @@ class LibcxxStdMapSyntheticFrontEnd : public SyntheticChildrenFrontEnd { uint32_t m_skip_size = UINT32_MAX; size_t m_count = UINT32_MAX; std::map<size_t, MapIterator> m_iterators; + bool m_has_compressed_pair_layout = false; }; } // namespace formatters } // namespace lldb_private @@ -209,6 +213,31 @@ lldb_private::formatters::LibcxxStdMapSyntheticFrontEnd:: Update(); } +size_t lldb_private::formatters::LibcxxStdMapSyntheticFrontEnd:: + CalculateNumChildrenV2() { + ValueObjectSP node(m_tree->GetChildMemberWithName("__size_")); + if (!node) + return 0; + + m_count = node->GetValueAsUnsigned(0); + return m_count; +} + +size_t lldb_private::formatters::LibcxxStdMapSyntheticFrontEnd:: + CalculateNumChildrenV1() { + ValueObjectSP node(m_tree->GetChildMemberWithName("__pair3_")); + if (!node) + return 0; + + node = formatters::GetFirstValueOfLibCXXCompressedPair(*node); + + if (!node) + return 0; + + m_count = node->GetValueAsUnsigned(0); + return m_count; +} + llvm::Expected<uint32_t> lldb_private::formatters:: LibcxxStdMapSyntheticFrontEnd::CalculateNumChildren() { if (m_count != UINT32_MAX) @@ -217,17 +246,10 @@ llvm::Expected<uint32_t> lldb_private::formatters:: if (m_tree == nullptr) return 0; - ValueObjectSP size_node(m_tree->GetChildMemberWithName("__pair3_")); - if (!size_node) - return 0; + if (m_has_compressed_pair_layout) + return CalculateNumChildrenV1(); - size_node = GetFirstValueOfLibCXXCompressedPair(*size_node); - - if (!size_node) - return 0; - - m_count = size_node->GetValueAsUnsigned(0); - return m_count; + return CalculateNumChildrenV2(); } bool lldb_private::formatters::LibcxxStdMapSyntheticFrontEnd::GetDataType() { @@ -244,12 +266,22 @@ bool lldb_private::formatters::LibcxxStdMapSyntheticFrontEnd::GetDataType() { m_element_type = deref->GetCompilerType(); return true; } - deref = m_backend.GetChildAtNamePath({"__tree_", "__pair3_"}); - if (!deref) - return false; - m_element_type = deref->GetCompilerType() - .GetTypeTemplateArgument(1) - .GetTypeTemplateArgument(1); + + if (m_has_compressed_pair_layout) { + deref = m_backend.GetChildAtNamePath({"__tree_", "__pair3_"}); + + if (!deref) + return false; + m_element_type = deref->GetCompilerType() + .GetTypeTemplateArgument(1) + .GetTypeTemplateArgument(1); + } else { + deref = m_backend.GetChildAtNamePath({"__tree_", "__value_comp_"}); + if (!deref) + return false; + m_element_type = deref->GetCompilerType().GetTypeTemplateArgument(1); + } + if (m_element_type) { std::string name; uint64_t bit_offset_ptr; @@ -413,6 +445,10 @@ lldb_private::formatters::LibcxxStdMapSyntheticFrontEnd::Update() { m_tree = m_backend.GetChildMemberWithName("__tree_").get(); if (!m_tree) return lldb::ChildCacheState::eRefetch; + + m_has_compressed_pair_layout = + m_tree->GetChildMemberWithName("__pair1_") != nullptr; + m_root_node = m_tree->GetChildMemberWithName("__begin_node_").get(); return lldb::ChildCacheState::eRefetch; } diff --git a/lldb/source/Plugins/Language/CPlusPlus/LibCxxUnorderedMap.cpp b/lldb/source/Plugins/Language/CPlusPlus/LibCxxUnorderedMap.cpp index af29fdb6d0010..a249d68ce1b87 100644 --- a/lldb/source/Plugins/Language/CPlusPlus/LibCxxUnorderedMap.cpp +++ b/lldb/source/Plugins/Language/CPlusPlus/LibCxxUnorderedMap.cpp @@ -18,6 +18,7 @@ #include "lldb/Utility/Endian.h" #include "lldb/Utility/Status.h" #include "lldb/Utility/Stream.h" +#include "clang/ASTMatchers/ASTMatchers.h" #include "llvm/ADT/StringRef.h" using namespace lldb; @@ -112,19 +113,38 @@ lldb::ValueObjectSP lldb_private::formatters:: ValueObjectSP hash_sp = node_sp->GetChildMemberWithName("__hash_"); if (!hash_sp || !value_sp) { if (!m_element_type) { - auto p1_sp = m_backend.GetChildAtNamePath({"__table_", "__p1_"}); - if (!p1_sp) - return nullptr; + auto compressed_pair_layout_getter = [this](ValueObject &node) { + ValueObjectSP first_sp = GetFirstValueOfLibCXXCompressedPair(node); - ValueObjectSP first_sp = GetFirstValueOfLibCXXCompressedPair(*p1_sp); - if (!first_sp) - return nullptr; + if (!first_sp) + return false; + + m_element_type = first_sp->GetCompilerType(); + m_element_type = m_element_type.GetTypeTemplateArgument(0); + m_element_type = m_element_type.GetPointeeType(); + m_node_type = m_element_type; + m_element_type = m_element_type.GetTypeTemplateArgument(0); + + return true; + }; + + auto compressed_pair_v2_layout_getter = [this](ValueObject &node) { + m_element_type = node.GetCompilerType(); + m_element_type = m_element_type.GetPointeeType(); + m_node_type = m_element_type; + m_element_type = m_element_type.GetTypeTemplateArgument(0); + + return true; + }; + + auto p1_sp = m_backend.GetChildAtNamePath({"__table_", "__p1_"}); + if (p1_sp) { + compressed_pair_layout_getter(*p1_sp); + } else { + p1_sp = m_backend.GetChildAtNamePath({"__table_", "__first_node_"}); + compressed_pair_v2_layout_getter(*p1_sp); + } - m_element_type = first_sp->GetCompilerType(); - m_element_type = m_element_type.GetTypeTemplateArgument(0); - m_element_type = m_element_type.GetPointeeType(); - m_node_type = m_element_type; - m_element_type = m_element_type.GetTypeTemplateArgument(0); // This synthetic provider is used for both unordered_(multi)map and // unordered_(multi)set. For unordered_map, the element type has an // additional type layer, an internal struct (`__hash_value_type`) @@ -202,24 +222,35 @@ lldb_private::formatters::LibcxxStdUnorderedMapSyntheticFrontEnd::Update() { if (!table_sp) return lldb::ChildCacheState::eRefetch; + bool has_compressed_pair_layout = true; + ValueObjectSP p1_sp = table_sp->GetChildMemberWithName("__p1_"); ValueObjectSP p2_sp = table_sp->GetChildMemberWithName("__p2_"); - if (!p2_sp) - return lldb::ChildCacheState::eRefetch; + if (!p1_sp || !p2_sp) { + has_compressed_pair_layout = false; + } + + ValueObjectSP num_elements_sp = nullptr; + if (has_compressed_pair_layout) { + num_elements_sp = GetFirstValueOfLibCXXCompressedPair(*p2_sp); + } else { + num_elements_sp = table_sp->GetChildMemberWithName("__size_"); + } - ValueObjectSP num_elements_sp = GetFirstValueOfLibCXXCompressedPair(*p2_sp); if (!num_elements_sp) return lldb::ChildCacheState::eRefetch; - ValueObjectSP p1_sp = table_sp->GetChildMemberWithName("__p1_"); - if (!p1_sp) - return lldb::ChildCacheState::eRefetch; + ValueObjectSP tree_sp = nullptr; + if (has_compressed_pair_layout) { + tree_sp = GetFirstValueOfLibCXXCompressedPair(*p1_sp); + } else { + tree_sp = table_sp->GetChildMemberWithName("__first_node_"); + } - ValueObjectSP value_sp = GetFirstValueOfLibCXXCompressedPair(*p1_sp); - if (!value_sp) + if (!tree_sp) return lldb::ChildCacheState::eRefetch; - m_tree = value_sp->GetChildMemberWithName("__next_").get(); - if (m_tree == nullptr) + m_tree = tree_sp->GetChildMemberWithName("__next_").get(); + if (!m_tree) return lldb::ChildCacheState::eRefetch; m_num_elements = num_elements_sp->GetValueAsUnsigned(0); diff --git a/lldb/source/Plugins/Language/CPlusPlus/LibCxxVector.cpp b/lldb/source/Plugins/Language/CPlusPlus/LibCxxVector.cpp index 461fed35164b4..dde23a78b4202 100644 --- a/lldb/source/Plugins/Language/CPlusPlus/LibCxxVector.cpp +++ b/lldb/source/Plugins/Language/CPlusPlus/LibCxxVector.cpp @@ -11,6 +11,8 @@ #include "lldb/Core/ValueObject.h" #include "lldb/DataFormatters/FormattersHelpers.h" #include "lldb/Utility/ConstString.h" +#include "lldb/lldb-enumerations.h" +#include "lldb/lldb-forward.h" #include <optional> using namespace lldb; @@ -116,16 +118,31 @@ lldb_private::formatters::LibcxxStdVectorSyntheticFrontEnd::GetChildAtIndex( m_element_type); } +static ValueObjectSP ExtractDataTypeFinderV1(ValueObject &valobj) { + ValueObjectSP data_type_finder_sp( + valobj.GetChildMemberWithName("__end_cap_")); + if (!data_type_finder_sp) + return {}; + + return GetFirstValueOfLibCXXCompressedPair(*data_type_finder_sp); +} + +static ValueObjectSP ExtractDataTypeFinderV2(ValueObject &valobj) { + return valobj.GetChildMemberWithName("__cap_"); +} + +static ValueObjectSP ExtractDataTypeFinder(ValueObject &valobj) { + if (auto ret = ExtractDataTypeFinderV1(valobj)) + return ret; + + return ExtractDataTypeFinderV2(valobj); +} + lldb::ChildCacheState lldb_private::formatters::LibcxxStdVectorSyntheticFrontEnd::Update() { m_start = m_finish = nullptr; - ValueObjectSP data_type_finder_sp( - m_backend.GetChildMemberWithName("__end_cap_")); - if (!data_type_finder_sp) - return lldb::ChildCacheState::eRefetch; + ValueObjectSP data_type_finder_sp(ExtractDataTypeFinder(m_backend)); - data_type_finder_sp = - GetFirstValueOfLibCXXCompressedPair(*data_type_finder_sp); if (!data_type_finder_sp) return lldb::ChildCacheState::eRefetch; @@ -216,17 +233,6 @@ lldb_private::formatters::LibcxxVectorBoolSyntheticFrontEnd::GetChildAtIndex( return retval_sp; } -/*(std::__1::vector<std::__1::allocator<bool> >) vBool = { - __begin_ = 0x00000001001000e0 - __size_ = 56 - __cap_alloc_ = { - std::__1::__libcpp_compressed_pair_imp<unsigned long, - std::__1::allocator<unsigned long> > = { - __first_ = 1 - } - } - }*/ - lldb::ChildCacheState lldb_private::formatters::LibcxxVectorBoolSyntheticFrontEnd::Update() { m_children.clear(); 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 270aab1b75122..af6183766301e 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 @@ -62,7 +62,8 @@ def cleanup(): self.expect( "frame variable numbers_list --raw", matching=False, - substrs=["size=0", "{}"], + #substrs=["size=0", "{}"], # TODO: if __padding_ members aren't added this isn't needed + substrs=["size=0"] ) if stdlib_type == USE_LIBSTDCPP: diff --git a/lldb/test/API/functionalities/data-formatter/data-formatter-stl/libcxx/string/simulator/main.cpp b/lldb/test/API/functionalities/data-formatter/data-formatter-stl/libcxx/string/simulator/main.cpp index 33e71044482a7..6d4200e19c246 100644 --- a/lldb/test/API/functionalities/data-formatter/data-formatter-stl/libcxx/string/simulator/main.cpp +++ b/lldb/test/API/functionalities/data-formatter/data-formatter-stl/libcxx/string/simulator/main.cpp @@ -212,6 +212,7 @@ template <class _CharT, class _Traits, class _Allocator> class basic_string { }; }; + // TODO: support the new non-compressed_pair layout __compressed_pair<__rep, allocator_type> __r_; public: diff --git a/lldb/test/API/functionalities/data-formatter/data-formatter-stl/libcxx/unique_ptr/TestDataFormatterLibcxxUniquePtr.py b/lldb/test/API/functionalities/data-formatter/data-formatter-stl/libcxx/unique_ptr/TestDataFormatterLibcxxUniquePtr.py index 6a726e0253482..153c507a45b87 100644 --- a/lldb/test/API/functionalities/data-formatter/data-formatter-stl/libcxx/unique_ptr/TestDataFormatterLibcxxUniquePtr.py +++ b/lldb/test/API/functionalities/data-formatter/data-formatter-stl/libcxx/unique_ptr/TestDataFormatterLibcxxUniquePtr.py @@ -45,6 +45,7 @@ def test_unique_ptr_variables(self): "up_empty", type=self.make_expected_type("int"), summary="nullptr", + #children=[ValueCheck(name="pointer"), ValueCheck(name="deleter")], # TODO: shouldn't be printing deleter children=[ValueCheck(name="pointer")], ) self.assertEqual( @@ -59,6 +60,7 @@ def test_unique_ptr_variables(self): "up_int", type=self.make_expected_type("int"), summary="10", + #children=[ValueCheck(name="pointer"), ValueCheck(name="deleter")], # TODO: shouldn't be printing deleter children=[ValueCheck(name="pointer")], ) self.assertNotEqual(valobj.child[0].unsigned, 0) @@ -67,6 +69,7 @@ def test_unique_ptr_variables(self): "up_int_ref", type=self.make_expected_type("int", qualifiers="&"), summary="10", + #children=[ValueCheck(name="pointer"), ValueCheck(name="deleter")], # TODO: shouldn't be printing deleter children=[ValueCheck(name="pointer")], ) self.assertNotEqual(valobj.child[0].unsigned, 0) @@ -75,6 +78,7 @@ def test_unique_ptr_variables(self): "up_int_ref_ref", type=self.make_expected_type("int", qualifiers="&&"), summary="10", + #children=[ValueCheck(name="pointer"), ValueCheck(name="deleter")], # TODO: shouldn't be printing deleter children=[ValueCheck(name="pointer")], ) self.assertNotEqual(valobj.child[0].unsigned, 0) @@ -83,7 +87,8 @@ def test_unique_ptr_variables(self): "up_str", type=self.make_expected_basic_string_ptr(), summary='"hello"', - children=[ValueCheck(name="pointer", summary='"hello"')], + #children=[ValueCheck(name="pointer"), ValueCheck(name="deleter")], # TODO: shouldn't be printing deleter + children=[ValueCheck(name="pointer")], ) valobj = self.expect_var_path("up_user", type=self.make_expected_type("User")) >From a658b095dbd78e0e0eaf2073e139181ba32994bb Mon Sep 17 00:00:00 2001 From: Michael Buch <michaelbuc...@gmail.com> Date: Thu, 27 Jun 2024 11:56:12 +0100 Subject: [PATCH 2/2] [lldb][DataFormatter] Fix unordered_map formatter --- .../Language/CPlusPlus/LibCxxUnorderedMap.cpp | 23 ++++++------------- 1 file changed, 7 insertions(+), 16 deletions(-) diff --git a/lldb/source/Plugins/Language/CPlusPlus/LibCxxUnorderedMap.cpp b/lldb/source/Plugins/Language/CPlusPlus/LibCxxUnorderedMap.cpp index a249d68ce1b87..0ab7e1afffaa7 100644 --- a/lldb/source/Plugins/Language/CPlusPlus/LibCxxUnorderedMap.cpp +++ b/lldb/source/Plugins/Language/CPlusPlus/LibCxxUnorderedMap.cpp @@ -114,22 +114,8 @@ lldb::ValueObjectSP lldb_private::formatters:: if (!hash_sp || !value_sp) { if (!m_element_type) { auto compressed_pair_layout_getter = [this](ValueObject &node) { - ValueObjectSP first_sp = GetFirstValueOfLibCXXCompressedPair(node); - - if (!first_sp) - return false; - - m_element_type = first_sp->GetCompilerType(); - m_element_type = m_element_type.GetTypeTemplateArgument(0); - m_element_type = m_element_type.GetPointeeType(); - m_node_type = m_element_type; - m_element_type = m_element_type.GetTypeTemplateArgument(0); - - return true; - }; - - auto compressed_pair_v2_layout_getter = [this](ValueObject &node) { m_element_type = node.GetCompilerType(); + m_element_type = m_element_type.GetTypeTemplateArgument(0); m_element_type = m_element_type.GetPointeeType(); m_node_type = m_element_type; m_element_type = m_element_type.GetTypeTemplateArgument(0); @@ -139,10 +125,15 @@ lldb::ValueObjectSP lldb_private::formatters:: auto p1_sp = m_backend.GetChildAtNamePath({"__table_", "__p1_"}); if (p1_sp) { + ValueObjectSP first_sp = GetFirstValueOfLibCXXCompressedPair(*p1_sp); + + if (!first_sp) + return {}; + compressed_pair_layout_getter(*p1_sp); } else { p1_sp = m_backend.GetChildAtNamePath({"__table_", "__first_node_"}); - compressed_pair_v2_layout_getter(*p1_sp); + compressed_pair_layout_getter(*p1_sp); } // This synthetic provider is used for both unordered_(multi)map and _______________________________________________ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits