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