1818#include " lldb/Utility/Status.h"
1919#include " lldb/Utility/Stream.h"
2020#include " lldb/lldb-forward.h"
21+ #include < cstdint>
22+ #include < optional>
2123
2224using namespace lldb ;
2325using namespace lldb_private ;
@@ -183,7 +185,7 @@ class LibcxxStdMapSyntheticFrontEnd : public SyntheticChildrenFrontEnd {
183185private:
184186 bool GetDataType ();
185187
186- void GetValueOffset ( const lldb::ValueObjectSP &node );
188+ std::optional< uint32_t > GetValueOffset ( );
187189
188190 // / Returns the ValueObject for the __tree_node type that
189191 // / holds the key/value pair of the node at index \ref idx.
@@ -204,7 +206,7 @@ class LibcxxStdMapSyntheticFrontEnd : public SyntheticChildrenFrontEnd {
204206 ValueObject *m_tree = nullptr ;
205207 ValueObject *m_root_node = nullptr ;
206208 CompilerType m_element_type;
207- uint32_t m_skip_size = UINT32_MAX;
209+ uint32_t m_value_type_offset = UINT32_MAX;
208210 size_t m_count = UINT32_MAX;
209211 std::map<size_t , MapIterator> m_iterators;
210212};
@@ -274,109 +276,84 @@ bool lldb_private::formatters::LibcxxStdMapSyntheticFrontEnd::GetDataType() {
274276 }
275277}
276278
277- void lldb_private::formatters::LibcxxStdMapSyntheticFrontEnd::GetValueOffset (
278- const lldb::ValueObjectSP &node) {
279- if (m_skip_size != UINT32_MAX)
280- return ;
281- if (!node)
282- return ;
283- CompilerType node_type (node->GetCompilerType ());
284- uint64_t bit_offset;
285- if (node_type.GetIndexOfFieldWithName (" __value_" , nullptr , &bit_offset) !=
286- UINT32_MAX) {
287- // Old layout (pre d05b10ab4fc65)
288- m_skip_size = bit_offset / 8u ;
289- } else {
290- auto ast_ctx = node_type.GetTypeSystem ().dyn_cast_or_null <TypeSystemClang>();
291- if (!ast_ctx)
292- return ;
293- CompilerType tree_node_type = ast_ctx->CreateStructForIdentifier (
294- llvm::StringRef (),
295- {{" ptr0" , ast_ctx->GetBasicType (lldb::eBasicTypeVoid).GetPointerType ()},
296- {" ptr1" , ast_ctx->GetBasicType (lldb::eBasicTypeVoid).GetPointerType ()},
297- {" ptr2" , ast_ctx->GetBasicType (lldb::eBasicTypeVoid).GetPointerType ()},
298- {" cw" , ast_ctx->GetBasicType (lldb::eBasicTypeBool)},
299- {" payload" , (m_element_type.GetCompleteType (), m_element_type)}});
300- std::string child_name;
301- uint32_t child_byte_size;
302- int32_t child_byte_offset = 0 ;
303- uint32_t child_bitfield_bit_size;
304- uint32_t child_bitfield_bit_offset;
305- bool child_is_base_class;
306- bool child_is_deref_of_parent;
307- uint64_t language_flags;
308- auto child_type =
309- llvm::expectedToStdOptional (tree_node_type.GetChildCompilerTypeAtIndex (
310- nullptr , 4 , true , true , true , child_name, child_byte_size,
311- child_byte_offset, child_bitfield_bit_size,
312- child_bitfield_bit_offset, child_is_base_class,
313- child_is_deref_of_parent, nullptr , language_flags));
314- if (child_type && child_type->IsValid ())
315- m_skip_size = (uint32_t )child_byte_offset;
316- }
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;
317316}
318317
319318ValueObjectSP
320319lldb_private::formatters::LibcxxStdMapSyntheticFrontEnd::GetKeyValuePair (
321320 size_t idx, size_t max_depth) {
322321 MapIterator iterator (m_root_node, max_depth);
323322
324- const bool need_to_skip = (idx > 0 );
325- size_t actual_advance = idx;
326- if (need_to_skip) {
323+ size_t advance_by = idx;
324+ if (idx > 0 ) {
327325 // If we have already created the iterator for the previous
328326 // index, we can start from there and advance by 1.
329327 auto cached_iterator = m_iterators.find (idx - 1 );
330328 if (cached_iterator != m_iterators.end ()) {
331329 iterator = cached_iterator->second ;
332- actual_advance = 1 ;
330+ advance_by = 1 ;
333331 }
334332 }
335333
336- ValueObjectSP iterated_sp (iterator.advance (actual_advance ));
334+ ValueObjectSP iterated_sp (iterator.advance (advance_by ));
337335 if (!iterated_sp)
338336 // this tree is garbage - stop
339337 return nullptr ;
340338
341339 if (!GetDataType ())
342340 return nullptr ;
343341
344- if (!need_to_skip) {
345- Status error;
346- iterated_sp = iterated_sp->Dereference (error);
347- if (!iterated_sp || error.Fail ())
348- return nullptr ;
349-
350- GetValueOffset (iterated_sp);
351- auto child_sp = iterated_sp->GetChildMemberWithName (" __value_" );
352- if (child_sp) {
353- // Old layout (pre 089a7cc5dea)
354- iterated_sp = child_sp;
355- } else {
356- iterated_sp = iterated_sp->GetSyntheticChildAtOffset (
357- m_skip_size, m_element_type, true );
358- }
359-
360- if (!iterated_sp)
342+ if (m_value_type_offset == UINT32_MAX) {
343+ if (auto offset = GetValueOffset ())
344+ m_value_type_offset = *offset;
345+ else
361346 return nullptr ;
362- } else {
363- // because of the way our debug info is made, we need to read item 0
364- // first so that we can cache information used to generate other elements
365- if (m_skip_size == UINT32_MAX)
366- GetChildAtIndex (0 );
347+ }
367348
368- if (m_skip_size == UINT32_MAX)
369- return nullptr ;
349+ assert (m_value_type_offset != UINT32_MAX);
370350
371- iterated_sp = iterated_sp->GetSyntheticChildAtOffset (m_skip_size,
372- m_element_type, true );
373- if (!iterated_sp)
374- return nullptr ;
375- }
351+ iterated_sp = iterated_sp->GetSyntheticChildAtOffset (m_value_type_offset,
352+ m_element_type, true );
353+ if (!iterated_sp)
354+ return nullptr ;
376355
377356 m_iterators[idx] = iterator;
378- assert (iterated_sp != nullptr &&
379- " Cached MapIterator for invalid ValueObject" );
380357
381358 return iterated_sp;
382359}
0 commit comments