1919#include " lldb/Utility/Stream.h"
2020#include " lldb/lldb-forward.h"
2121#include < cstdint>
22+ #include < locale>
2223#include < optional>
2324
2425using namespace lldb ;
2526using namespace lldb_private ;
2627using namespace lldb_private ::formatters;
2728
29+ // The flattened layout of the std::__tree_iterator::__ptr_ looks
30+ // as follows:
31+ //
32+ // The following shows the contiguous block of memory:
33+ //
34+ // +-----------------------------+ class __tree_end_node
35+ // __ptr_ | pointer __left_; |
36+ // +-----------------------------+ class __tree_node_base
37+ // | pointer __right_; |
38+ // | __parent_pointer __parent_; |
39+ // | bool __is_black_; |
40+ // +-----------------------------+ class __tree_node
41+ // | __node_value_type __value_; | <<< our key/value pair
42+ // +-----------------------------+
43+ //
44+ // where __ptr_ has type __iter_pointer.
45+
2846class MapEntry {
2947public:
3048 MapEntry () = default ;
@@ -183,10 +201,6 @@ class LibcxxStdMapSyntheticFrontEnd : public SyntheticChildrenFrontEnd {
183201 size_t GetIndexOfChildWithName (ConstString name) override ;
184202
185203private:
186- bool GetDataType ();
187-
188- std::optional<uint32_t > GetValueOffset ();
189-
190204 // / Returns the ValueObject for the __tree_node type that
191205 // / holds the key/value pair of the node at index \ref idx.
192206 // /
@@ -205,8 +219,7 @@ class LibcxxStdMapSyntheticFrontEnd : public SyntheticChildrenFrontEnd {
205219
206220 ValueObject *m_tree = nullptr ;
207221 ValueObject *m_root_node = nullptr ;
208- CompilerType m_element_type;
209- uint32_t m_value_type_offset = UINT32_MAX;
222+ CompilerType m_node_ptr_type;
210223 size_t m_count = UINT32_MAX;
211224 std::map<size_t , MapIterator> m_iterators;
212225};
@@ -215,7 +228,7 @@ class LibcxxStdMapSyntheticFrontEnd : public SyntheticChildrenFrontEnd {
215228
216229lldb_private::formatters::LibcxxStdMapSyntheticFrontEnd::
217230 LibcxxStdMapSyntheticFrontEnd (lldb::ValueObjectSP valobj_sp)
218- : SyntheticChildrenFrontEnd(*valobj_sp), m_element_type(), m_iterators() {
231+ : SyntheticChildrenFrontEnd(*valobj_sp) {
219232 if (valobj_sp)
220233 Update ();
221234}
@@ -241,80 +254,6 @@ llvm::Expected<uint32_t> lldb_private::formatters::
241254 return m_count;
242255}
243256
244- bool lldb_private::formatters::LibcxxStdMapSyntheticFrontEnd::GetDataType () {
245- if (m_element_type.IsValid ())
246- return true ;
247- m_element_type.Clear ();
248- ValueObjectSP deref;
249- Status error;
250- deref = m_root_node->Dereference (error);
251- if (!deref || error.Fail ())
252- return false ;
253- deref = deref->GetChildMemberWithName (" __value_" );
254- if (deref) {
255- m_element_type = deref->GetCompilerType ();
256- return true ;
257- }
258- deref = m_backend.GetChildAtNamePath ({" __tree_" , " __pair3_" });
259- if (!deref)
260- return false ;
261- m_element_type = deref->GetCompilerType ()
262- .GetTypeTemplateArgument (1 )
263- .GetTypeTemplateArgument (1 );
264- if (m_element_type) {
265- std::string name;
266- uint64_t bit_offset_ptr;
267- uint32_t bitfield_bit_size_ptr;
268- bool is_bitfield_ptr;
269- m_element_type = m_element_type.GetFieldAtIndex (
270- 0 , name, &bit_offset_ptr, &bitfield_bit_size_ptr, &is_bitfield_ptr);
271- m_element_type = m_element_type.GetTypedefedType ();
272- return m_element_type.IsValid ();
273- } else {
274- m_element_type = m_backend.GetCompilerType ().GetTypeTemplateArgument (0 );
275- return m_element_type.IsValid ();
276- }
277- }
278-
279- std::optional<uint32_t >
280- lldb_private::formatters::LibcxxStdMapSyntheticFrontEnd::GetValueOffset () {
281- if (!m_tree)
282- return std::nullopt ;
283-
284- auto ast_ctx = m_tree->GetCompilerType ()
285- .GetTypeSystem ()
286- .dyn_cast_or_null <TypeSystemClang>();
287- if (!ast_ctx)
288- return std::nullopt ;
289-
290- CompilerType tree_node_type = ast_ctx->CreateStructForIdentifier (
291- llvm::StringRef (),
292- {{" ptr0" , ast_ctx->GetBasicType (lldb::eBasicTypeVoid).GetPointerType ()},
293- {" ptr1" , ast_ctx->GetBasicType (lldb::eBasicTypeVoid).GetPointerType ()},
294- {" ptr2" , ast_ctx->GetBasicType (lldb::eBasicTypeVoid).GetPointerType ()},
295- {" cw" , ast_ctx->GetBasicType (lldb::eBasicTypeBool)},
296- {" payload" , (m_element_type.GetCompleteType (), m_element_type)}});
297- std::string child_name;
298- uint32_t child_byte_size;
299- int32_t child_byte_offset = 0 ;
300- uint32_t child_bitfield_bit_size;
301- uint32_t child_bitfield_bit_offset;
302- bool child_is_base_class;
303- bool child_is_deref_of_parent;
304- uint64_t language_flags;
305- auto child_type =
306- llvm::expectedToStdOptional (tree_node_type.GetChildCompilerTypeAtIndex (
307- nullptr , 4 , true , true , true , child_name, child_byte_size,
308- child_byte_offset, child_bitfield_bit_size, child_bitfield_bit_offset,
309- child_is_base_class, child_is_deref_of_parent, nullptr ,
310- language_flags));
311-
312- if (!child_type || !child_type->IsValid ())
313- return std::nullopt ;
314-
315- return child_byte_offset;
316- }
317-
318257ValueObjectSP
319258lldb_private::formatters::LibcxxStdMapSyntheticFrontEnd::GetKeyValuePair (
320259 size_t idx, size_t max_depth) {
@@ -336,26 +275,31 @@ lldb_private::formatters::LibcxxStdMapSyntheticFrontEnd::GetKeyValuePair(
336275 // this tree is garbage - stop
337276 return nullptr ;
338277
339- if (!GetDataType ())
278+ if (!m_node_ptr_type. IsValid ())
340279 return nullptr ;
341280
342- if (m_value_type_offset == UINT32_MAX) {
343- if (auto offset = GetValueOffset ())
344- m_value_type_offset = *offset;
345- else
346- return nullptr ;
347- }
281+ // iterated_sp is a __iter_pointer at this point.
282+ // We can cast it to a __node_pointer (which is what libc++ does).
283+ auto value_type_sp = iterated_sp->Cast (m_node_ptr_type);
284+ if (!value_type_sp)
285+ return nullptr ;
348286
349- assert (m_value_type_offset != UINT32_MAX);
287+ // After dereferencing the __node_pointer, we will have a handle to
288+ // a std::__1::__tree_node<void *>, which has the __value_ member
289+ // we are looking for.
290+ Status s;
291+ value_type_sp = value_type_sp->Dereference (s);
292+ if (!value_type_sp || s.Fail ())
293+ return nullptr ;
350294
351- iterated_sp = iterated_sp-> GetSyntheticChildAtOffset (m_value_type_offset,
352- m_element_type, true );
353- if (!iterated_sp )
295+ // Finally, get the key/value pair.
296+ value_type_sp = value_type_sp-> GetChildMemberWithName ( " __value_ " );
297+ if (!value_type_sp )
354298 return nullptr ;
355299
356300 m_iterators[idx] = iterator;
357301
358- return iterated_sp ;
302+ return value_type_sp ;
359303}
360304
361305lldb::ValueObjectSP
@@ -415,6 +359,9 @@ lldb_private::formatters::LibcxxStdMapSyntheticFrontEnd::Update() {
415359 if (!m_tree)
416360 return lldb::ChildCacheState::eRefetch;
417361 m_root_node = m_tree->GetChildMemberWithName (" __begin_node_" ).get ();
362+ m_node_ptr_type =
363+ m_tree->GetCompilerType ().GetDirectNestedTypeWithName (" __node_pointer" );
364+
418365 return lldb::ChildCacheState::eRefetch;
419366}
420367
0 commit comments