https://github.com/Michael137 updated https://github.com/llvm/llvm-project/pull/96538
>From 2b82d72874c396258378f9db2f01729e5be5bae1 Mon Sep 17 00:00:00 2001 From: Michael Buch <michaelbuc...@gmail.com> Date: Mon, 29 Jan 2024 16:23:16 +0000 Subject: [PATCH] [lldb] Support new libc++ __compressed_pair layout --- lldb/examples/synthetic/libcxx.py | 26 ++++-- .../Plugins/Language/CPlusPlus/LibCxx.cpp | 78 ++++++++++++----- .../Plugins/Language/CPlusPlus/LibCxx.h | 1 + .../Plugins/Language/CPlusPlus/LibCxxList.cpp | 83 ++++++++++++------- .../Plugins/Language/CPlusPlus/LibCxxMap.cpp | 68 +++++++++++---- .../Language/CPlusPlus/LibCxxUnorderedMap.cpp | 82 +++++++++--------- .../Language/CPlusPlus/LibCxxVector.cpp | 40 +++++---- .../list/TestDataFormatterGenericList.py | 3 +- .../libcxx/string/simulator/main.cpp | 1 + .../TestDataFormatterLibcxxUniquePtr.py | 2 +- 10 files changed, 253 insertions(+), 131 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 05cfa0568c25d..f23b8697792da 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> @@ -34,6 +35,31 @@ using namespace lldb; using namespace lldb_private; using namespace lldb_private::formatters; +static bool isOldCompressedPairLayout(ValueObject &pair_obj) { + return isStdTemplate(pair_obj.GetTypeName(), "__compressed_pair"); +} + +static void consumeInlineNamespace(llvm::StringRef &name) { + // Delete past an inline namespace, if any: __[a-zA-Z0-9_]+:: + auto scratch = name; + if (scratch.consume_front("__") && std::isalnum(scratch[0])) { + scratch = scratch.drop_while([](char c) { return std::isalnum(c); }); + if (scratch.consume_front("::")) { + // Successfully consumed a namespace. + name = scratch; + } + } +} + +bool lldb_private::formatters::isStdTemplate(ConstString type_name, llvm::StringRef type) { + llvm::StringRef name = type_name.GetStringRef(); + // The type name may be prefixed with `std::__<inline-namespace>::`. + if (name.consume_front("std::")) + consumeInlineNamespace(name); + return name.consume_front(type) && name.starts_with("<"); +} + + lldb::ValueObjectSP lldb_private::formatters::GetChildMemberWithName( ValueObject &obj, llvm::ArrayRef<ConstString> alternative_names) { for (ConstString name : alternative_names) { @@ -176,7 +202,9 @@ bool lldb_private::formatters::LibcxxUniquePointerSummaryProvider( if (!ptr_sp) return false; - ptr_sp = GetFirstValueOfLibCXXCompressedPair(*ptr_sp); + if (isOldCompressedPairLayout(*ptr_sp)) + ptr_sp = GetFirstValueOfLibCXXCompressedPair(*ptr_sp); + if (!ptr_sp) return false; @@ -512,13 +540,20 @@ lldb_private::formatters::LibcxxUniquePtrSyntheticFrontEnd::Update() { // 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")); + if (isOldCompressedPairLayout(*ptr_sp)) { + if (ValueObjectSP value_pointer_sp = + GetFirstValueOfLibCXXCompressedPair(*ptr_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")); + if (ValueObjectSP deleter_sp = GetSecondValueOfLibCXXCompressedPair(*ptr_sp)) + m_deleter_sp = deleter_sp->Clone(ConstString("deleter")); + } else { + m_value_ptr_sp = ptr_sp->Clone(ConstString("pointer")); + + if (ValueObjectSP deleter_sp = valobj_sp->GetChildMemberWithName("__deleter_")) + if (deleter_sp->GetNumChildrenIgnoringErrors() > 0) + m_deleter_sp = deleter_sp->Clone(ConstString("deleter")); + } return lldb::ChildCacheState::eRefetch; } @@ -556,24 +591,27 @@ namespace { enum class StringLayout { CSD, DSC }; } +static ValueObjectSP ExtractLibCxxStringData(ValueObject &valobj) { + if (auto rep_sp = valobj.GetChildMemberWithName("__rep_")) + return rep_sp; + + ValueObjectSP valobj_r_sp = valobj.GetChildMemberWithName("__r_"); + if (!valobj_r_sp || !valobj_r_sp->GetError().Success()) + return nullptr; + + if (!isOldCompressedPairLayout(*valobj_r_sp)) + return nullptr; + + return GetFirstValueOfLibCXXCompressedPair(*valobj_r_sp); +} + /// 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_r_sp = valobj.GetChildMemberWithName("__r_"); - if (!valobj_r_sp || !valobj_r_sp->GetError().Success()) - return {}; - - // __r_ is a compressed_pair of the actual data and the allocator. The data we - // want is in the first base class. - ValueObjectSP valobj_r_base_sp = valobj_r_sp->GetChildAtIndex(0); - if (!valobj_r_base_sp) - return {}; - - ValueObjectSP valobj_rep_sp = - valobj_r_base_sp->GetChildMemberWithName("__value_"); - if (!valobj_rep_sp) + ValueObjectSP valobj_rep_sp = ExtractLibCxxStringData(valobj); + if (!valobj_rep_sp || !valobj_rep_sp->GetError().Success()) return {}; ValueObjectSP l = valobj_rep_sp->GetChildMemberWithName("__l"); diff --git a/lldb/source/Plugins/Language/CPlusPlus/LibCxx.h b/lldb/source/Plugins/Language/CPlusPlus/LibCxx.h index 21dba015d1ba1..2ba2d584f340f 100644 --- a/lldb/source/Plugins/Language/CPlusPlus/LibCxx.h +++ b/lldb/source/Plugins/Language/CPlusPlus/LibCxx.h @@ -26,6 +26,7 @@ GetChildMemberWithName(ValueObject &obj, lldb::ValueObjectSP GetFirstValueOfLibCXXCompressedPair(ValueObject &pair); lldb::ValueObjectSP GetSecondValueOfLibCXXCompressedPair(ValueObject &pair); +bool isStdTemplate(ConstString type_name, llvm::StringRef type); bool LibcxxStringSummaryProviderASCII( ValueObject &valobj, Stream &stream, 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 c2bb3555908be..bb81a95d34831 100644 --- a/lldb/source/Plugins/Language/CPlusPlus/LibCxxMap.cpp +++ b/lldb/source/Plugins/Language/CPlusPlus/LibCxxMap.cpp @@ -181,6 +181,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); @@ -207,6 +210,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; }; class LibCxxMapIteratorSyntheticFrontEnd : public SyntheticChildrenFrontEnd { @@ -239,6 +243,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) @@ -247,17 +276,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() { @@ -274,12 +296,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; @@ -458,6 +490,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..6d811adbc8a26 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; @@ -67,26 +68,6 @@ llvm::Expected<uint32_t> lldb_private::formatters:: return m_num_elements; } -static void consumeInlineNamespace(llvm::StringRef &name) { - // Delete past an inline namespace, if any: __[a-zA-Z0-9_]+:: - auto scratch = name; - if (scratch.consume_front("__") && std::isalnum(scratch[0])) { - scratch = scratch.drop_while([](char c) { return std::isalnum(c); }); - if (scratch.consume_front("::")) { - // Successfully consumed a namespace. - name = scratch; - } - } -} - -static bool isStdTemplate(ConstString type_name, llvm::StringRef type) { - llvm::StringRef name = type_name.GetStringRef(); - // The type name may be prefixed with `std::__<inline-namespace>::`. - if (name.consume_front("std::")) - consumeInlineNamespace(name); - return name.consume_front(type) && name.starts_with("<"); -} - static bool isUnorderedMap(ConstString type_name) { return isStdTemplate(type_name, "unordered_map") || isStdTemplate(type_name, "unordered_multimap"); @@ -112,19 +93,29 @@ lldb::ValueObjectSP lldb_private::formatters:: ValueObjectSP hash_sp = node_sp->GetChildMemberWithName("__hash_"); if (!hash_sp || !value_sp) { if (!m_element_type) { + auto compressed_pair_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); + + return true; + }; + auto p1_sp = m_backend.GetChildAtNamePath({"__table_", "__p1_"}); - if (!p1_sp) - return nullptr; + if (p1_sp) { + ValueObjectSP first_sp = GetFirstValueOfLibCXXCompressedPair(*p1_sp); - ValueObjectSP first_sp = GetFirstValueOfLibCXXCompressedPair(*p1_sp); - if (!first_sp) - return nullptr; + if (!first_sp) + return {}; + + compressed_pair_layout_getter(*first_sp); + } else { + p1_sp = m_backend.GetChildAtNamePath({"__table_", "__first_node_"}); + compressed_pair_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 +193,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..4aad9221fcf15 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 @@ -83,7 +83,7 @@ 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")], ) valobj = self.expect_var_path("up_user", type=self.make_expected_type("User")) _______________________________________________ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits