Fix an issue where libc++ changed the type information we get for std::map::iterator, rendering LLDB unable to display elements vended by an iterator

Fixes <rdar://problem/28237521>

llvm-svn: 282648
diff --git a/lldb/source/Plugins/Language/CPlusPlus/LibCxx.cpp b/lldb/source/Plugins/Language/CPlusPlus/LibCxx.cpp
index 74f4c5c..7303ae5 100644
--- a/lldb/source/Plugins/Language/CPlusPlus/LibCxx.cpp
+++ b/lldb/source/Plugins/Language/CPlusPlus/LibCxx.cpp
@@ -27,6 +27,7 @@
 #include "lldb/Host/Endian.h"
 #include "lldb/Symbol/ClangASTContext.h"
 #include "lldb/Target/Target.h"
+#include "lldb/Utility/ProcessStructReader.h"
 
 using namespace lldb;
 using namespace lldb_private;
@@ -247,12 +248,15 @@
 
 lldb_private::formatters::LibCxxMapIteratorSyntheticFrontEnd::
     LibCxxMapIteratorSyntheticFrontEnd(lldb::ValueObjectSP valobj_sp)
-    : SyntheticChildrenFrontEnd(*valobj_sp), m_pair_ptr() {
+    : SyntheticChildrenFrontEnd(*valobj_sp), m_pair_ptr(), m_pair_sp() {
   if (valobj_sp)
     Update();
 }
 
 bool lldb_private::formatters::LibCxxMapIteratorSyntheticFrontEnd::Update() {
+  m_pair_sp.reset();
+  m_pair_ptr = nullptr;
+
   ValueObjectSP valobj_sp = m_backend.GetSP();
   if (!valobj_sp)
     return false;
@@ -264,7 +268,9 @@
 
   if (!valobj_sp)
     return false;
-
+  
+  static ConstString g___i_("__i_");
+  
   // this must be a ValueObject* because it is a child of the ValueObject we are
   // producing children for
   // it if were a ValueObjectSP, we would end up with a loop (iterator ->
@@ -281,6 +287,57 @@
                                    SyntheticChildrenTraversal::None),
                        nullptr)
                    .get();
+  
+  if (!m_pair_ptr) {
+    m_pair_ptr = valobj_sp->GetValueForExpressionPath(".__i_.__ptr_", nullptr, nullptr, nullptr,
+                                                      ValueObject::GetValueForExpressionPathOptions()
+                                                      .DontCheckDotVsArrowSyntax()
+                                                      .SetSyntheticChildrenTraversal(
+                                                                                     ValueObject::GetValueForExpressionPathOptions::
+                                                                                     SyntheticChildrenTraversal::None),
+                                                      nullptr)
+    .get();
+    if (m_pair_ptr) {
+      auto __i_(valobj_sp->GetChildMemberWithName(g___i_, true));
+      lldb::TemplateArgumentKind kind;
+      if (!__i_) {
+        m_pair_ptr = nullptr;
+        return false;
+      }
+      CompilerType pair_type(__i_->GetCompilerType().GetTemplateArgument(0, kind));
+      std::string name; uint64_t bit_offset_ptr; uint32_t bitfield_bit_size_ptr; bool is_bitfield_ptr;
+      pair_type = pair_type.GetFieldAtIndex(0, name, &bit_offset_ptr, &bitfield_bit_size_ptr, &is_bitfield_ptr);
+      if (!pair_type) {
+        m_pair_ptr = nullptr;
+        return false;
+      }
+      
+      auto addr(m_pair_ptr->GetValueAsUnsigned(LLDB_INVALID_ADDRESS));
+      m_pair_ptr = nullptr;
+      if (addr && addr!=LLDB_INVALID_ADDRESS) {
+        ClangASTContext *ast_ctx = llvm::dyn_cast_or_null<ClangASTContext>(pair_type.GetTypeSystem());
+        if (!ast_ctx)
+          return false;
+        CompilerType tree_node_type = ast_ctx->CreateStructForIdentifier(ConstString(), {
+          {"ptr0",ast_ctx->GetBasicType(lldb::eBasicTypeVoid).GetPointerType()},
+          {"ptr1",ast_ctx->GetBasicType(lldb::eBasicTypeVoid).GetPointerType()},
+          {"ptr2",ast_ctx->GetBasicType(lldb::eBasicTypeVoid).GetPointerType()},
+          {"cw",ast_ctx->GetBasicType(lldb::eBasicTypeBool)},
+          {"payload",pair_type}
+        });
+        DataBufferSP buffer_sp(new DataBufferHeap(tree_node_type.GetByteSize(nullptr),0));
+        ProcessSP process_sp(target_sp->GetProcessSP());
+        Error error;
+        process_sp->ReadMemory(addr, buffer_sp->GetBytes(), buffer_sp->GetByteSize(), error);
+        if (error.Fail())
+          return false;
+        DataExtractor extractor(buffer_sp, process_sp->GetByteOrder(), process_sp->GetAddressByteSize());
+        auto pair_sp = CreateValueObjectFromData("pair", extractor, valobj_sp->GetExecutionContextRef(), tree_node_type);
+        if (pair_sp)
+          m_pair_sp = pair_sp->GetChildAtIndex(4,true);
+      }
+    }
+  }
 
   return false;
 }
@@ -293,9 +350,11 @@
 lldb::ValueObjectSP
 lldb_private::formatters::LibCxxMapIteratorSyntheticFrontEnd::GetChildAtIndex(
     size_t idx) {
-  if (!m_pair_ptr)
-    return lldb::ValueObjectSP();
-  return m_pair_ptr->GetChildAtIndex(idx, true);
+  if (m_pair_ptr)
+    return m_pair_ptr->GetChildAtIndex(idx, true);
+  if (m_pair_sp)
+    return m_pair_sp->GetChildAtIndex(idx, true);
+  return lldb::ValueObjectSP();
 }
 
 bool lldb_private::formatters::LibCxxMapIteratorSyntheticFrontEnd::