2727#include " Plugins/LanguageRuntime/CPlusPlus/CPPLanguageRuntime.h"
2828#include " Plugins/TypeSystem/Clang/TypeSystemClang.h"
2929#include " lldb/lldb-enumerations.h"
30+ #include " lldb/lldb-forward.h"
3031#include < optional>
3132#include < tuple>
3233
3334using namespace lldb ;
3435using namespace lldb_private ;
3536using namespace lldb_private ::formatters;
3637
38+ static void consumeInlineNamespace (llvm::StringRef &name) {
39+ // Delete past an inline namespace, if any: __[a-zA-Z0-9_]+::
40+ auto scratch = name;
41+ if (scratch.consume_front (" __" ) && std::isalnum (scratch[0 ])) {
42+ scratch = scratch.drop_while ([](char c) { return std::isalnum (c); });
43+ if (scratch.consume_front (" ::" )) {
44+ // Successfully consumed a namespace.
45+ name = scratch;
46+ }
47+ }
48+ }
49+
50+ bool lldb_private::formatters::isOldCompressedPairLayout (
51+ ValueObject &pair_obj) {
52+ return isStdTemplate (pair_obj.GetTypeName (), " __compressed_pair" );
53+ }
54+
55+ bool lldb_private::formatters::isStdTemplate (ConstString type_name,
56+ llvm::StringRef type) {
57+ llvm::StringRef name = type_name.GetStringRef ();
58+ // The type name may be prefixed with `std::__<inline-namespace>::`.
59+ if (name.consume_front (" std::" ))
60+ consumeInlineNamespace (name);
61+ return name.consume_front (type) && name.starts_with (" <" );
62+ }
63+
3764lldb::ValueObjectSP lldb_private::formatters::GetChildMemberWithName (
3865 ValueObject &obj, llvm::ArrayRef<ConstString> alternative_names) {
3966 for (ConstString name : alternative_names) {
@@ -53,7 +80,7 @@ lldb_private::formatters::GetFirstValueOfLibCXXCompressedPair(
5380 if (first_child)
5481 value = first_child->GetChildMemberWithName (" __value_" );
5582 if (!value) {
56- // pre-r300140 member name
83+ // pre-c88580c member name
5784 value = pair.GetChildMemberWithName (" __first_" );
5885 }
5986 return value;
@@ -70,7 +97,7 @@ lldb_private::formatters::GetSecondValueOfLibCXXCompressedPair(
7097 }
7198 }
7299 if (!value) {
73- // pre-r300140 member name
100+ // pre-c88580c member name
74101 value = pair.GetChildMemberWithName (" __second_" );
75102 }
76103 return value;
@@ -176,7 +203,9 @@ bool lldb_private::formatters::LibcxxUniquePointerSummaryProvider(
176203 if (!ptr_sp)
177204 return false ;
178205
179- ptr_sp = GetFirstValueOfLibCXXCompressedPair (*ptr_sp);
206+ if (isOldCompressedPairLayout (*ptr_sp))
207+ ptr_sp = GetFirstValueOfLibCXXCompressedPair (*ptr_sp);
208+
180209 if (!ptr_sp)
181210 return false ;
182211
@@ -363,13 +392,22 @@ lldb_private::formatters::LibcxxUniquePtrSyntheticFrontEnd::Update() {
363392
364393 // Retrieve the actual pointer and the deleter, and clone them to give them
365394 // user-friendly names.
366- ValueObjectSP value_pointer_sp = GetFirstValueOfLibCXXCompressedPair (*ptr_sp);
367- if (value_pointer_sp)
368- m_value_ptr_sp = value_pointer_sp->Clone (ConstString (" pointer" ));
395+ if (isOldCompressedPairLayout (*ptr_sp)) {
396+ if (ValueObjectSP value_pointer_sp =
397+ GetFirstValueOfLibCXXCompressedPair (*ptr_sp))
398+ m_value_ptr_sp = value_pointer_sp->Clone (ConstString (" pointer" ));
399+
400+ if (ValueObjectSP deleter_sp =
401+ GetSecondValueOfLibCXXCompressedPair (*ptr_sp))
402+ m_deleter_sp = deleter_sp->Clone (ConstString (" deleter" ));
403+ } else {
404+ m_value_ptr_sp = ptr_sp->Clone (ConstString (" pointer" ));
369405
370- ValueObjectSP deleter_sp = GetSecondValueOfLibCXXCompressedPair (*ptr_sp);
371- if (deleter_sp)
372- m_deleter_sp = deleter_sp->Clone (ConstString (" deleter" ));
406+ if (ValueObjectSP deleter_sp =
407+ valobj_sp->GetChildMemberWithName (" __deleter_" ))
408+ if (deleter_sp->GetNumChildrenIgnoringErrors () > 0 )
409+ m_deleter_sp = deleter_sp->Clone (ConstString (" deleter" ));
410+ }
373411
374412 return lldb::ChildCacheState::eRefetch;
375413}
@@ -407,24 +445,27 @@ namespace {
407445enum class StringLayout { CSD, DSC };
408446}
409447
448+ static ValueObjectSP ExtractLibCxxStringData (ValueObject &valobj) {
449+ if (auto rep_sp = valobj.GetChildMemberWithName (" __rep_" ))
450+ return rep_sp;
451+
452+ ValueObjectSP valobj_r_sp = valobj.GetChildMemberWithName (" __r_" );
453+ if (!valobj_r_sp || !valobj_r_sp->GetError ().Success ())
454+ return nullptr ;
455+
456+ if (!isOldCompressedPairLayout (*valobj_r_sp))
457+ return nullptr ;
458+
459+ return GetFirstValueOfLibCXXCompressedPair (*valobj_r_sp);
460+ }
461+
410462// / Determine the size in bytes of \p valobj (a libc++ std::string object) and
411463// / extract its data payload. Return the size + payload pair.
412464// TODO: Support big-endian architectures.
413465static std::optional<std::pair<uint64_t , ValueObjectSP>>
414466ExtractLibcxxStringInfo (ValueObject &valobj) {
415- ValueObjectSP valobj_r_sp = valobj.GetChildMemberWithName (" __r_" );
416- if (!valobj_r_sp || !valobj_r_sp->GetError ().Success ())
417- return {};
418-
419- // __r_ is a compressed_pair of the actual data and the allocator. The data we
420- // want is in the first base class.
421- ValueObjectSP valobj_r_base_sp = valobj_r_sp->GetChildAtIndex (0 );
422- if (!valobj_r_base_sp)
423- return {};
424-
425- ValueObjectSP valobj_rep_sp =
426- valobj_r_base_sp->GetChildMemberWithName (" __value_" );
427- if (!valobj_rep_sp)
467+ ValueObjectSP valobj_rep_sp = ExtractLibCxxStringData (valobj);
468+ if (!valobj_rep_sp || !valobj_rep_sp->GetError ().Success ())
428469 return {};
429470
430471 ValueObjectSP l = valobj_rep_sp->GetChildMemberWithName (" __l" );
0 commit comments