Move the C++ data formatters to the C++ language plugin

llvm-svn: 246873
diff --git a/lldb/source/Plugins/Language/CPlusPlus/CMakeLists.txt b/lldb/source/Plugins/Language/CPlusPlus/CMakeLists.txt
index 8b28b7d..0b0f0f4 100644
--- a/lldb/source/Plugins/Language/CPlusPlus/CMakeLists.txt
+++ b/lldb/source/Plugins/Language/CPlusPlus/CMakeLists.txt
@@ -1,3 +1,11 @@
 add_lldb_library(lldbPluginCPlusPlusLanguage
   CPlusPlusLanguage.cpp
+  CxxStringTypes.cpp
+  LibCxx.cpp
+  LibCxxInitializerList.cpp
+  LibCxxList.cpp
+  LibCxxMap.cpp
+  LibCxxUnorderedMap.cpp
+  LibCxxVector.cpp
+  LibStdcpp.cpp
 )
diff --git a/lldb/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.cpp b/lldb/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.cpp
index a69e3dc..923be58 100644
--- a/lldb/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.cpp
+++ b/lldb/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.cpp
@@ -17,9 +17,20 @@
 #include "lldb/Core/PluginManager.h"
 #include "lldb/Core/RegularExpression.h"
 #include "lldb/Core/UniqueCStringMap.h"
+#include "lldb/DataFormatters/DataVisualization.h"
+#include "lldb/DataFormatters/FormattersHelpers.h"
+
+#include "CXXFunctionPointer.h"
+#include "CxxStringTypes.h"
+#include "LibCxx.h"
+#include "LibStdcpp.h"
+
+#include <functional>
+#include <mutex>
 
 using namespace lldb;
 using namespace lldb_private;
+using namespace lldb_private::formatters;
 
 void
 CPlusPlusLanguage::Initialize()
@@ -438,3 +449,224 @@
     return count;
 }
 
+static void
+LoadLibCxxFormatters (lldb::TypeCategoryImplSP cpp_category_sp)
+{
+    if (!cpp_category_sp)
+        return;
+    
+    TypeSummaryImpl::Flags stl_summary_flags;
+    stl_summary_flags.SetCascades(true)
+    .SetSkipPointers(false)
+    .SetSkipReferences(false)
+    .SetDontShowChildren(true)
+    .SetDontShowValue(true)
+    .SetShowMembersOneLiner(false)
+    .SetHideItemNames(false);
+    
+#ifndef LLDB_DISABLE_PYTHON
+    lldb::TypeSummaryImplSP std_string_summary_sp(new CXXFunctionSummaryFormat(stl_summary_flags, lldb_private::formatters::LibcxxStringSummaryProvider, "std::string summary provider"));
+    lldb::TypeSummaryImplSP std_wstring_summary_sp(new CXXFunctionSummaryFormat(stl_summary_flags, lldb_private::formatters::LibcxxWStringSummaryProvider, "std::wstring summary provider"));
+    
+    cpp_category_sp->GetTypeSummariesContainer()->Add(ConstString("std::__1::string"),
+                                                         std_string_summary_sp);
+    cpp_category_sp->GetTypeSummariesContainer()->Add(ConstString("std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >"),
+                                                         std_string_summary_sp);
+    
+    cpp_category_sp->GetTypeSummariesContainer()->Add(ConstString("std::__1::wstring"),
+                                                         std_wstring_summary_sp);
+    cpp_category_sp->GetTypeSummariesContainer()->Add(ConstString("std::__1::basic_string<wchar_t, std::__1::char_traits<wchar_t>, std::__1::allocator<wchar_t> >"),
+                                                         std_wstring_summary_sp);
+    
+    SyntheticChildren::Flags stl_synth_flags;
+    stl_synth_flags.SetCascades(true).SetSkipPointers(false).SetSkipReferences(false);
+    
+    AddCXXSynthetic(cpp_category_sp, lldb_private::formatters::LibcxxStdVectorSyntheticFrontEndCreator, "libc++ std::vector synthetic children", ConstString("^std::__1::vector<.+>(( )?&)?$"), stl_synth_flags, true);
+    AddCXXSynthetic(cpp_category_sp, lldb_private::formatters::LibcxxStdListSyntheticFrontEndCreator, "libc++ std::list synthetic children", ConstString("^std::__1::list<.+>(( )?&)?$"), stl_synth_flags, true);
+    AddCXXSynthetic(cpp_category_sp, lldb_private::formatters::LibcxxStdMapSyntheticFrontEndCreator, "libc++ std::map synthetic children", ConstString("^std::__1::map<.+> >(( )?&)?$"), stl_synth_flags, true);
+    AddCXXSynthetic(cpp_category_sp, lldb_private::formatters::LibcxxVectorBoolSyntheticFrontEndCreator, "libc++ std::vector<bool> synthetic children", ConstString("std::__1::vector<std::__1::allocator<bool> >"), stl_synth_flags);
+    AddCXXSynthetic(cpp_category_sp, lldb_private::formatters::LibcxxVectorBoolSyntheticFrontEndCreator, "libc++ std::vector<bool> synthetic children", ConstString("std::__1::vector<bool, std::__1::allocator<bool> >"), stl_synth_flags);
+    AddCXXSynthetic(cpp_category_sp, lldb_private::formatters::LibcxxStdMapSyntheticFrontEndCreator, "libc++ std::set synthetic children", ConstString("^std::__1::set<.+> >(( )?&)?$"), stl_synth_flags, true);
+    AddCXXSynthetic(cpp_category_sp, lldb_private::formatters::LibcxxStdMapSyntheticFrontEndCreator, "libc++ std::multiset synthetic children", ConstString("^std::__1::multiset<.+> >(( )?&)?$"), stl_synth_flags, true);
+    AddCXXSynthetic(cpp_category_sp, lldb_private::formatters::LibcxxStdMapSyntheticFrontEndCreator, "libc++ std::multimap synthetic children", ConstString("^std::__1::multimap<.+> >(( )?&)?$"), stl_synth_flags, true);
+    AddCXXSynthetic(cpp_category_sp, lldb_private::formatters::LibcxxStdUnorderedMapSyntheticFrontEndCreator, "libc++ std::unordered containers synthetic children", ConstString("^(std::__1::)unordered_(multi)?(map|set)<.+> >$"), stl_synth_flags, true);
+    AddCXXSynthetic(cpp_category_sp, lldb_private::formatters::LibcxxInitializerListSyntheticFrontEndCreator, "libc++ std::initializer_list synthetic children", ConstString("^std::initializer_list<.+>(( )?&)?$"), stl_synth_flags, true);
+    
+    cpp_category_sp->GetRegexTypeSyntheticsContainer()->Add(RegularExpressionSP(new RegularExpression("^(std::__1::)deque<.+>(( )?&)?$")),
+                                                               SyntheticChildrenSP(new ScriptedSyntheticChildren(stl_synth_flags,
+                                                                                                                 "lldb.formatters.cpp.libcxx.stddeque_SynthProvider")));
+    
+    AddCXXSynthetic(cpp_category_sp, lldb_private::formatters::LibcxxSharedPtrSyntheticFrontEndCreator, "shared_ptr synthetic children", ConstString("^(std::__1::)shared_ptr<.+>(( )?&)?$"), stl_synth_flags, true);
+    AddCXXSynthetic(cpp_category_sp, lldb_private::formatters::LibcxxSharedPtrSyntheticFrontEndCreator, "weak_ptr synthetic children", ConstString("^(std::__1::)weak_ptr<.+>(( )?&)?$"), stl_synth_flags, true);
+    
+    stl_summary_flags.SetDontShowChildren(false);stl_summary_flags.SetSkipPointers(false);
+    AddCXXSynthetic(cpp_category_sp, lldb_private::formatters::LibcxxVectorBoolSyntheticFrontEndCreator, "libc++ std::vector<bool> synthetic children", ConstString("std::__1::vector<bool, std::__1::allocator<bool> >"), stl_synth_flags);
+    
+    AddCXXSummary(cpp_category_sp, lldb_private::formatters::LibcxxContainerSummaryProvider, "libc++ std::vector summary provider", ConstString("^std::__1::vector<.+>(( )?&)?$"), stl_summary_flags, true);
+    AddCXXSummary(cpp_category_sp, lldb_private::formatters::LibcxxContainerSummaryProvider, "libc++ std::list summary provider", ConstString("^std::__1::list<.+>(( )?&)?$"), stl_summary_flags, true);
+    AddCXXSummary(cpp_category_sp, lldb_private::formatters::LibcxxContainerSummaryProvider, "libc++ std::map summary provider", ConstString("^std::__1::map<.+>(( )?&)?$"), stl_summary_flags, true);
+    AddCXXSummary(cpp_category_sp, lldb_private::formatters::LibcxxContainerSummaryProvider, "libc++ std::deque summary provider", ConstString("^std::__1::deque<.+>(( )?&)?$"), stl_summary_flags, true);
+    AddCXXSummary(cpp_category_sp, lldb_private::formatters::LibcxxContainerSummaryProvider, "libc++ std::vector<bool> summary provider", ConstString("std::__1::vector<std::__1::allocator<bool> >"), stl_summary_flags);
+    AddCXXSummary(cpp_category_sp, lldb_private::formatters::LibcxxContainerSummaryProvider, "libc++ std::vector<bool> summary provider", ConstString("std::__1::vector<bool, std::__1::allocator<bool> >"), stl_summary_flags);
+    AddCXXSummary(cpp_category_sp, lldb_private::formatters::LibcxxContainerSummaryProvider, "libc++ std::set summary provider", ConstString("^std::__1::set<.+>(( )?&)?$"), stl_summary_flags, true);
+    AddCXXSummary(cpp_category_sp, lldb_private::formatters::LibcxxContainerSummaryProvider, "libc++ std::multiset summary provider", ConstString("^std::__1::multiset<.+>(( )?&)?$"), stl_summary_flags, true);
+    AddCXXSummary(cpp_category_sp, lldb_private::formatters::LibcxxContainerSummaryProvider, "libc++ std::multimap summary provider", ConstString("^std::__1::multimap<.+>(( )?&)?$"), stl_summary_flags, true);
+    AddCXXSummary(cpp_category_sp, lldb_private::formatters::LibcxxContainerSummaryProvider, "libc++ std::unordered containers summary provider", ConstString("^(std::__1::)unordered_(multi)?(map|set)<.+> >$"), stl_summary_flags, true);
+    
+    stl_summary_flags.SetSkipPointers(true);
+    
+    AddCXXSummary(cpp_category_sp, lldb_private::formatters::LibcxxSmartPointerSummaryProvider, "libc++ std::shared_ptr summary provider", ConstString("^std::__1::shared_ptr<.+>(( )?&)?$"), stl_summary_flags, true);
+    AddCXXSummary(cpp_category_sp, lldb_private::formatters::LibcxxSmartPointerSummaryProvider, "libc++ std::weak_ptr summary provider", ConstString("^std::__1::weak_ptr<.+>(( )?&)?$"), stl_summary_flags, true);
+    
+    AddCXXSynthetic(cpp_category_sp, lldb_private::formatters::LibCxxVectorIteratorSyntheticFrontEndCreator, "std::vector iterator synthetic children", ConstString("^std::__1::__wrap_iter<.+>$"), stl_synth_flags, true);
+    
+    AddCXXSummary(cpp_category_sp, lldb_private::formatters::LibcxxContainerSummaryProvider, "libc++ std::vector<bool> summary provider", ConstString("std::__1::vector<bool, std::__1::allocator<bool> >"), stl_summary_flags);
+    AddCXXSynthetic(cpp_category_sp, lldb_private::formatters::LibCxxMapIteratorSyntheticFrontEndCreator, "std::map iterator synthetic children", ConstString("^std::__1::__map_iterator<.+>$"), stl_synth_flags, true);
+    
+    AddFilter(cpp_category_sp, {"__a_"}, "libc++ std::atomic filter", ConstString("^std::__1::atomic<.*>$"), stl_synth_flags, true);
+#endif
+}
+
+static void
+LoadLibStdcppFormatters(lldb::TypeCategoryImplSP cpp_category_sp)
+{
+    if (!cpp_category_sp)
+        return;
+    
+    TypeSummaryImpl::Flags stl_summary_flags;
+    stl_summary_flags.SetCascades(true)
+    .SetSkipPointers(false)
+    .SetSkipReferences(false)
+    .SetDontShowChildren(true)
+    .SetDontShowValue(true)
+    .SetShowMembersOneLiner(false)
+    .SetHideItemNames(false);
+    
+    lldb::TypeSummaryImplSP std_string_summary_sp(new StringSummaryFormat(stl_summary_flags,
+                                                                          "${var._M_dataplus._M_p}"));
+    
+    cpp_category_sp->GetTypeSummariesContainer()->Add(ConstString("std::string"),
+                                                      std_string_summary_sp);
+    cpp_category_sp->GetTypeSummariesContainer()->Add(ConstString("std::basic_string<char>"),
+                                                      std_string_summary_sp);
+    cpp_category_sp->GetTypeSummariesContainer()->Add(ConstString("std::basic_string<char,std::char_traits<char>,std::allocator<char> >"),
+                                                      std_string_summary_sp);
+    cpp_category_sp->GetTypeSummariesContainer()->Add(ConstString("std::basic_string<char, std::char_traits<char>, std::allocator<char> >"),
+                                                      std_string_summary_sp);
+    
+    // making sure we force-pick the summary for printing wstring (_M_p is a wchar_t*)
+    lldb::TypeSummaryImplSP std_wstring_summary_sp(new StringSummaryFormat(stl_summary_flags,
+                                                                           "${var._M_dataplus._M_p%S}"));
+    
+    cpp_category_sp->GetTypeSummariesContainer()->Add(ConstString("std::wstring"),
+                                                      std_wstring_summary_sp);
+    cpp_category_sp->GetTypeSummariesContainer()->Add(ConstString("std::basic_string<wchar_t>"),
+                                                      std_wstring_summary_sp);
+    cpp_category_sp->GetTypeSummariesContainer()->Add(ConstString("std::basic_string<wchar_t,std::char_traits<wchar_t>,std::allocator<wchar_t> >"),
+                                                      std_wstring_summary_sp);
+    cpp_category_sp->GetTypeSummariesContainer()->Add(ConstString("std::basic_string<wchar_t, std::char_traits<wchar_t>, std::allocator<wchar_t> >"),
+                                                      std_wstring_summary_sp);
+    
+    
+#ifndef LLDB_DISABLE_PYTHON
+    
+    SyntheticChildren::Flags stl_synth_flags;
+    stl_synth_flags.SetCascades(true).SetSkipPointers(false).SetSkipReferences(false);
+    
+    cpp_category_sp->GetRegexTypeSyntheticsContainer()->Add(RegularExpressionSP(new RegularExpression("^std::vector<.+>(( )?&)?$")),
+                                                            SyntheticChildrenSP(new ScriptedSyntheticChildren(stl_synth_flags,
+                                                                                                              "lldb.formatters.cpp.gnu_libstdcpp.StdVectorSynthProvider")));
+    cpp_category_sp->GetRegexTypeSyntheticsContainer()->Add(RegularExpressionSP(new RegularExpression("^std::map<.+> >(( )?&)?$")),
+                                                            SyntheticChildrenSP(new ScriptedSyntheticChildren(stl_synth_flags,
+                                                                                                              "lldb.formatters.cpp.gnu_libstdcpp.StdMapSynthProvider")));
+    cpp_category_sp->GetRegexTypeSyntheticsContainer()->Add(RegularExpressionSP(new RegularExpression("^std::list<.+>(( )?&)?$")),
+                                                            SyntheticChildrenSP(new ScriptedSyntheticChildren(stl_synth_flags,
+                                                                                                              "lldb.formatters.cpp.gnu_libstdcpp.StdListSynthProvider")));
+    
+    stl_summary_flags.SetDontShowChildren(false);stl_summary_flags.SetSkipPointers(true);
+    cpp_category_sp->GetRegexTypeSummariesContainer()->Add(RegularExpressionSP(new RegularExpression("^std::vector<.+>(( )?&)?$")),
+                                                           TypeSummaryImplSP(new StringSummaryFormat(stl_summary_flags,
+                                                                                                     "size=${svar%#}")));
+    cpp_category_sp->GetRegexTypeSummariesContainer()->Add(RegularExpressionSP(new RegularExpression("^std::map<.+> >(( )?&)?$")),
+                                                           TypeSummaryImplSP(new StringSummaryFormat(stl_summary_flags,
+                                                                                                     "size=${svar%#}")));
+    cpp_category_sp->GetRegexTypeSummariesContainer()->Add(RegularExpressionSP(new RegularExpression("^std::list<.+>(( )?&)?$")),
+                                                           TypeSummaryImplSP(new StringSummaryFormat(stl_summary_flags,
+                                                                                                     "size=${svar%#}")));
+    
+    AddCXXSynthetic(cpp_category_sp, lldb_private::formatters::LibStdcppVectorIteratorSyntheticFrontEndCreator, "std::vector iterator synthetic children", ConstString("^__gnu_cxx::__normal_iterator<.+>$"), stl_synth_flags, true);
+    
+    AddCXXSynthetic(cpp_category_sp, lldb_private::formatters::LibstdcppMapIteratorSyntheticFrontEndCreator, "std::map iterator synthetic children", ConstString("^std::_Rb_tree_iterator<.+>$"), stl_synth_flags, true);
+#endif
+}
+
+static void
+LoadSystemFormatters(lldb::TypeCategoryImplSP cpp_category_sp)
+{
+    if (!cpp_category_sp)
+        return;
+    
+    TypeSummaryImpl::Flags string_flags;
+    string_flags.SetCascades(true)
+    .SetSkipPointers(true)
+    .SetSkipReferences(false)
+    .SetDontShowChildren(true)
+    .SetDontShowValue(false)
+    .SetShowMembersOneLiner(false)
+    .SetHideItemNames(false);
+    
+    TypeSummaryImpl::Flags string_array_flags;
+    string_array_flags.SetCascades(true)
+    .SetSkipPointers(true)
+    .SetSkipReferences(false)
+    .SetDontShowChildren(true)
+    .SetDontShowValue(true)
+    .SetShowMembersOneLiner(false)
+    .SetHideItemNames(false);
+    
+#ifndef LLDB_DISABLE_PYTHON
+    // FIXME because of a bug in the FormattersContainer we need to add a summary for both X* and const X* (<rdar://problem/12717717>)
+    AddCXXSummary(cpp_category_sp, lldb_private::formatters::Char16StringSummaryProvider, "char16_t * summary provider", ConstString("char16_t *"), string_flags);
+    
+    AddCXXSummary(cpp_category_sp, lldb_private::formatters::Char32StringSummaryProvider, "char32_t * summary provider", ConstString("char32_t *"), string_flags);
+    
+    AddCXXSummary(cpp_category_sp, lldb_private::formatters::WCharStringSummaryProvider, "wchar_t * summary provider", ConstString("wchar_t *"), string_flags);
+    AddCXXSummary(cpp_category_sp, lldb_private::formatters::WCharStringSummaryProvider, "wchar_t * summary provider", ConstString("wchar_t \\[[0-9]+\\]"), string_array_flags, true);
+    
+    AddCXXSummary(cpp_category_sp, lldb_private::formatters::Char16StringSummaryProvider, "unichar * summary provider", ConstString("unichar *"), string_flags);
+    
+    TypeSummaryImpl::Flags widechar_flags;
+    widechar_flags.SetDontShowValue(true)
+    .SetSkipPointers(true)
+    .SetSkipReferences(false)
+    .SetCascades(true)
+    .SetDontShowChildren(true)
+    .SetHideItemNames(true)
+    .SetShowMembersOneLiner(false);
+    
+    AddCXXSummary(cpp_category_sp, lldb_private::formatters::Char16SummaryProvider, "char16_t summary provider", ConstString("char16_t"), widechar_flags);
+    AddCXXSummary(cpp_category_sp, lldb_private::formatters::Char32SummaryProvider, "char32_t summary provider", ConstString("char32_t"), widechar_flags);
+    AddCXXSummary(cpp_category_sp, lldb_private::formatters::WCharSummaryProvider, "wchar_t summary provider", ConstString("wchar_t"), widechar_flags);
+    
+    AddCXXSummary(cpp_category_sp, lldb_private::formatters::Char16SummaryProvider, "unichar summary provider", ConstString("unichar"), widechar_flags);
+#endif
+}
+
+lldb::TypeCategoryImplSP
+CPlusPlusLanguage::GetFormatters ()
+{
+    static std::once_flag g_initialize;
+    static TypeCategoryImplSP g_category;
+    
+    std::call_once(g_initialize, [this] () -> void {
+        DataVisualization::Categories::GetCategory(GetPluginName(), g_category);
+        if (g_category)
+        {
+            LoadLibCxxFormatters(g_category);
+            LoadLibStdcppFormatters(g_category);
+            LoadSystemFormatters(g_category);
+        }
+    });
+    return g_category;
+}
+
diff --git a/lldb/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.h b/lldb/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.h
index 2ede8d8..1dba19b 100644
--- a/lldb/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.h
+++ b/lldb/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.h
@@ -121,11 +121,14 @@
     CPlusPlusLanguage () = default;
     
     lldb::LanguageType
-    GetLanguageType () const
+    GetLanguageType () const override
     {
         return lldb::eLanguageTypeC_plus_plus;
     }
     
+    lldb::TypeCategoryImplSP
+    GetFormatters () override;
+    
     //------------------------------------------------------------------
     // Static Functions
     //------------------------------------------------------------------
@@ -167,10 +170,10 @@
     // PluginInterface protocol
     //------------------------------------------------------------------
     virtual ConstString
-    GetPluginName();
+    GetPluginName() override;
     
     virtual uint32_t
-    GetPluginVersion();
+    GetPluginVersion() override;
 };
     
 } // namespace lldb_private
diff --git a/lldb/source/Plugins/Language/CPlusPlus/CxxStringTypes.cpp b/lldb/source/Plugins/Language/CPlusPlus/CxxStringTypes.cpp
new file mode 100644
index 0000000..6607043
--- /dev/null
+++ b/lldb/source/Plugins/Language/CPlusPlus/CxxStringTypes.cpp
@@ -0,0 +1,211 @@
+//===-- CXXStringTypes.cpp --------------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "CxxStringTypes.h"
+
+#include "llvm/Support/ConvertUTF.h"
+
+#include "lldb/Core/DataBufferHeap.h"
+#include "lldb/Core/Error.h"
+#include "lldb/Core/Stream.h"
+#include "lldb/Core/ValueObject.h"
+#include "lldb/Core/ValueObjectConstResult.h"
+#include "lldb/DataFormatters/StringPrinter.h"
+#include "lldb/DataFormatters/TypeSummary.h"
+#include "lldb/Host/Endian.h"
+#include "lldb/Symbol/ClangASTContext.h"
+#include "lldb/Target/SectionLoadList.h"
+#include "lldb/Target/Target.h"
+#include "lldb/Target/Thread.h"
+#include "lldb/Utility/ProcessStructReader.h"
+
+#include <algorithm>
+
+#if __ANDROID_NDK__
+#include <sys/types.h>
+#endif
+
+#include "lldb/Host/Time.h"
+
+using namespace lldb;
+using namespace lldb_private;
+using namespace lldb_private::formatters;
+
+bool
+lldb_private::formatters::Char16StringSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions&)
+{
+    ProcessSP process_sp = valobj.GetProcessSP();
+    if (!process_sp)
+        return false;
+    
+    lldb::addr_t valobj_addr = valobj.GetValueAsUnsigned(0);
+    
+    if (!valobj_addr)
+        return false;
+    
+    ReadStringAndDumpToStreamOptions options(valobj);
+    options.SetLocation(valobj_addr);
+    options.SetProcessSP(process_sp);
+    options.SetStream(&stream);
+    options.SetPrefixToken('u');
+    
+    if (!ReadStringAndDumpToStream<StringElementType::UTF16>(options))
+    {
+        stream.Printf("Summary Unavailable");
+        return true;
+    }
+    
+    return true;
+}
+
+bool
+lldb_private::formatters::Char32StringSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions&)
+{
+    ProcessSP process_sp = valobj.GetProcessSP();
+    if (!process_sp)
+        return false;
+    
+    lldb::addr_t valobj_addr = valobj.GetValueAsUnsigned(0);
+    
+    if (!valobj_addr)
+        return false;
+    
+    ReadStringAndDumpToStreamOptions options(valobj);
+    options.SetLocation(valobj_addr);
+    options.SetProcessSP(process_sp);
+    options.SetStream(&stream);
+    options.SetPrefixToken('U');
+    
+    if (!ReadStringAndDumpToStream<StringElementType::UTF32>(options))
+    {
+        stream.Printf("Summary Unavailable");
+        return true;
+    }
+    
+    return true;
+}
+
+bool
+lldb_private::formatters::WCharStringSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions&)
+{
+    ProcessSP process_sp = valobj.GetProcessSP();
+    if (!process_sp)
+        return false;
+    
+    lldb::addr_t data_addr = 0;
+    
+    if (valobj.IsPointerType())
+        data_addr = valobj.GetValueAsUnsigned(0);
+    else if (valobj.IsArrayType())
+        data_addr = valobj.GetAddressOf();
+    
+    if (data_addr == 0 || data_addr == LLDB_INVALID_ADDRESS)
+        return false;
+    
+    // Get a wchar_t basic type from the current type system
+    CompilerType wchar_clang_type = valobj.GetCompilerType().GetBasicTypeFromAST(lldb::eBasicTypeWChar);
+    
+    if (!wchar_clang_type)
+        return false;
+    
+    const uint32_t wchar_size = wchar_clang_type.GetBitSize(nullptr); // Safe to pass NULL for exe_scope here
+    
+    ReadStringAndDumpToStreamOptions options(valobj);
+    options.SetLocation(data_addr);
+    options.SetProcessSP(process_sp);
+    options.SetStream(&stream);
+    options.SetPrefixToken('L');
+    
+    switch (wchar_size)
+    {
+        case 8:
+            return ReadStringAndDumpToStream<StringElementType::UTF8>(options);
+        case 16:
+            return ReadStringAndDumpToStream<StringElementType::UTF16>(options);
+        case 32:
+            return ReadStringAndDumpToStream<StringElementType::UTF32>(options);
+        default:
+            stream.Printf("size for wchar_t is not valid");
+            return true;
+    }
+    return true;
+}
+
+bool
+lldb_private::formatters::Char16SummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions&)
+{
+    DataExtractor data;
+    Error error;
+    valobj.GetData(data, error);
+    
+    if (error.Fail())
+        return false;
+    
+    std::string value;
+    valobj.GetValueAsCString(lldb::eFormatUnicode16, value);
+    if (!value.empty())
+        stream.Printf("%s ", value.c_str());
+    
+    ReadBufferAndDumpToStreamOptions options(valobj);
+    options.SetData(data);
+    options.SetStream(&stream);
+    options.SetPrefixToken('u');
+    options.SetQuote('\'');
+    options.SetSourceSize(1);
+    options.SetBinaryZeroIsTerminator(false);
+    
+    return ReadBufferAndDumpToStream<StringElementType::UTF16>(options);
+}
+
+bool
+lldb_private::formatters::Char32SummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions&)
+{
+    DataExtractor data;
+    Error error;
+    valobj.GetData(data, error);
+    
+    if (error.Fail())
+        return false;
+    
+    std::string value;
+    valobj.GetValueAsCString(lldb::eFormatUnicode32, value);
+    if (!value.empty())
+        stream.Printf("%s ", value.c_str());
+    
+    ReadBufferAndDumpToStreamOptions options(valobj);
+    options.SetData(data);
+    options.SetStream(&stream);
+    options.SetPrefixToken('U');
+    options.SetQuote('\'');
+    options.SetSourceSize(1);
+    options.SetBinaryZeroIsTerminator(false);
+    
+    return ReadBufferAndDumpToStream<StringElementType::UTF32>(options);
+}
+
+bool
+lldb_private::formatters::WCharSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions&)
+{
+    DataExtractor data;
+    Error error;
+    valobj.GetData(data, error);
+    
+    if (error.Fail())
+        return false;
+    
+    ReadBufferAndDumpToStreamOptions options(valobj);
+    options.SetData(data);
+    options.SetStream(&stream);
+    options.SetPrefixToken('L');
+    options.SetQuote('\'');
+    options.SetSourceSize(1);
+    options.SetBinaryZeroIsTerminator(false);
+    
+    return ReadBufferAndDumpToStream<StringElementType::UTF16>(options);
+}
diff --git a/lldb/source/Plugins/Language/CPlusPlus/CxxStringTypes.h b/lldb/source/Plugins/Language/CPlusPlus/CxxStringTypes.h
new file mode 100644
index 0000000..bfb03bd
--- /dev/null
+++ b/lldb/source/Plugins/Language/CPlusPlus/CxxStringTypes.h
@@ -0,0 +1,41 @@
+//===-- CxxStringTypes.h ----------------------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef liblldb_CxxStringTypes_h_
+#define liblldb_CxxStringTypes_h_
+
+#include "lldb/Core/Stream.h"
+#include "lldb/Core/ValueObject.h"
+#include "lldb/DataFormatters/TypeSummary.h"
+
+namespace lldb_private {
+    namespace formatters
+    {
+        bool
+        Char16StringSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options); // char16_t* and unichar*
+        
+        bool
+        Char32StringSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options); // char32_t*
+        
+        bool
+        WCharStringSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options); // wchar_t*
+        
+        bool
+        Char16SummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options); // char16_t and unichar
+        
+        bool
+        Char32SummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options); // char32_t
+        
+        bool
+        WCharSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options); // wchar_t
+        
+    } // namespace formatters
+} // namespace lldb_private
+
+#endif // liblldb_CxxStringTypes_h_
diff --git a/lldb/source/Plugins/Language/CPlusPlus/LibCxx.cpp b/lldb/source/Plugins/Language/CPlusPlus/LibCxx.cpp
new file mode 100644
index 0000000..392e812
--- /dev/null
+++ b/lldb/source/Plugins/Language/CPlusPlus/LibCxx.cpp
@@ -0,0 +1,636 @@
+//===-- LibCxx.cpp ----------------------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "LibCxx.h"
+
+#include "lldb/Core/DataBufferHeap.h"
+#include "lldb/Core/Debugger.h"
+#include "lldb/Core/Error.h"
+#include "lldb/Core/FormatEntity.h"
+#include "lldb/Core/Stream.h"
+#include "lldb/Core/ValueObject.h"
+#include "lldb/Core/ValueObjectConstResult.h"
+#include "lldb/DataFormatters/FormattersHelpers.h"
+#include "lldb/DataFormatters/StringPrinter.h"
+#include "lldb/DataFormatters/TypeSummary.h"
+#include "lldb/DataFormatters/VectorIterator.h"
+#include "lldb/Host/Endian.h"
+#include "lldb/Symbol/ClangASTContext.h"
+#include "lldb/Target/Target.h"
+
+using namespace lldb;
+using namespace lldb_private;
+using namespace lldb_private::formatters;
+
+bool
+lldb_private::formatters::LibcxxSmartPointerSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options)
+{
+    ValueObjectSP valobj_sp(valobj.GetNonSyntheticValue());
+    if (!valobj_sp)
+        return false;
+    ValueObjectSP ptr_sp(valobj_sp->GetChildMemberWithName(ConstString("__ptr_"), true));
+    ValueObjectSP count_sp(valobj_sp->GetChildAtNamePath( {ConstString("__cntrl_"),ConstString("__shared_owners_")} ));
+    ValueObjectSP weakcount_sp(valobj_sp->GetChildAtNamePath( {ConstString("__cntrl_"),ConstString("__shared_weak_owners_")} ));
+    
+    if (!ptr_sp)
+        return false;
+    
+    if (ptr_sp->GetValueAsUnsigned(0) == 0)
+    {
+        stream.Printf("nullptr");
+        return true;
+    }
+    else
+    {
+        bool print_pointee = false;
+        Error error;
+        ValueObjectSP pointee_sp = ptr_sp->Dereference(error);
+        if (pointee_sp && error.Success())
+        {
+            if (pointee_sp->DumpPrintableRepresentation(stream,
+                                                        ValueObject::eValueObjectRepresentationStyleSummary,
+                                                        lldb::eFormatInvalid,
+                                                        ValueObject::ePrintableRepresentationSpecialCasesDisable,
+                                                        false))
+                print_pointee = true;
+        }
+        if (!print_pointee)
+            stream.Printf("ptr = 0x%" PRIx64, ptr_sp->GetValueAsUnsigned(0));
+    }
+    
+    if (count_sp)
+        stream.Printf(" strong=%" PRIu64, 1+count_sp->GetValueAsUnsigned(0));
+
+    if (weakcount_sp)
+        stream.Printf(" weak=%" PRIu64, 1+weakcount_sp->GetValueAsUnsigned(0));
+    
+    return true;
+}
+
+lldb_private::formatters::LibcxxVectorBoolSyntheticFrontEnd::LibcxxVectorBoolSyntheticFrontEnd (lldb::ValueObjectSP valobj_sp) :
+SyntheticChildrenFrontEnd(*valobj_sp.get()),
+m_bool_type(),
+m_exe_ctx_ref(),
+m_count(0),
+m_base_data_address(0),
+m_children()
+{
+    if (valobj_sp)
+    {
+        Update();
+        m_bool_type = valobj_sp->GetCompilerType().GetBasicTypeFromAST(lldb::eBasicTypeBool);
+    }
+}
+
+size_t
+lldb_private::formatters::LibcxxVectorBoolSyntheticFrontEnd::CalculateNumChildren ()
+{
+    return m_count;
+}
+
+lldb::ValueObjectSP
+lldb_private::formatters::LibcxxVectorBoolSyntheticFrontEnd::GetChildAtIndex (size_t idx)
+{
+    auto iter = m_children.find(idx),
+        end = m_children.end();
+    if (iter != end)
+        return iter->second;
+    if (idx >= m_count)
+        return ValueObjectSP();
+    if (m_base_data_address == 0 || m_count == 0)
+        return ValueObjectSP();
+    if (!m_bool_type)
+        return ValueObjectSP();
+    size_t byte_idx = (idx >> 3); // divide by 8 to get byte index
+    size_t bit_index = (idx & 7); // efficient idx % 8 for bit index
+    lldb::addr_t byte_location = m_base_data_address + byte_idx;
+    ProcessSP process_sp(m_exe_ctx_ref.GetProcessSP());
+    if (!process_sp)
+        return ValueObjectSP();
+    uint8_t byte = 0;
+    uint8_t mask = 0;
+    Error err;
+    size_t bytes_read = process_sp->ReadMemory(byte_location, &byte, 1, err);
+    if (err.Fail() || bytes_read == 0)
+        return ValueObjectSP();
+    switch (bit_index)
+    {
+        case 0:
+            mask = 1; break;
+        case 1:
+            mask = 2; break;
+        case 2:
+            mask = 4; break;
+        case 3:
+            mask = 8; break;
+        case 4:
+            mask = 16; break;
+        case 5:
+            mask = 32; break;
+        case 6:
+            mask = 64; break;
+        case 7:
+            mask = 128; break;
+        default:
+            return ValueObjectSP();
+    }
+    bool bit_set = ((byte & mask) != 0);
+    DataBufferSP buffer_sp(new DataBufferHeap(m_bool_type.GetByteSize(nullptr),0));
+    if (bit_set && buffer_sp && buffer_sp->GetBytes())
+        *(buffer_sp->GetBytes()) = 1; // regardless of endianness, anything non-zero is true
+    StreamString name; name.Printf("[%" PRIu64 "]", (uint64_t)idx);
+    ValueObjectSP retval_sp(CreateValueObjectFromData(name.GetData(), DataExtractor(buffer_sp, process_sp->GetByteOrder(), process_sp->GetAddressByteSize()), m_exe_ctx_ref, m_bool_type));
+    if (retval_sp)
+        m_children[idx] = retval_sp;
+    return retval_sp;
+}
+
+/*(std::__1::vector<std::__1::allocator<bool> >) vBool = {
+ __begin_ = 0x00000001001000e0
+ __size_ = 56
+ __cap_alloc_ = {
+ std::__1::__libcpp_compressed_pair_imp<unsigned long, std::__1::allocator<unsigned long> > = {
+ __first_ = 1
+ }
+ }
+ }*/
+
+bool
+lldb_private::formatters::LibcxxVectorBoolSyntheticFrontEnd::Update()
+{
+    m_children.clear();
+    ValueObjectSP valobj_sp = m_backend.GetSP();
+    if (!valobj_sp)
+        return false;
+    m_exe_ctx_ref = valobj_sp->GetExecutionContextRef();
+    ValueObjectSP size_sp(valobj_sp->GetChildMemberWithName(ConstString("__size_"), true));
+    if (!size_sp)
+        return false;
+    m_count = size_sp->GetValueAsUnsigned(0);
+    if (!m_count)
+        return true;
+    ValueObjectSP begin_sp(valobj_sp->GetChildMemberWithName(ConstString("__begin_"), true));
+    if (!begin_sp)
+    {
+        m_count = 0;
+        return false;
+    }
+    m_base_data_address = begin_sp->GetValueAsUnsigned(0);
+    if (!m_base_data_address)
+    {
+        m_count = 0;
+        return false;
+    }
+    return false;
+}
+
+bool
+lldb_private::formatters::LibcxxVectorBoolSyntheticFrontEnd::MightHaveChildren ()
+{
+    return true;
+}
+
+size_t
+lldb_private::formatters::LibcxxVectorBoolSyntheticFrontEnd::GetIndexOfChildWithName (const ConstString &name)
+{
+    if (!m_count || !m_base_data_address)
+        return UINT32_MAX;
+    const char* item_name = name.GetCString();
+    uint32_t idx = ExtractIndexFromString(item_name);
+    if (idx < UINT32_MAX && idx >= CalculateNumChildren())
+        return UINT32_MAX;
+    return idx;
+}
+
+lldb_private::formatters::LibcxxVectorBoolSyntheticFrontEnd::~LibcxxVectorBoolSyntheticFrontEnd ()
+{}
+
+SyntheticChildrenFrontEnd*
+lldb_private::formatters::LibcxxVectorBoolSyntheticFrontEndCreator (CXXSyntheticChildren*, lldb::ValueObjectSP valobj_sp)
+{
+    if (!valobj_sp)
+        return NULL;
+    return (new LibcxxVectorBoolSyntheticFrontEnd(valobj_sp));
+}
+
+/*
+ (lldb) fr var ibeg --raw --ptr-depth 1
+ (std::__1::__map_iterator<std::__1::__tree_iterator<std::__1::pair<int, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > >, std::__1::__tree_node<std::__1::pair<int, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > >, void *> *, long> >) ibeg = {
+ __i_ = {
+ __ptr_ = 0x0000000100103870 {
+ std::__1::__tree_node_base<void *> = {
+ std::__1::__tree_end_node<std::__1::__tree_node_base<void *> *> = {
+ __left_ = 0x0000000000000000
+ }
+ __right_ = 0x0000000000000000
+ __parent_ = 0x00000001001038b0
+ __is_black_ = true
+ }
+ __value_ = {
+ first = 0
+ second = { std::string }
+ */
+
+lldb_private::formatters::LibCxxMapIteratorSyntheticFrontEnd::LibCxxMapIteratorSyntheticFrontEnd (lldb::ValueObjectSP valobj_sp) :
+SyntheticChildrenFrontEnd(*valobj_sp.get()),
+m_pair_ptr()
+{
+    if (valobj_sp)
+        Update();
+}
+
+bool
+lldb_private::formatters::LibCxxMapIteratorSyntheticFrontEnd::Update()
+{
+    ValueObjectSP valobj_sp = m_backend.GetSP();
+    if (!valobj_sp)
+        return false;
+    
+    TargetSP target_sp(valobj_sp->GetTargetSP());
+    
+    if (!target_sp)
+        return false;
+
+    if (!valobj_sp)
+        return false;
+
+    // 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 -> synthetic -> child -> parent == iterator)
+    // and that would in turn leak memory by never allowing the ValueObjects to die and free their memory
+    m_pair_ptr = valobj_sp->GetValueForExpressionPath(".__i_.__ptr_->__value_",
+                                                     NULL,
+                                                     NULL,
+                                                     NULL,
+                                                     ValueObject::GetValueForExpressionPathOptions().DontCheckDotVsArrowSyntax().SetSyntheticChildrenTraversal(ValueObject::GetValueForExpressionPathOptions::SyntheticChildrenTraversal::None),
+                                                     NULL).get();
+    
+    return false;
+}
+
+size_t
+lldb_private::formatters::LibCxxMapIteratorSyntheticFrontEnd::CalculateNumChildren ()
+{
+    return 2;
+}
+
+lldb::ValueObjectSP
+lldb_private::formatters::LibCxxMapIteratorSyntheticFrontEnd::GetChildAtIndex (size_t idx)
+{
+    if (!m_pair_ptr)
+        return lldb::ValueObjectSP();
+    return m_pair_ptr->GetChildAtIndex(idx, true);
+}
+
+bool
+lldb_private::formatters::LibCxxMapIteratorSyntheticFrontEnd::MightHaveChildren ()
+{
+    return true;
+}
+
+size_t
+lldb_private::formatters::LibCxxMapIteratorSyntheticFrontEnd::GetIndexOfChildWithName (const ConstString &name)
+{
+    if (name == ConstString("first"))
+        return 0;
+    if (name == ConstString("second"))
+        return 1;
+    return UINT32_MAX;
+}
+
+lldb_private::formatters::LibCxxMapIteratorSyntheticFrontEnd::~LibCxxMapIteratorSyntheticFrontEnd ()
+{
+    // this will be deleted when its parent dies (since it's a child object)
+    //delete m_pair_ptr;
+}
+
+SyntheticChildrenFrontEnd*
+lldb_private::formatters::LibCxxMapIteratorSyntheticFrontEndCreator (CXXSyntheticChildren*, lldb::ValueObjectSP valobj_sp)
+{
+    if (!valobj_sp)
+        return NULL;
+    return (new LibCxxMapIteratorSyntheticFrontEnd(valobj_sp));
+}
+
+/*
+ (lldb) fr var ibeg --raw --ptr-depth 1 -T
+ (std::__1::__wrap_iter<int *>) ibeg = {
+ (std::__1::__wrap_iter<int *>::iterator_type) __i = 0x00000001001037a0 {
+ (int) *__i = 1
+ }
+ }
+*/
+
+SyntheticChildrenFrontEnd*
+lldb_private::formatters::LibCxxVectorIteratorSyntheticFrontEndCreator (CXXSyntheticChildren*, lldb::ValueObjectSP valobj_sp)
+{
+    static ConstString g_item_name;
+    if (!g_item_name)
+        g_item_name.SetCString("__i");
+    if (!valobj_sp)
+        return NULL;
+    return (new VectorIteratorSyntheticFrontEnd(valobj_sp,g_item_name));
+}
+
+lldb_private::formatters::LibcxxSharedPtrSyntheticFrontEnd::LibcxxSharedPtrSyntheticFrontEnd (lldb::ValueObjectSP valobj_sp) :
+SyntheticChildrenFrontEnd(*valobj_sp.get()),
+m_cntrl(NULL),
+m_count_sp(),
+m_weak_count_sp(),
+m_ptr_size(0),
+m_byte_order(lldb::eByteOrderInvalid)
+{
+    if (valobj_sp)
+        Update();
+}
+
+size_t
+lldb_private::formatters::LibcxxSharedPtrSyntheticFrontEnd::CalculateNumChildren ()
+{
+    return (m_cntrl ? 1 : 0);
+}
+
+lldb::ValueObjectSP
+lldb_private::formatters::LibcxxSharedPtrSyntheticFrontEnd::GetChildAtIndex (size_t idx)
+{
+    if (!m_cntrl)
+        return lldb::ValueObjectSP();
+
+    ValueObjectSP valobj_sp = m_backend.GetSP();
+    if (!valobj_sp)
+        return lldb::ValueObjectSP();
+
+    if (idx == 0)
+        return valobj_sp->GetChildMemberWithName(ConstString("__ptr_"), true);
+
+    if (idx > 2)
+        return lldb::ValueObjectSP();
+
+    if (idx == 1)
+    {
+        if (!m_count_sp)
+        {
+            ValueObjectSP shared_owners_sp(m_cntrl->GetChildMemberWithName(ConstString("__shared_owners_"),true));
+            if (!shared_owners_sp)
+                return lldb::ValueObjectSP();
+            uint64_t count = 1 + shared_owners_sp->GetValueAsUnsigned(0);
+            DataExtractor data(&count, 8, m_byte_order, m_ptr_size);
+            m_count_sp = CreateValueObjectFromData("count", data, valobj_sp->GetExecutionContextRef(), shared_owners_sp->GetCompilerType());
+        }
+        return m_count_sp;
+    }
+    else /* if (idx == 2) */
+    {
+        if (!m_weak_count_sp)
+        {
+            ValueObjectSP shared_weak_owners_sp(m_cntrl->GetChildMemberWithName(ConstString("__shared_weak_owners_"),true));
+            if (!shared_weak_owners_sp)
+                return lldb::ValueObjectSP();
+            uint64_t count = 1 + shared_weak_owners_sp->GetValueAsUnsigned(0);
+            DataExtractor data(&count, 8, m_byte_order, m_ptr_size);
+            m_weak_count_sp = CreateValueObjectFromData("count", data, valobj_sp->GetExecutionContextRef(), shared_weak_owners_sp->GetCompilerType());
+        }
+        return m_weak_count_sp;
+    }
+}
+
+bool
+lldb_private::formatters::LibcxxSharedPtrSyntheticFrontEnd::Update()
+{
+    m_count_sp.reset();
+    m_weak_count_sp.reset();
+    m_cntrl = NULL;
+    
+    ValueObjectSP valobj_sp = m_backend.GetSP();
+    if (!valobj_sp)
+        return false;
+    
+    TargetSP target_sp(valobj_sp->GetTargetSP());
+    if (!target_sp)
+        return false;
+    
+    m_byte_order = target_sp->GetArchitecture().GetByteOrder();
+    m_ptr_size = target_sp->GetArchitecture().GetAddressByteSize();
+    
+    lldb::ValueObjectSP cntrl_sp(valobj_sp->GetChildMemberWithName(ConstString("__cntrl_"),true));
+    
+    m_cntrl = cntrl_sp.get(); // need to store the raw pointer to avoid a circular dependency
+    return false;
+}
+
+bool
+lldb_private::formatters::LibcxxSharedPtrSyntheticFrontEnd::MightHaveChildren ()
+{
+    return true;
+}
+
+size_t
+lldb_private::formatters::LibcxxSharedPtrSyntheticFrontEnd::GetIndexOfChildWithName (const ConstString &name)
+{
+    if (name == ConstString("__ptr_"))
+        return 0;
+    if (name == ConstString("count"))
+        return 1;
+    if (name == ConstString("weak_count"))
+        return 2;
+    return UINT32_MAX;
+}
+
+lldb_private::formatters::LibcxxSharedPtrSyntheticFrontEnd::~LibcxxSharedPtrSyntheticFrontEnd ()
+{}
+
+SyntheticChildrenFrontEnd*
+lldb_private::formatters::LibcxxSharedPtrSyntheticFrontEndCreator (CXXSyntheticChildren*, lldb::ValueObjectSP valobj_sp)
+{
+    if (!valobj_sp)
+        return NULL;
+    return (new LibcxxSharedPtrSyntheticFrontEnd(valobj_sp));
+}
+
+bool
+lldb_private::formatters::LibcxxContainerSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options)
+{
+    if (valobj.IsPointerType())
+    {
+        uint64_t value = valobj.GetValueAsUnsigned(0);
+        if (!value)
+            return false;
+        stream.Printf("0x%016" PRIx64 " ", value);
+    }
+    return FormatEntity::FormatStringRef("size=${svar%#}", stream, NULL, NULL, NULL, &valobj, false, false);
+}
+
+// the field layout in a libc++ string (cap, side, data or data, size, cap)
+enum LibcxxStringLayoutMode
+{
+    eLibcxxStringLayoutModeCSD = 0,
+    eLibcxxStringLayoutModeDSC = 1,
+    eLibcxxStringLayoutModeInvalid = 0xffff
+};
+
+// this function abstracts away the layout and mode details of a libc++ string
+// and returns the address of the data and the size ready for callers to consume
+static bool
+ExtractLibcxxStringInfo (ValueObject& valobj,
+                         ValueObjectSP &location_sp,
+                         uint64_t& size)
+{
+    ValueObjectSP D(valobj.GetChildAtIndexPath({0,0,0,0}));
+    if (!D)
+        return false;
+    
+    ValueObjectSP layout_decider(D->GetChildAtIndexPath({0,0}));
+    
+    // this child should exist
+    if (!layout_decider)
+        return false;
+    
+    ConstString g_data_name("__data_");
+    ConstString g_size_name("__size_");
+    bool short_mode = false; // this means the string is in short-mode and the data is stored inline
+    LibcxxStringLayoutMode layout = (layout_decider->GetName() == g_data_name) ? eLibcxxStringLayoutModeDSC : eLibcxxStringLayoutModeCSD;
+    uint64_t size_mode_value = 0;
+    
+    if (layout == eLibcxxStringLayoutModeDSC)
+    {
+        ValueObjectSP size_mode(D->GetChildAtIndexPath({1,1,0}));
+        if (!size_mode)
+            return false;
+        
+        if (size_mode->GetName() != g_size_name)
+        {
+            // we are hitting the padding structure, move along
+            size_mode = D->GetChildAtIndexPath({1,1,1});
+            if (!size_mode)
+                return false;
+        }
+        
+        size_mode_value = (size_mode->GetValueAsUnsigned(0));
+        short_mode = ((size_mode_value & 0x80) == 0);
+    }
+    else
+    {
+        ValueObjectSP size_mode(D->GetChildAtIndexPath({1,0,0}));
+        if (!size_mode)
+            return false;
+        
+        size_mode_value = (size_mode->GetValueAsUnsigned(0));
+        short_mode = ((size_mode_value & 1) == 0);
+    }
+    
+    if (short_mode)
+    {
+        ValueObjectSP s(D->GetChildAtIndex(1, true));
+        if (!s)
+            return false;
+        location_sp = s->GetChildAtIndex((layout == eLibcxxStringLayoutModeDSC) ? 0 : 1, true);
+        size = (layout == eLibcxxStringLayoutModeDSC) ? size_mode_value : ((size_mode_value >> 1) % 256);
+        return (location_sp.get() != nullptr);
+    }
+    else
+    {
+        ValueObjectSP l(D->GetChildAtIndex(0, true));
+        if (!l)
+            return false;
+        // we can use the layout_decider object as the data pointer
+        location_sp = (layout == eLibcxxStringLayoutModeDSC) ? layout_decider : l->GetChildAtIndex(2, true);
+        ValueObjectSP size_vo(l->GetChildAtIndex(1, true));
+        if (!size_vo || !location_sp)
+            return false;
+        size = size_vo->GetValueAsUnsigned(0);
+        return true;
+    }
+}
+
+bool
+lldb_private::formatters::LibcxxWStringSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& summary_options)
+{
+    uint64_t size = 0;
+    ValueObjectSP location_sp((ValueObject*)nullptr);
+    if (!ExtractLibcxxStringInfo(valobj, location_sp, size))
+        return false;
+    if (size == 0)
+    {
+        stream.Printf("L\"\"");
+        return true;
+    }
+    if (!location_sp)
+        return false;
+    
+    DataExtractor extractor;
+    if (summary_options.GetCapping() == TypeSummaryCapping::eTypeSummaryCapped)
+        size = std::min<decltype(size)>(size, valobj.GetTargetSP()->GetMaximumSizeOfStringSummary());
+    location_sp->GetPointeeData(extractor, 0, size);
+    
+    // std::wstring::size() is measured in 'characters', not bytes
+    auto wchar_t_size = valobj.GetTargetSP()->GetScratchClangASTContext()->GetBasicType(lldb::eBasicTypeWChar).GetByteSize(nullptr);
+    
+    ReadBufferAndDumpToStreamOptions options(valobj);
+    options.SetData(extractor);
+    options.SetStream(&stream);
+    options.SetPrefixToken('L');
+    options.SetQuote('"');
+    options.SetSourceSize(size);
+    options.SetBinaryZeroIsTerminator(false);
+    
+    switch (wchar_t_size)
+    {
+        case 1:
+            lldb_private::formatters::ReadBufferAndDumpToStream<lldb_private::formatters::StringElementType::UTF8>(options);
+            break;
+            
+        case 2:
+            lldb_private::formatters::ReadBufferAndDumpToStream<lldb_private::formatters::StringElementType::UTF16>(options);
+            break;
+            
+        case 4:
+            lldb_private::formatters::ReadBufferAndDumpToStream<lldb_private::formatters::StringElementType::UTF32>(options);
+            break;
+            
+        default:
+            stream.Printf("size for wchar_t is not valid");
+            return true;
+    }
+    
+    return true;
+}
+
+bool
+lldb_private::formatters::LibcxxStringSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& summary_options)
+{
+    uint64_t size = 0;
+    ValueObjectSP location_sp((ValueObject*)nullptr);
+    
+    if (!ExtractLibcxxStringInfo(valobj, location_sp, size))
+        return false;
+    
+    if (size == 0)
+    {
+        stream.Printf("\"\"");
+        return true;
+    }
+    
+    if (!location_sp)
+        return false;
+    
+    DataExtractor extractor;
+    if (summary_options.GetCapping() == TypeSummaryCapping::eTypeSummaryCapped)
+        size = std::min<decltype(size)>(size, valobj.GetTargetSP()->GetMaximumSizeOfStringSummary());
+    location_sp->GetPointeeData(extractor, 0, size);
+    
+    ReadBufferAndDumpToStreamOptions options(valobj);
+    options.SetData(extractor);
+    options.SetStream(&stream);
+    options.SetPrefixToken(0);
+    options.SetQuote('"');
+    options.SetSourceSize(size);
+    options.SetBinaryZeroIsTerminator(false);
+    lldb_private::formatters::ReadBufferAndDumpToStream<lldb_private::formatters::StringElementType::ASCII>(options);
+    
+    return true;
+}
diff --git a/lldb/source/Plugins/Language/CPlusPlus/LibCxx.h b/lldb/source/Plugins/Language/CPlusPlus/LibCxx.h
new file mode 100644
index 0000000..ae00bc0
--- /dev/null
+++ b/lldb/source/Plugins/Language/CPlusPlus/LibCxx.h
@@ -0,0 +1,141 @@
+//===-- LibCxx.h ---------------------------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef liblldb_LibCxx_h_
+#define liblldb_LibCxx_h_
+
+#include "lldb/Core/Stream.h"
+#include "lldb/Core/ValueObject.h"
+#include "lldb/DataFormatters/TypeSummary.h"
+#include "lldb/DataFormatters/TypeSynthetic.h"
+
+namespace lldb_private {
+    namespace formatters
+    {
+        
+        bool
+        LibcxxStringSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options); // libc++ std::string
+        
+        bool
+        LibcxxWStringSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options); // libc++ std::wstring
+        
+        bool
+        LibcxxSmartPointerSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options); // libc++ std::shared_ptr<> and std::weak_ptr<>
+        
+        class LibcxxVectorBoolSyntheticFrontEnd : public SyntheticChildrenFrontEnd
+        {
+        public:
+            LibcxxVectorBoolSyntheticFrontEnd (lldb::ValueObjectSP valobj_sp);
+            
+            size_t
+            CalculateNumChildren() override;
+            
+            lldb::ValueObjectSP
+            GetChildAtIndex(size_t idx) override;
+            
+            bool
+            Update() override;
+            
+            bool
+            MightHaveChildren() override;
+            
+            size_t
+            GetIndexOfChildWithName(const ConstString &name) override;
+            
+            ~LibcxxVectorBoolSyntheticFrontEnd() override;
+            
+        private:
+            CompilerType m_bool_type;
+            ExecutionContextRef m_exe_ctx_ref;
+            uint64_t m_count;
+            lldb::addr_t m_base_data_address;
+            std::map<size_t,lldb::ValueObjectSP> m_children;
+        };
+        
+        SyntheticChildrenFrontEnd* LibcxxVectorBoolSyntheticFrontEndCreator (CXXSyntheticChildren*, lldb::ValueObjectSP);
+        
+        bool
+        LibcxxContainerSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options);
+        
+        class LibCxxMapIteratorSyntheticFrontEnd : public SyntheticChildrenFrontEnd
+        {
+        public:
+            LibCxxMapIteratorSyntheticFrontEnd (lldb::ValueObjectSP valobj_sp);
+            
+            size_t
+            CalculateNumChildren() override;
+            
+            lldb::ValueObjectSP
+            GetChildAtIndex(size_t idx) override;
+            
+            bool
+            Update() override;
+            
+            bool
+            MightHaveChildren() override;
+            
+            size_t
+            GetIndexOfChildWithName(const ConstString &name) override;
+            
+            ~LibCxxMapIteratorSyntheticFrontEnd() override;
+            
+        private:
+            ValueObject *m_pair_ptr;
+        };
+        
+        SyntheticChildrenFrontEnd* LibCxxMapIteratorSyntheticFrontEndCreator (CXXSyntheticChildren*, lldb::ValueObjectSP);
+        
+        SyntheticChildrenFrontEnd* LibCxxVectorIteratorSyntheticFrontEndCreator (CXXSyntheticChildren*, lldb::ValueObjectSP);
+        
+        class LibcxxSharedPtrSyntheticFrontEnd : public SyntheticChildrenFrontEnd
+        {
+        public:
+            LibcxxSharedPtrSyntheticFrontEnd (lldb::ValueObjectSP valobj_sp);
+            
+            size_t
+            CalculateNumChildren() override;
+            
+            lldb::ValueObjectSP
+            GetChildAtIndex(size_t idx) override;
+            
+            bool
+            Update() override;
+            
+            bool
+            MightHaveChildren() override;
+            
+            size_t
+            GetIndexOfChildWithName(const ConstString &name) override;
+            
+            ~LibcxxSharedPtrSyntheticFrontEnd() override;
+            
+        private:
+            ValueObject* m_cntrl;
+            lldb::ValueObjectSP m_count_sp;
+            lldb::ValueObjectSP m_weak_count_sp;
+            uint8_t m_ptr_size;
+            lldb::ByteOrder m_byte_order;
+        };
+        
+        SyntheticChildrenFrontEnd* LibcxxSharedPtrSyntheticFrontEndCreator (CXXSyntheticChildren*, lldb::ValueObjectSP);
+        
+        SyntheticChildrenFrontEnd* LibcxxStdVectorSyntheticFrontEndCreator (CXXSyntheticChildren*, lldb::ValueObjectSP);
+        
+        SyntheticChildrenFrontEnd* LibcxxStdListSyntheticFrontEndCreator (CXXSyntheticChildren*, lldb::ValueObjectSP);
+        
+        SyntheticChildrenFrontEnd* LibcxxStdMapSyntheticFrontEndCreator (CXXSyntheticChildren*, lldb::ValueObjectSP);
+        
+        SyntheticChildrenFrontEnd* LibcxxStdUnorderedMapSyntheticFrontEndCreator (CXXSyntheticChildren*, lldb::ValueObjectSP);
+        
+        SyntheticChildrenFrontEnd* LibcxxInitializerListSyntheticFrontEndCreator (CXXSyntheticChildren*, lldb::ValueObjectSP);
+
+    } // namespace formatters
+} // namespace lldb_private
+
+#endif // liblldb_LibCxx_h_
diff --git a/lldb/source/Plugins/Language/CPlusPlus/LibCxxInitializerList.cpp b/lldb/source/Plugins/Language/CPlusPlus/LibCxxInitializerList.cpp
new file mode 100644
index 0000000..ac6501f
--- /dev/null
+++ b/lldb/source/Plugins/Language/CPlusPlus/LibCxxInitializerList.cpp
@@ -0,0 +1,144 @@
+//===-- LibCxxInitializerList.cpp ----------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "LibCxx.h"
+
+#include "lldb/Core/ConstString.h"
+#include "lldb/Core/ValueObject.h"
+#include "lldb/DataFormatters/FormattersHelpers.h"
+
+using namespace lldb;
+using namespace lldb_private;
+using namespace lldb_private::formatters;
+
+namespace lldb_private {
+    namespace formatters {
+        class LibcxxInitializerListSyntheticFrontEnd : public SyntheticChildrenFrontEnd
+        {
+        public:
+            LibcxxInitializerListSyntheticFrontEnd (lldb::ValueObjectSP valobj_sp);
+            
+            virtual size_t
+            CalculateNumChildren ();
+            
+            virtual lldb::ValueObjectSP
+            GetChildAtIndex (size_t idx);
+            
+            virtual bool
+            Update();
+            
+            virtual bool
+            MightHaveChildren ();
+            
+            virtual size_t
+            GetIndexOfChildWithName (const ConstString &name);
+            
+            virtual
+            ~LibcxxInitializerListSyntheticFrontEnd ();
+        private:
+            ValueObject* m_start;
+            CompilerType m_element_type;
+            uint32_t m_element_size;
+            size_t m_num_elements;
+            std::map<size_t,lldb::ValueObjectSP> m_children;
+        };
+    }
+}
+
+lldb_private::formatters::LibcxxInitializerListSyntheticFrontEnd::LibcxxInitializerListSyntheticFrontEnd (lldb::ValueObjectSP valobj_sp) :
+SyntheticChildrenFrontEnd(*valobj_sp.get()),
+m_start(NULL),
+m_element_type(),
+m_element_size(0),
+m_num_elements(0),
+m_children()
+{
+    if (valobj_sp)
+        Update();
+}
+
+size_t
+lldb_private::formatters::LibcxxInitializerListSyntheticFrontEnd::CalculateNumChildren ()
+{
+    static ConstString g___size_("__size_");
+    m_num_elements = 0;
+    ValueObjectSP size_sp(m_backend.GetChildMemberWithName(g___size_, true));
+    if (size_sp)
+        m_num_elements = size_sp->GetValueAsUnsigned(0);
+    return m_num_elements;
+}
+
+lldb::ValueObjectSP
+lldb_private::formatters::LibcxxInitializerListSyntheticFrontEnd::GetChildAtIndex (size_t idx)
+{
+    if (!m_start)
+        return lldb::ValueObjectSP();
+    
+    auto cached = m_children.find(idx);
+    if (cached != m_children.end())
+        return cached->second;
+    
+    uint64_t offset = idx * m_element_size;
+    offset = offset + m_start->GetValueAsUnsigned(0);
+    StreamString name;
+    name.Printf("[%" PRIu64 "]", (uint64_t)idx);
+    ValueObjectSP child_sp = CreateValueObjectFromAddress(name.GetData(), offset, m_backend.GetExecutionContextRef(), m_element_type);
+    m_children[idx] = child_sp;
+    return child_sp;
+}
+
+bool
+lldb_private::formatters::LibcxxInitializerListSyntheticFrontEnd::Update()
+{
+    static ConstString g___begin_("__begin_");
+
+    m_start = nullptr;
+    m_num_elements = 0;
+    m_children.clear();
+    lldb::TemplateArgumentKind kind;
+    m_element_type = m_backend.GetCompilerType().GetTemplateArgument(0, kind);
+    if (kind != lldb::eTemplateArgumentKindType || false == m_element_type.IsValid())
+        return false;
+    
+    m_element_size = m_element_type.GetByteSize(nullptr);
+    
+    if (m_element_size > 0)
+        m_start = m_backend.GetChildMemberWithName(g___begin_,true).get(); // store raw pointers or end up with a circular dependency
+
+    return false;
+}
+
+bool
+lldb_private::formatters::LibcxxInitializerListSyntheticFrontEnd::MightHaveChildren ()
+{
+    return true;
+}
+
+size_t
+lldb_private::formatters::LibcxxInitializerListSyntheticFrontEnd::GetIndexOfChildWithName (const ConstString &name)
+{
+    if (!m_start)
+        return UINT32_MAX;
+    return ExtractIndexFromString(name.GetCString());
+}
+
+lldb_private::formatters::LibcxxInitializerListSyntheticFrontEnd::~LibcxxInitializerListSyntheticFrontEnd ()
+{
+    // this needs to stay around because it's a child object who will follow its parent's life cycle
+    // delete m_start;
+}
+
+lldb_private::SyntheticChildrenFrontEnd*
+lldb_private::formatters::LibcxxInitializerListSyntheticFrontEndCreator (CXXSyntheticChildren*, lldb::ValueObjectSP valobj_sp)
+{
+    if (!valobj_sp)
+        return NULL;
+    return (new LibcxxInitializerListSyntheticFrontEnd(valobj_sp));
+}
+
diff --git a/lldb/source/Plugins/Language/CPlusPlus/LibCxxList.cpp b/lldb/source/Plugins/Language/CPlusPlus/LibCxxList.cpp
new file mode 100644
index 0000000..7da1b7a
--- /dev/null
+++ b/lldb/source/Plugins/Language/CPlusPlus/LibCxxList.cpp
@@ -0,0 +1,370 @@
+//===-- LibCxxList.cpp -------------------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "LibCxx.h"
+
+#include "lldb/Core/DataBufferHeap.h"
+#include "lldb/Core/Error.h"
+#include "lldb/Core/Stream.h"
+#include "lldb/Core/ValueObject.h"
+#include "lldb/Core/ValueObjectConstResult.h"
+#include "lldb/DataFormatters/FormattersHelpers.h"
+#include "lldb/Host/Endian.h"
+#include "lldb/Symbol/ClangASTContext.h"
+#include "lldb/Target/Target.h"
+
+using namespace lldb;
+using namespace lldb_private;
+using namespace lldb_private::formatters;
+
+namespace lldb_private {
+    namespace formatters {
+        class LibcxxStdListSyntheticFrontEnd : public SyntheticChildrenFrontEnd
+        {
+        public:
+            LibcxxStdListSyntheticFrontEnd (lldb::ValueObjectSP valobj_sp);
+            
+            virtual size_t
+            CalculateNumChildren ();
+            
+            virtual lldb::ValueObjectSP
+            GetChildAtIndex (size_t idx);
+            
+            virtual bool
+            Update();
+            
+            virtual bool
+            MightHaveChildren ();
+            
+            virtual size_t
+            GetIndexOfChildWithName (const ConstString &name);
+            
+            virtual
+            ~LibcxxStdListSyntheticFrontEnd ();
+        private:
+            bool
+            HasLoop(size_t);
+            
+            size_t m_list_capping_size;
+            static const bool g_use_loop_detect = true;
+            size_t m_loop_detected;
+            lldb::addr_t m_node_address;
+            ValueObject* m_head;
+            ValueObject* m_tail;
+            CompilerType m_element_type;
+            size_t m_count;
+            std::map<size_t,lldb::ValueObjectSP> m_children;
+        };
+    }
+}
+
+class ListEntry
+{
+public:
+    ListEntry () {}
+    ListEntry (ValueObjectSP entry_sp) : m_entry_sp(entry_sp) {}
+    ListEntry (const ListEntry& rhs) : m_entry_sp(rhs.m_entry_sp) {}
+    ListEntry (ValueObject* entry) : m_entry_sp(entry ? entry->GetSP() : ValueObjectSP()) {}
+    
+    ListEntry
+    next ()
+    {
+        if (!m_entry_sp)
+            return ListEntry();
+        return ListEntry(m_entry_sp->GetChildMemberWithName(ConstString("__next_"), true));
+    }
+    
+    ListEntry
+    prev ()
+    {
+        if (!m_entry_sp)
+            return ListEntry();
+        return ListEntry(m_entry_sp->GetChildMemberWithName(ConstString("__prev_"), true));
+    }
+    
+    uint64_t
+    value ()
+    {
+        if (!m_entry_sp)
+            return 0;
+        return m_entry_sp->GetValueAsUnsigned(0);
+    }
+
+    bool
+    null()
+    {
+        return (value() == 0);
+    }
+    
+    explicit operator bool ()
+    {
+        return GetEntry().get() != nullptr && null() == false;
+    }
+    
+    ValueObjectSP
+    GetEntry ()
+    {
+        return m_entry_sp;
+    }
+    
+    void
+    SetEntry (ValueObjectSP entry)
+    {
+        m_entry_sp = entry;
+    }
+    
+    bool
+    operator == (const ListEntry& rhs) const
+    {
+        return (rhs.m_entry_sp.get() == m_entry_sp.get());
+    }
+    
+private:
+    ValueObjectSP m_entry_sp;
+};
+
+class ListIterator
+{
+public:
+    ListIterator () {}
+    ListIterator (ListEntry entry) : m_entry(entry) {}
+    ListIterator (ValueObjectSP entry) : m_entry(entry) {}
+    ListIterator (const ListIterator& rhs) : m_entry(rhs.m_entry) {}
+    ListIterator (ValueObject* entry) : m_entry(entry) {}
+
+    ValueObjectSP
+    value ()
+    {
+        return m_entry.GetEntry();
+    }
+    
+    ValueObjectSP
+    advance (size_t count)
+    {
+        if (count == 0)
+            return m_entry.GetEntry();
+        if (count == 1)
+        {
+            next ();
+            return m_entry.GetEntry();
+        }
+        while (count > 0)
+        {
+            next ();
+            count--;
+            if (m_entry.null())
+                return lldb::ValueObjectSP();
+        }
+        return m_entry.GetEntry();
+    }
+    
+    bool
+    operator == (const ListIterator& rhs) const
+    {
+        return (rhs.m_entry == m_entry);
+    }
+    
+protected:
+    void
+    next ()
+    {
+        m_entry = m_entry.next();
+    }
+    
+    void
+    prev ()
+    {
+        m_entry = m_entry.prev();
+    }
+private:
+    ListEntry m_entry;
+};
+
+lldb_private::formatters::LibcxxStdListSyntheticFrontEnd::LibcxxStdListSyntheticFrontEnd (lldb::ValueObjectSP valobj_sp) :
+SyntheticChildrenFrontEnd(*valobj_sp.get()),
+m_list_capping_size(0),
+m_loop_detected(0),
+m_node_address(),
+m_head(NULL),
+m_tail(NULL),
+m_element_type(),
+m_count(UINT32_MAX),
+m_children()
+{
+    if (valobj_sp)
+        Update();
+}
+
+bool
+lldb_private::formatters::LibcxxStdListSyntheticFrontEnd::HasLoop(size_t count)
+{
+    if (g_use_loop_detect == false)
+        return false;
+    // don't bother checking for a loop if we won't actually need to jump nodes
+    if (m_count < 2)
+        return false;
+    auto steps_left = std::min(count,m_count);
+    auto steps_left_save = steps_left;
+    ListEntry slow(m_head);
+    ListEntry fast(m_head);
+    while (steps_left-- > 0)
+    {
+        slow = slow.next();
+        fast = fast.next();
+        if (fast.next())
+            fast = fast.next().next();
+        else
+            fast = nullptr;
+        if (!slow || !fast)
+            return false;
+        if (slow == fast)
+            return true;
+    }
+    m_loop_detected = steps_left_save;
+    return false;
+}
+
+size_t
+lldb_private::formatters::LibcxxStdListSyntheticFrontEnd::CalculateNumChildren ()
+{
+    if (m_count != UINT32_MAX)
+        return m_count;
+    if (!m_head || !m_tail || m_node_address == 0)
+        return 0;
+    ValueObjectSP size_alloc(m_backend.GetChildMemberWithName(ConstString("__size_alloc_"), true));
+    if (size_alloc)
+    {
+        ValueObjectSP first(size_alloc->GetChildMemberWithName(ConstString("__first_"), true));
+        if (first)
+        {
+            m_count = first->GetValueAsUnsigned(UINT32_MAX);
+        }
+    }
+    if (m_count != UINT32_MAX)
+    {
+        return m_count;
+    }
+    else
+    {
+        uint64_t next_val = m_head->GetValueAsUnsigned(0);
+        uint64_t prev_val = m_tail->GetValueAsUnsigned(0);
+        if (next_val == 0 || prev_val == 0)
+            return 0;
+        if (next_val == m_node_address)
+            return 0;
+        if (next_val == prev_val)
+            return 1;
+        uint64_t size = 2;
+        ListEntry current(m_head);
+        while (current.next() && current.next().value() != m_node_address)
+        {
+            size++;
+            current = current.next();
+            if (size > m_list_capping_size)
+                break;
+        }
+        return m_count = (size-1);
+    }
+}
+
+lldb::ValueObjectSP
+lldb_private::formatters::LibcxxStdListSyntheticFrontEnd::GetChildAtIndex (size_t idx)
+{
+    if (idx >= CalculateNumChildren())
+        return lldb::ValueObjectSP();
+    
+    if (!m_head || !m_tail || m_node_address == 0)
+        return lldb::ValueObjectSP();
+    
+    auto cached = m_children.find(idx);
+    if (cached != m_children.end())
+        return cached->second;
+    
+    if (m_loop_detected <= idx)
+        if (HasLoop(idx))
+            return lldb::ValueObjectSP();
+        
+    ListIterator current(m_head);
+    ValueObjectSP current_sp(current.advance(idx));
+    if (!current_sp)
+        return lldb::ValueObjectSP();
+    current_sp = current_sp->GetChildMemberWithName(ConstString("__value_"), true);
+    if (!current_sp)
+        return lldb::ValueObjectSP();
+    // we need to copy current_sp into a new object otherwise we will end up with all items named __value_
+    DataExtractor data;
+    Error error;
+    current_sp->GetData(data, error);
+    if (error.Fail())
+        return lldb::ValueObjectSP();
+    
+    StreamString name;
+    name.Printf("[%" PRIu64 "]", (uint64_t)idx);
+    return (m_children[idx] = CreateValueObjectFromData(name.GetData(), data, m_backend.GetExecutionContextRef(), m_element_type));
+}
+
+bool
+lldb_private::formatters::LibcxxStdListSyntheticFrontEnd::Update()
+{
+    m_children.clear();
+    m_head = m_tail = NULL;
+    m_node_address = 0;
+    m_count = UINT32_MAX;
+    m_loop_detected = false;
+    Error err;
+    ValueObjectSP backend_addr(m_backend.AddressOf(err));
+    m_list_capping_size = 0;
+    if (m_backend.GetTargetSP())
+        m_list_capping_size = m_backend.GetTargetSP()->GetMaximumNumberOfChildrenToDisplay();
+    if (m_list_capping_size == 0)
+        m_list_capping_size = 255;
+    if (err.Fail() || backend_addr.get() == NULL)
+        return false;
+    m_node_address = backend_addr->GetValueAsUnsigned(0);
+    if (!m_node_address || m_node_address == LLDB_INVALID_ADDRESS)
+        return false;
+    ValueObjectSP impl_sp(m_backend.GetChildMemberWithName(ConstString("__end_"),true));
+    if (!impl_sp)
+        return false;
+    CompilerType list_type = m_backend.GetCompilerType();
+    if (list_type.IsReferenceType())
+        list_type = list_type.GetNonReferenceType();
+
+    if (list_type.GetNumTemplateArguments() == 0)
+        return false;
+    lldb::TemplateArgumentKind kind;
+    m_element_type = list_type.GetTemplateArgument(0, kind);
+    m_head = impl_sp->GetChildMemberWithName(ConstString("__next_"), true).get();
+    m_tail = impl_sp->GetChildMemberWithName(ConstString("__prev_"), true).get();
+    return false;
+}
+
+bool
+lldb_private::formatters::LibcxxStdListSyntheticFrontEnd::MightHaveChildren ()
+{
+    return true;
+}
+
+size_t
+lldb_private::formatters::LibcxxStdListSyntheticFrontEnd::GetIndexOfChildWithName (const ConstString &name)
+{
+    return ExtractIndexFromString(name.GetCString());
+}
+
+lldb_private::formatters::LibcxxStdListSyntheticFrontEnd::~LibcxxStdListSyntheticFrontEnd ()
+{}
+
+SyntheticChildrenFrontEnd*
+lldb_private::formatters::LibcxxStdListSyntheticFrontEndCreator (CXXSyntheticChildren*, lldb::ValueObjectSP valobj_sp)
+{
+    if (!valobj_sp)
+        return NULL;
+    return (new LibcxxStdListSyntheticFrontEnd(valobj_sp));
+}
+
diff --git a/lldb/source/Plugins/Language/CPlusPlus/LibCxxMap.cpp b/lldb/source/Plugins/Language/CPlusPlus/LibCxxMap.cpp
new file mode 100644
index 0000000..99557fc
--- /dev/null
+++ b/lldb/source/Plugins/Language/CPlusPlus/LibCxxMap.cpp
@@ -0,0 +1,452 @@
+//===-- LibCxxList.cpp -------------------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "LibCxx.h"
+
+#include "lldb/Core/DataBufferHeap.h"
+#include "lldb/Core/Error.h"
+#include "lldb/Core/Stream.h"
+#include "lldb/Core/ValueObject.h"
+#include "lldb/Core/ValueObjectConstResult.h"
+#include "lldb/DataFormatters/FormattersHelpers.h"
+#include "lldb/Host/Endian.h"
+#include "lldb/Symbol/ClangASTContext.h"
+#include "lldb/Target/Target.h"
+
+using namespace lldb;
+using namespace lldb_private;
+using namespace lldb_private::formatters;
+
+namespace lldb_private {
+    namespace formatters {
+        class LibcxxStdMapSyntheticFrontEnd : public SyntheticChildrenFrontEnd
+        {
+        public:
+            LibcxxStdMapSyntheticFrontEnd (lldb::ValueObjectSP valobj_sp);
+            
+            virtual size_t
+            CalculateNumChildren ();
+            
+            virtual lldb::ValueObjectSP
+            GetChildAtIndex (size_t idx);
+            
+            virtual bool
+            Update();
+            
+            virtual bool
+            MightHaveChildren ();
+            
+            virtual size_t
+            GetIndexOfChildWithName (const ConstString &name);
+            
+            virtual
+            ~LibcxxStdMapSyntheticFrontEnd ();
+        private:
+            bool
+            GetDataType();
+            
+            void
+            GetValueOffset (const lldb::ValueObjectSP& node);
+            
+            ValueObject* m_tree;
+            ValueObject* m_root_node;
+            CompilerType m_element_type;
+            uint32_t m_skip_size;
+            size_t m_count;
+            std::map<size_t,lldb::ValueObjectSP> m_children;
+        };
+    }
+}
+
+class MapEntry
+{
+public:
+    MapEntry () {}
+    explicit MapEntry (ValueObjectSP entry_sp) : m_entry_sp(entry_sp) {}
+    MapEntry (const MapEntry& rhs) : m_entry_sp(rhs.m_entry_sp) {}
+    explicit MapEntry (ValueObject* entry) : m_entry_sp(entry ? entry->GetSP() : ValueObjectSP()) {}
+    
+    ValueObjectSP
+    left () const
+    {
+        static ConstString g_left("__left_");
+        if (!m_entry_sp)
+            return m_entry_sp;
+        return m_entry_sp->GetChildMemberWithName(g_left, true);
+    }
+    
+    ValueObjectSP
+    right () const
+    {
+        static ConstString g_right("__right_");
+        if (!m_entry_sp)
+            return m_entry_sp;
+        return m_entry_sp->GetChildMemberWithName(g_right, true);
+    }
+    
+    ValueObjectSP
+    parent () const
+    {
+        static ConstString g_parent("__parent_");
+        if (!m_entry_sp)
+            return m_entry_sp;
+        return m_entry_sp->GetChildMemberWithName(g_parent, true);
+    }
+    
+    uint64_t
+    value () const
+    {
+        if (!m_entry_sp)
+            return 0;
+        return m_entry_sp->GetValueAsUnsigned(0);
+    }
+    
+    bool
+    error () const
+    {
+        if (!m_entry_sp)
+            return true;
+        return m_entry_sp->GetError().Fail();
+    }
+    
+    bool
+    null() const
+    {
+        return (value() == 0);
+    }
+    
+    ValueObjectSP
+    GetEntry () const
+    {
+        return m_entry_sp;
+    }
+    
+    void
+    SetEntry (ValueObjectSP entry)
+    {
+        m_entry_sp = entry;
+    }
+    
+    bool
+    operator == (const MapEntry& rhs) const
+    {
+        return (rhs.m_entry_sp.get() == m_entry_sp.get());
+    }
+    
+private:
+    ValueObjectSP m_entry_sp;
+};
+
+class MapIterator
+{
+public:
+    MapIterator () {}
+    MapIterator (MapEntry entry, size_t depth = 0) : m_entry(entry), m_max_depth(depth), m_error(false) {}
+    MapIterator (ValueObjectSP entry, size_t depth = 0) : m_entry(entry), m_max_depth(depth), m_error(false) {}
+    MapIterator (const MapIterator& rhs) : m_entry(rhs.m_entry),m_max_depth(rhs.m_max_depth), m_error(false) {}
+    MapIterator (ValueObject* entry, size_t depth = 0) : m_entry(entry), m_max_depth(depth), m_error(false) {}
+    
+    ValueObjectSP
+    value ()
+    {
+        return m_entry.GetEntry();
+    }
+    
+    ValueObjectSP
+    advance (size_t count)
+    {
+        ValueObjectSP fail(nullptr);
+        if (m_error)
+            return fail;
+        size_t steps = 0;
+        while (count > 0)
+        {
+            next();
+            count--, steps++;
+            if (m_error ||
+                m_entry.null() ||
+                (steps > m_max_depth))
+                return fail;
+        }
+        return m_entry.GetEntry();
+    }
+protected:
+    void
+    next ()
+    {
+        if (m_entry.null())
+            return;
+        MapEntry right(m_entry.right());
+        if (right.null() == false)
+        {
+            m_entry = tree_min(std::move(right));
+            return;
+        }
+        size_t steps = 0;
+        while (!is_left_child(m_entry))
+        {
+            if (m_entry.error())
+            {
+                m_error = true;
+                return;
+            }
+            m_entry.SetEntry(m_entry.parent());
+            steps++;
+            if (steps > m_max_depth)
+            {
+                m_entry = MapEntry();
+                return;
+            }
+        }
+        m_entry = MapEntry(m_entry.parent());
+    }
+
+private:
+    MapEntry
+    tree_min (MapEntry&& x)
+    {
+        if (x.null())
+            return MapEntry();
+        MapEntry left(x.left());
+        size_t steps = 0;
+        while (left.null() == false)
+        {
+            if (left.error())
+            {
+                m_error = true;
+                return MapEntry();
+            }
+            x = left;
+            left.SetEntry(x.left());
+            steps++;
+            if (steps > m_max_depth)
+                return MapEntry();
+        }
+        return x;
+    }
+
+    bool
+    is_left_child (const MapEntry& x)
+    {
+        if (x.null())
+            return false;
+        MapEntry rhs(x.parent());
+        rhs.SetEntry(rhs.left());
+        return x.value() == rhs.value();
+    }
+    
+    MapEntry m_entry;
+    size_t m_max_depth;
+    bool m_error;
+};
+
+lldb_private::formatters::LibcxxStdMapSyntheticFrontEnd::LibcxxStdMapSyntheticFrontEnd (lldb::ValueObjectSP valobj_sp) :
+SyntheticChildrenFrontEnd(*valobj_sp.get()),
+m_tree(NULL),
+m_root_node(NULL),
+m_element_type(),
+m_skip_size(UINT32_MAX),
+m_count(UINT32_MAX),
+m_children()
+{
+    if (valobj_sp)
+        Update();
+}
+
+size_t
+lldb_private::formatters::LibcxxStdMapSyntheticFrontEnd::CalculateNumChildren ()
+{
+    if (m_count != UINT32_MAX)
+        return m_count;
+    if (m_tree == NULL)
+        return 0;
+    ValueObjectSP m_item(m_tree->GetChildMemberWithName(ConstString("__pair3_"), true));
+    if (!m_item)
+        return 0;
+    m_item = m_item->GetChildMemberWithName(ConstString("__first_"), true);
+    if (!m_item)
+        return 0;
+    m_count = m_item->GetValueAsUnsigned(0);
+    return m_count;
+}
+
+bool
+lldb_private::formatters::LibcxxStdMapSyntheticFrontEnd::GetDataType()
+{
+    if (m_element_type.GetOpaqueQualType() && m_element_type.GetTypeSystem())
+        return true;
+    m_element_type.Clear();
+    ValueObjectSP deref;
+    Error error;
+    deref = m_root_node->Dereference(error);
+    if (!deref || error.Fail())
+        return false;
+    deref = deref->GetChildMemberWithName(ConstString("__value_"), true);
+    if (!deref)
+        return false;
+    m_element_type = deref->GetCompilerType();
+    return true;
+}
+
+void
+lldb_private::formatters::LibcxxStdMapSyntheticFrontEnd::GetValueOffset (const lldb::ValueObjectSP& node)
+{
+    if (m_skip_size != UINT32_MAX)
+        return;
+    if (!node)
+        return;
+    CompilerType node_type(node->GetCompilerType());
+    uint64_t bit_offset;
+    if (node_type.GetIndexOfFieldWithName("__value_", NULL, &bit_offset) == UINT32_MAX)
+        return;
+    m_skip_size = bit_offset / 8u;
+}
+
+lldb::ValueObjectSP
+lldb_private::formatters::LibcxxStdMapSyntheticFrontEnd::GetChildAtIndex (size_t idx)
+{
+    static ConstString g___cc("__cc");
+    static ConstString g___nc("__nc");
+
+    
+    if (idx >= CalculateNumChildren())
+        return lldb::ValueObjectSP();
+    if (m_tree == NULL || m_root_node == NULL)
+        return lldb::ValueObjectSP();
+    
+    auto cached = m_children.find(idx);
+    if (cached != m_children.end())
+        return cached->second;
+    
+    bool need_to_skip = (idx > 0);
+    MapIterator iterator(m_root_node, CalculateNumChildren());
+    ValueObjectSP iterated_sp(iterator.advance(idx));
+    if (iterated_sp.get() == NULL)
+    {
+        // this tree is garbage - stop
+        m_tree = NULL; // this will stop all future searches until an Update() happens
+        return iterated_sp;
+    }
+    if (GetDataType())
+    {
+        if (!need_to_skip)
+        {
+            Error error;
+            iterated_sp = iterated_sp->Dereference(error);
+            if (!iterated_sp || error.Fail())
+            {
+                m_tree = NULL;
+                return lldb::ValueObjectSP();
+            }
+            GetValueOffset(iterated_sp);
+            iterated_sp = iterated_sp->GetChildMemberWithName(ConstString("__value_"), true);
+            if (!iterated_sp)
+            {
+                m_tree = NULL;
+                return lldb::ValueObjectSP();
+            }
+        }
+        else
+        {
+            // because of the way our debug info is made, we need to read item 0 first
+            // so that we can cache information used to generate other elements
+            if (m_skip_size == UINT32_MAX)
+                GetChildAtIndex(0);
+            if (m_skip_size == UINT32_MAX)
+            {
+                m_tree = NULL;
+                return lldb::ValueObjectSP();
+            }
+            iterated_sp = iterated_sp->GetSyntheticChildAtOffset(m_skip_size, m_element_type, true);
+            if (!iterated_sp)
+            {
+                m_tree = NULL;
+                return lldb::ValueObjectSP();
+            }
+        }
+    }
+    else
+    {
+        m_tree = NULL;
+        return lldb::ValueObjectSP();
+    }
+    // at this point we have a valid 
+    // we need to copy current_sp into a new object otherwise we will end up with all items named __value_
+    DataExtractor data;
+    Error error;
+    iterated_sp->GetData(data, error);
+    if (error.Fail())
+    {
+        m_tree = NULL;
+        return lldb::ValueObjectSP();
+    }
+    StreamString name;
+    name.Printf("[%" PRIu64 "]", (uint64_t)idx);
+    auto potential_child_sp = CreateValueObjectFromData(name.GetData(), data, m_backend.GetExecutionContextRef(), m_element_type);
+    if (potential_child_sp)
+    {
+        switch (potential_child_sp->GetNumChildren())
+        {
+            case 1:
+            {
+                auto child0_sp = potential_child_sp->GetChildAtIndex(0, true);
+                if (child0_sp && child0_sp->GetName() == g___cc)
+                    potential_child_sp = child0_sp;
+                break;
+            }
+            case 2:
+            {
+                auto child0_sp = potential_child_sp->GetChildAtIndex(0, true);
+                auto child1_sp = potential_child_sp->GetChildAtIndex(1, true);
+                if (child0_sp && child0_sp->GetName() == g___cc &&
+                    child1_sp && child1_sp->GetName() == g___nc)
+                    potential_child_sp = child0_sp;
+                break;
+            }
+        }
+        potential_child_sp->SetName(ConstString(name.GetData()));
+    }
+    return (m_children[idx] = potential_child_sp);
+}
+
+bool
+lldb_private::formatters::LibcxxStdMapSyntheticFrontEnd::Update()
+{
+    m_count = UINT32_MAX;
+    m_tree = m_root_node = NULL;
+    m_children.clear();
+    m_tree = m_backend.GetChildMemberWithName(ConstString("__tree_"), true).get();
+    if (!m_tree)
+        return false;
+    m_root_node = m_tree->GetChildMemberWithName(ConstString("__begin_node_"), true).get();
+    return false;
+}
+
+bool
+lldb_private::formatters::LibcxxStdMapSyntheticFrontEnd::MightHaveChildren ()
+{
+    return true;
+}
+
+size_t
+lldb_private::formatters::LibcxxStdMapSyntheticFrontEnd::GetIndexOfChildWithName (const ConstString &name)
+{
+    return ExtractIndexFromString(name.GetCString());
+}
+
+lldb_private::formatters::LibcxxStdMapSyntheticFrontEnd::~LibcxxStdMapSyntheticFrontEnd ()
+{}
+
+SyntheticChildrenFrontEnd*
+lldb_private::formatters::LibcxxStdMapSyntheticFrontEndCreator (CXXSyntheticChildren*, lldb::ValueObjectSP valobj_sp)
+{
+    if (!valobj_sp)
+        return NULL;
+    return (new LibcxxStdMapSyntheticFrontEnd(valobj_sp));
+}
diff --git a/lldb/source/Plugins/Language/CPlusPlus/LibCxxUnorderedMap.cpp b/lldb/source/Plugins/Language/CPlusPlus/LibCxxUnorderedMap.cpp
new file mode 100644
index 0000000..82af5bd
--- /dev/null
+++ b/lldb/source/Plugins/Language/CPlusPlus/LibCxxUnorderedMap.cpp
@@ -0,0 +1,172 @@
+//===-- LibCxxUnorderedMap.cpp -----------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "LibCxx.h"
+
+#include "lldb/Core/DataBufferHeap.h"
+#include "lldb/Core/Error.h"
+#include "lldb/Core/Stream.h"
+#include "lldb/Core/ValueObject.h"
+#include "lldb/Core/ValueObjectConstResult.h"
+#include "lldb/DataFormatters/FormattersHelpers.h"
+#include "lldb/Host/Endian.h"
+#include "lldb/Symbol/ClangASTContext.h"
+#include "lldb/Target/Target.h"
+
+using namespace lldb;
+using namespace lldb_private;
+using namespace lldb_private::formatters;
+
+namespace lldb_private {
+    namespace formatters {
+        class LibcxxStdUnorderedMapSyntheticFrontEnd : public SyntheticChildrenFrontEnd
+        {
+        public:
+            LibcxxStdUnorderedMapSyntheticFrontEnd (lldb::ValueObjectSP valobj_sp);
+            
+            virtual size_t
+            CalculateNumChildren ();
+            
+            virtual lldb::ValueObjectSP
+            GetChildAtIndex (size_t idx);
+            
+            virtual bool
+            Update();
+            
+            virtual bool
+            MightHaveChildren ();
+            
+            virtual size_t
+            GetIndexOfChildWithName (const ConstString &name);
+            
+            virtual
+            ~LibcxxStdUnorderedMapSyntheticFrontEnd ();
+        private:
+            
+            ValueObject* m_tree;
+            size_t m_num_elements;
+            ValueObject* m_next_element;
+            std::map<size_t,lldb::ValueObjectSP> m_children;
+            std::vector<std::pair<ValueObject*, uint64_t> > m_elements_cache;
+        };
+    }
+}
+
+lldb_private::formatters::LibcxxStdUnorderedMapSyntheticFrontEnd::LibcxxStdUnorderedMapSyntheticFrontEnd (lldb::ValueObjectSP valobj_sp) :
+SyntheticChildrenFrontEnd(*valobj_sp.get()),
+m_tree(NULL),
+m_num_elements(0),
+m_next_element(nullptr),
+m_children(),
+m_elements_cache()
+{
+    if (valobj_sp)
+        Update();
+}
+
+size_t
+lldb_private::formatters::LibcxxStdUnorderedMapSyntheticFrontEnd::CalculateNumChildren ()
+{
+    if (m_num_elements != UINT32_MAX)
+        return m_num_elements;
+    return 0;
+}
+
+lldb::ValueObjectSP
+lldb_private::formatters::LibcxxStdUnorderedMapSyntheticFrontEnd::GetChildAtIndex (size_t idx)
+{
+    if (idx >= CalculateNumChildren())
+        return lldb::ValueObjectSP();
+    if (m_tree == NULL)
+        return lldb::ValueObjectSP();
+    
+    auto cached = m_children.find(idx);
+    if (cached != m_children.end())
+        return cached->second;
+    
+    while (idx >= m_elements_cache.size())
+    {
+        if (m_next_element == nullptr)
+            return lldb::ValueObjectSP();
+        
+        Error error;
+        ValueObjectSP node_sp = m_next_element->Dereference(error);
+        if (!node_sp || error.Fail())
+            return lldb::ValueObjectSP();
+        
+        ValueObjectSP value_sp = node_sp->GetChildMemberWithName(ConstString("__value_"), true);
+        ValueObjectSP hash_sp = node_sp->GetChildMemberWithName(ConstString("__hash_"), true);
+        if (!hash_sp || !value_sp)
+            return lldb::ValueObjectSP();
+        m_elements_cache.push_back({value_sp.get(),hash_sp->GetValueAsUnsigned(0)});
+        m_next_element = node_sp->GetChildMemberWithName(ConstString("__next_"),true).get();
+        if (!m_next_element || m_next_element->GetValueAsUnsigned(0) == 0)
+            m_next_element = nullptr;
+    }
+    
+    std::pair<ValueObject*, uint64_t> val_hash = m_elements_cache[idx];
+    if (!val_hash.first)
+        return lldb::ValueObjectSP();
+    StreamString stream;
+    stream.Printf("[%" PRIu64 "]", (uint64_t)idx);
+    DataExtractor data;
+    Error error;
+    val_hash.first->GetData(data, error);
+    if (error.Fail())
+        return lldb::ValueObjectSP();
+    const bool thread_and_frame_only_if_stopped = true;
+    ExecutionContext exe_ctx = val_hash.first->GetExecutionContextRef().Lock(thread_and_frame_only_if_stopped);
+    return val_hash.first->CreateValueObjectFromData(stream.GetData(),
+                                                     data,
+                                                     exe_ctx,
+                                                     val_hash.first->GetCompilerType());
+}
+
+bool
+lldb_private::formatters::LibcxxStdUnorderedMapSyntheticFrontEnd::Update()
+{
+    m_num_elements = UINT32_MAX;
+    m_next_element = nullptr;
+    m_elements_cache.clear();
+    m_children.clear();
+    ValueObjectSP table_sp = m_backend.GetChildMemberWithName(ConstString("__table_"), true);
+    if (!table_sp)
+        return false;
+    ValueObjectSP num_elements_sp = table_sp->GetChildAtNamePath({ConstString("__p2_"),ConstString("__first_")});
+    if (!num_elements_sp)
+        return false;
+    m_num_elements = num_elements_sp->GetValueAsUnsigned(0);
+    m_tree = table_sp->GetChildAtNamePath({ConstString("__p1_"),ConstString("__first_"),ConstString("__next_")}).get();
+    if (m_num_elements > 0)
+        m_next_element = table_sp->GetChildAtNamePath({ConstString("__p1_"),ConstString("__first_"),ConstString("__next_")}).get();
+    return false;
+}
+
+bool
+lldb_private::formatters::LibcxxStdUnorderedMapSyntheticFrontEnd::MightHaveChildren ()
+{
+    return true;
+}
+
+size_t
+lldb_private::formatters::LibcxxStdUnorderedMapSyntheticFrontEnd::GetIndexOfChildWithName (const ConstString &name)
+{
+    return ExtractIndexFromString(name.GetCString());
+}
+
+lldb_private::formatters::LibcxxStdUnorderedMapSyntheticFrontEnd::~LibcxxStdUnorderedMapSyntheticFrontEnd ()
+{}
+
+SyntheticChildrenFrontEnd*
+lldb_private::formatters::LibcxxStdUnorderedMapSyntheticFrontEndCreator (CXXSyntheticChildren*, lldb::ValueObjectSP valobj_sp)
+{
+    if (!valobj_sp)
+        return NULL;
+    return (new LibcxxStdUnorderedMapSyntheticFrontEnd(valobj_sp));
+}
diff --git a/lldb/source/Plugins/Language/CPlusPlus/LibCxxVector.cpp b/lldb/source/Plugins/Language/CPlusPlus/LibCxxVector.cpp
new file mode 100644
index 0000000..6c448b3
--- /dev/null
+++ b/lldb/source/Plugins/Language/CPlusPlus/LibCxxVector.cpp
@@ -0,0 +1,156 @@
+//===-- LibCxxVector.cpp -----------------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "LibCxx.h"
+
+#include "lldb/Core/ConstString.h"
+#include "lldb/Core/ValueObject.h"
+#include "lldb/DataFormatters/FormattersHelpers.h"
+
+using namespace lldb;
+using namespace lldb_private;
+using namespace lldb_private::formatters;
+
+namespace lldb_private {
+    namespace formatters {
+        class LibcxxStdVectorSyntheticFrontEnd : public SyntheticChildrenFrontEnd
+        {
+        public:
+            LibcxxStdVectorSyntheticFrontEnd (lldb::ValueObjectSP valobj_sp);
+            
+            virtual size_t
+            CalculateNumChildren ();
+            
+            virtual lldb::ValueObjectSP
+            GetChildAtIndex (size_t idx);
+            
+            virtual bool
+            Update();
+            
+            virtual bool
+            MightHaveChildren ();
+            
+            virtual size_t
+            GetIndexOfChildWithName (const ConstString &name);
+            
+            virtual
+            ~LibcxxStdVectorSyntheticFrontEnd ();
+        private:
+            ValueObject* m_start;
+            ValueObject* m_finish;
+            CompilerType m_element_type;
+            uint32_t m_element_size;
+            std::map<size_t,lldb::ValueObjectSP> m_children;
+        };
+    }
+}
+
+lldb_private::formatters::LibcxxStdVectorSyntheticFrontEnd::LibcxxStdVectorSyntheticFrontEnd (lldb::ValueObjectSP valobj_sp) :
+SyntheticChildrenFrontEnd(*valobj_sp.get()),
+m_start(NULL),
+m_finish(NULL),
+m_element_type(),
+m_element_size(0),
+m_children()
+{
+    if (valobj_sp)
+        Update();
+}
+
+size_t
+lldb_private::formatters::LibcxxStdVectorSyntheticFrontEnd::CalculateNumChildren ()
+{
+    if (!m_start || !m_finish)
+        return 0;
+    uint64_t start_val = m_start->GetValueAsUnsigned(0);
+    uint64_t finish_val = m_finish->GetValueAsUnsigned(0);
+    
+    if (start_val == 0 || finish_val == 0)
+        return 0;
+    
+    if (start_val >= finish_val)
+        return 0;
+    
+    size_t num_children = (finish_val - start_val);
+    if (num_children % m_element_size)
+        return 0;
+    return num_children/m_element_size;
+}
+
+lldb::ValueObjectSP
+lldb_private::formatters::LibcxxStdVectorSyntheticFrontEnd::GetChildAtIndex (size_t idx)
+{
+    if (!m_start || !m_finish)
+        return lldb::ValueObjectSP();
+    
+    auto cached = m_children.find(idx);
+    if (cached != m_children.end())
+        return cached->second;
+    
+    uint64_t offset = idx * m_element_size;
+    offset = offset + m_start->GetValueAsUnsigned(0);
+    StreamString name;
+    name.Printf("[%" PRIu64 "]", (uint64_t)idx);
+    ValueObjectSP child_sp = CreateValueObjectFromAddress(name.GetData(), offset, m_backend.GetExecutionContextRef(), m_element_type);
+    m_children[idx] = child_sp;
+    return child_sp;
+}
+
+bool
+lldb_private::formatters::LibcxxStdVectorSyntheticFrontEnd::Update()
+{
+    m_start = m_finish = NULL;
+    m_children.clear();
+    ValueObjectSP data_type_finder_sp(m_backend.GetChildMemberWithName(ConstString("__end_cap_"),true));
+    if (!data_type_finder_sp)
+        return false;
+    data_type_finder_sp = data_type_finder_sp->GetChildMemberWithName(ConstString("__first_"),true);
+    if (!data_type_finder_sp)
+        return false;
+    m_element_type = data_type_finder_sp->GetCompilerType().GetPointeeType();
+    m_element_size = m_element_type.GetByteSize(nullptr);
+    
+    if (m_element_size > 0)
+    {
+        // store raw pointers or end up with a circular dependency
+        m_start = m_backend.GetChildMemberWithName(ConstString("__begin_"),true).get();
+        m_finish = m_backend.GetChildMemberWithName(ConstString("__end_"),true).get();
+    }
+    return false;
+}
+
+bool
+lldb_private::formatters::LibcxxStdVectorSyntheticFrontEnd::MightHaveChildren ()
+{
+    return true;
+}
+
+size_t
+lldb_private::formatters::LibcxxStdVectorSyntheticFrontEnd::GetIndexOfChildWithName (const ConstString &name)
+{
+    if (!m_start || !m_finish)
+        return UINT32_MAX;
+    return ExtractIndexFromString(name.GetCString());
+}
+
+lldb_private::formatters::LibcxxStdVectorSyntheticFrontEnd::~LibcxxStdVectorSyntheticFrontEnd ()
+{
+    // these need to stay around because they are child objects who will follow their parent's life cycle
+    // delete m_start;
+    // delete m_finish;
+}
+
+lldb_private::SyntheticChildrenFrontEnd*
+lldb_private::formatters::LibcxxStdVectorSyntheticFrontEndCreator (CXXSyntheticChildren*, lldb::ValueObjectSP valobj_sp)
+{
+    if (!valobj_sp)
+        return NULL;
+    return (new LibcxxStdVectorSyntheticFrontEnd(valobj_sp));
+}
+
diff --git a/lldb/source/Plugins/Language/CPlusPlus/LibStdcpp.cpp b/lldb/source/Plugins/Language/CPlusPlus/LibStdcpp.cpp
new file mode 100644
index 0000000..14f7527
--- /dev/null
+++ b/lldb/source/Plugins/Language/CPlusPlus/LibStdcpp.cpp
@@ -0,0 +1,258 @@
+//===-- LibStdcpp.cpp ---------------------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "LibStdcpp.h"
+
+#include "lldb/Core/DataBufferHeap.h"
+#include "lldb/Core/Error.h"
+#include "lldb/Core/Stream.h"
+#include "lldb/Core/ValueObject.h"
+#include "lldb/Core/ValueObjectConstResult.h"
+#include "lldb/DataFormatters/VectorIterator.h"
+#include "lldb/Host/Endian.h"
+#include "lldb/Symbol/ClangASTContext.h"
+#include "lldb/Target/Target.h"
+
+using namespace lldb;
+using namespace lldb_private;
+using namespace lldb_private::formatters;
+
+class LibstdcppMapIteratorSyntheticFrontEnd : public SyntheticChildrenFrontEnd
+{
+public:
+    LibstdcppMapIteratorSyntheticFrontEnd (lldb::ValueObjectSP valobj_sp);
+    
+    size_t
+    CalculateNumChildren() override;
+    
+    lldb::ValueObjectSP
+    GetChildAtIndex(size_t idx) override;
+    
+    bool
+    Update() override;
+    
+    bool
+    MightHaveChildren() override;
+    
+    size_t
+    GetIndexOfChildWithName (const ConstString &name) override;
+    
+    ~LibstdcppMapIteratorSyntheticFrontEnd() override;
+    
+private:
+    ExecutionContextRef m_exe_ctx_ref;
+    lldb::addr_t m_pair_address;
+    CompilerType m_pair_type;
+    EvaluateExpressionOptions m_options;
+    lldb::ValueObjectSP m_pair_sp;
+};
+
+/*
+ (std::_Rb_tree_iterator<std::pair<const int, std::basic_string<char, std::char_traits<char>, std::allocator<char> > > >) ibeg = {
+ (_Base_ptr) _M_node = 0x0000000100103910 {
+ (std::_Rb_tree_color) _M_color = _S_black
+ (std::_Rb_tree_node_base::_Base_ptr) _M_parent = 0x00000001001038c0
+ (std::_Rb_tree_node_base::_Base_ptr) _M_left = 0x0000000000000000
+ (std::_Rb_tree_node_base::_Base_ptr) _M_right = 0x0000000000000000
+ }
+ }
+ */
+
+LibstdcppMapIteratorSyntheticFrontEnd::LibstdcppMapIteratorSyntheticFrontEnd (lldb::ValueObjectSP valobj_sp) :
+    SyntheticChildrenFrontEnd(*valobj_sp.get()),
+    m_exe_ctx_ref(),
+    m_pair_address(0),
+    m_pair_type(),
+    m_options(),
+    m_pair_sp()
+{
+    if (valobj_sp)
+        Update();
+    m_options.SetCoerceToId(false);
+    m_options.SetUnwindOnError(true);
+    m_options.SetKeepInMemory(true);
+    m_options.SetUseDynamic(lldb::eDynamicCanRunTarget);
+}
+
+bool
+LibstdcppMapIteratorSyntheticFrontEnd::Update()
+{
+    ValueObjectSP valobj_sp = m_backend.GetSP();
+    if (!valobj_sp)
+        return false;
+    
+    TargetSP target_sp(valobj_sp->GetTargetSP());
+    
+    if (!target_sp)
+        return false;
+    
+    bool is_64bit = (target_sp->GetArchitecture().GetAddressByteSize() == 8);
+    
+    if (!valobj_sp)
+        return false;
+    m_exe_ctx_ref = valobj_sp->GetExecutionContextRef();
+    
+    ValueObjectSP _M_node_sp(valobj_sp->GetChildMemberWithName(ConstString("_M_node"), true));
+    if (!_M_node_sp)
+        return false;
+    
+    m_pair_address = _M_node_sp->GetValueAsUnsigned(0);
+    if (m_pair_address == 0)
+        return false;
+    
+    m_pair_address += (is_64bit ? 32 : 16);
+    
+    CompilerType my_type(valobj_sp->GetCompilerType());
+    if (my_type.GetNumTemplateArguments() >= 1)
+    {
+        TemplateArgumentKind kind;
+        CompilerType pair_type = my_type.GetTemplateArgument(0, kind);
+        if (kind != eTemplateArgumentKindType && kind != eTemplateArgumentKindTemplate && kind != eTemplateArgumentKindTemplateExpansion)
+            return false;
+        m_pair_type = pair_type;
+    }
+    else
+        return false;
+    
+    return true;
+}
+
+size_t
+LibstdcppMapIteratorSyntheticFrontEnd::CalculateNumChildren ()
+{
+    return 2;
+}
+
+lldb::ValueObjectSP
+LibstdcppMapIteratorSyntheticFrontEnd::GetChildAtIndex (size_t idx)
+{
+    if (m_pair_address != 0 && m_pair_type)
+    {
+        if (!m_pair_sp)
+            m_pair_sp = CreateValueObjectFromAddress("pair", m_pair_address, m_exe_ctx_ref, m_pair_type);
+        if (m_pair_sp)
+            return m_pair_sp->GetChildAtIndex(idx, true);
+    }
+    return lldb::ValueObjectSP();
+}
+
+bool
+LibstdcppMapIteratorSyntheticFrontEnd::MightHaveChildren ()
+{
+    return true;
+}
+
+size_t
+LibstdcppMapIteratorSyntheticFrontEnd::GetIndexOfChildWithName (const ConstString &name)
+{
+    if (name == ConstString("first"))
+        return 0;
+    if (name == ConstString("second"))
+        return 1;
+    return UINT32_MAX;
+}
+
+LibstdcppMapIteratorSyntheticFrontEnd::~LibstdcppMapIteratorSyntheticFrontEnd ()
+{}
+
+SyntheticChildrenFrontEnd*
+lldb_private::formatters::LibstdcppMapIteratorSyntheticFrontEndCreator (CXXSyntheticChildren*, lldb::ValueObjectSP valobj_sp)
+{
+    if (!valobj_sp)
+        return NULL;
+    return (new LibstdcppMapIteratorSyntheticFrontEnd(valobj_sp));
+}
+
+/*
+ (lldb) fr var ibeg --ptr-depth 1
+ (__gnu_cxx::__normal_iterator<int *, std::vector<int, std::allocator<int> > >) ibeg = {
+ _M_current = 0x00000001001037a0 {
+ *_M_current = 1
+ }
+ }
+ */
+
+SyntheticChildrenFrontEnd*
+lldb_private::formatters::LibStdcppVectorIteratorSyntheticFrontEndCreator (CXXSyntheticChildren*, lldb::ValueObjectSP valobj_sp)
+{
+    static ConstString g_item_name;
+    if (!g_item_name)
+        g_item_name.SetCString("_M_current");
+    if (!valobj_sp)
+        return NULL;
+    return (new VectorIteratorSyntheticFrontEnd(valobj_sp,g_item_name));
+}
+
+lldb_private::formatters::VectorIteratorSyntheticFrontEnd::VectorIteratorSyntheticFrontEnd (lldb::ValueObjectSP valobj_sp,
+                                                                                            ConstString item_name) :
+SyntheticChildrenFrontEnd(*valobj_sp.get()),
+m_exe_ctx_ref(),
+m_item_name(item_name),
+m_item_sp()
+{
+    if (valobj_sp)
+        Update();
+}
+
+bool
+lldb_private::formatters::VectorIteratorSyntheticFrontEnd::Update()
+{
+    m_item_sp.reset();
+    
+    ValueObjectSP valobj_sp = m_backend.GetSP();
+    if (!valobj_sp)
+        return false;
+    
+    if (!valobj_sp)
+        return false;
+    
+    ValueObjectSP item_ptr(valobj_sp->GetChildMemberWithName(m_item_name,true));
+    if (!item_ptr)
+        return false;
+    if (item_ptr->GetValueAsUnsigned(0) == 0)
+        return false;
+    Error err;
+    m_exe_ctx_ref = valobj_sp->GetExecutionContextRef();
+    m_item_sp = CreateValueObjectFromAddress("item", item_ptr->GetValueAsUnsigned(0), m_exe_ctx_ref, item_ptr->GetCompilerType().GetPointeeType());
+    if (err.Fail())
+        m_item_sp.reset();
+    return false;
+}
+
+size_t
+lldb_private::formatters::VectorIteratorSyntheticFrontEnd::CalculateNumChildren ()
+{
+    return 1;
+}
+
+lldb::ValueObjectSP
+lldb_private::formatters::VectorIteratorSyntheticFrontEnd::GetChildAtIndex (size_t idx)
+{
+    if (idx == 0)
+        return m_item_sp;
+    return lldb::ValueObjectSP();
+}
+
+bool
+lldb_private::formatters::VectorIteratorSyntheticFrontEnd::MightHaveChildren ()
+{
+    return true;
+}
+
+size_t
+lldb_private::formatters::VectorIteratorSyntheticFrontEnd::GetIndexOfChildWithName (const ConstString &name)
+{
+    if (name == ConstString("item"))
+        return 0;
+    return UINT32_MAX;
+}
+
+lldb_private::formatters::VectorIteratorSyntheticFrontEnd::~VectorIteratorSyntheticFrontEnd ()
+{
+}
diff --git a/lldb/source/Plugins/Language/CPlusPlus/LibStdcpp.h b/lldb/source/Plugins/Language/CPlusPlus/LibStdcpp.h
new file mode 100644
index 0000000..21b2ea4
--- /dev/null
+++ b/lldb/source/Plugins/Language/CPlusPlus/LibStdcpp.h
@@ -0,0 +1,27 @@
+//===-- LibStdCpp.h ---------------------------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef liblldb_LibStdCpp_h_
+#define liblldb_LibStdCpp_h_
+
+#include "lldb/Core/Stream.h"
+#include "lldb/Core/ValueObject.h"
+#include "lldb/DataFormatters/TypeSummary.h"
+#include "lldb/DataFormatters/TypeSynthetic.h"
+
+namespace lldb_private {
+    namespace formatters
+    {
+        SyntheticChildrenFrontEnd* LibstdcppMapIteratorSyntheticFrontEndCreator (CXXSyntheticChildren*, lldb::ValueObjectSP);
+        
+        SyntheticChildrenFrontEnd* LibStdcppVectorIteratorSyntheticFrontEndCreator (CXXSyntheticChildren*, lldb::ValueObjectSP);
+    } // namespace formatters
+} // namespace lldb_private
+
+#endif // liblldb_LibStdCpp_h_