Import block pointers from DWARF as Clang block pointers, not as structs.

Also added a data formatter that presents them as structs if you use frame
variable to look at their contents.  Now the blocks testcase works.

<rdar://problem/15984431>

llvm-svn: 268307
diff --git a/lldb/source/Plugins/Language/CPlusPlus/BlockPointer.cpp b/lldb/source/Plugins/Language/CPlusPlus/BlockPointer.cpp
new file mode 100644
index 0000000..92e30d5
--- /dev/null
+++ b/lldb/source/Plugins/Language/CPlusPlus/BlockPointer.cpp
@@ -0,0 +1,225 @@
+//===-- BlockPointer.cpp ----------------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
+#include "BlockPointer.h"
+
+#include "lldb/Core/ValueObject.h"
+#include "lldb/DataFormatters/FormattersHelpers.h"
+#include "lldb/Symbol/ClangASTContext.h"
+#include "lldb/Symbol/ClangASTImporter.h"
+#include "lldb/Symbol/CompilerType.h"
+#include "lldb/Symbol/TypeSystem.h"
+#include "lldb/Target/Target.h"
+
+#include "lldb/Utility/LLDBAssert.h"
+
+using namespace lldb;
+using namespace lldb_private;
+using namespace lldb_private::formatters;
+
+namespace lldb_private
+{
+namespace formatters
+{
+
+class BlockPointerSyntheticFrontEnd : public SyntheticChildrenFrontEnd
+{
+public:
+    BlockPointerSyntheticFrontEnd(lldb::ValueObjectSP valobj_sp)
+        : SyntheticChildrenFrontEnd(*valobj_sp),
+          m_block_struct_type()
+    {
+        CompilerType block_pointer_type(m_backend.GetCompilerType());
+        CompilerType function_pointer_type;
+        block_pointer_type.IsBlockPointerType(&function_pointer_type);
+        
+        TargetSP target_sp(m_backend.GetTargetSP());
+        
+        if (!target_sp)
+        {
+            return;
+        }
+        
+        Error err;
+        TypeSystem *type_system = target_sp->GetScratchTypeSystemForLanguage(&err, lldb::eLanguageTypeC_plus_plus);
+        
+        if (!err.Success() || !type_system)
+        {
+            return;
+        }
+        
+        ClangASTContext *clang_ast_context = llvm::dyn_cast<ClangASTContext>(type_system);
+        
+        if (!clang_ast_context)
+        {
+            return;
+        }
+        
+        ClangASTImporterSP clang_ast_importer = target_sp->GetClangASTImporter();
+        
+        if (!clang_ast_importer)
+        {
+            return;
+        }
+        
+        const char *const   isa_name("__isa");
+        const CompilerType  isa_type = clang_ast_context->GetBasicType(lldb::eBasicTypeObjCClass);
+        const char *const   flags_name("__flags");
+        const CompilerType  flags_type = clang_ast_context->GetBasicType(lldb::eBasicTypeInt);
+        const char *const   reserved_name("__reserved");
+        const CompilerType  reserved_type = clang_ast_context->GetBasicType(lldb::eBasicTypeInt);
+        const char *const   FuncPtr_name("__FuncPtr");
+        const CompilerType  FuncPtr_type = clang_ast_importer->CopyType(*clang_ast_context, function_pointer_type);
+        
+        m_block_struct_type = clang_ast_context->CreateStructForIdentifier(ConstString(),
+                                                                           {
+                                                                               {isa_name, isa_type},
+                                                                               {flags_name, flags_type},
+                                                                               {reserved_name, reserved_type},
+                                                                               {FuncPtr_name, FuncPtr_type}
+                                                                           });
+
+    }
+
+    ~BlockPointerSyntheticFrontEnd() override = default;
+
+    size_t
+    CalculateNumChildren() override
+    {
+        const bool omit_empty_base_classes = false;
+        return m_block_struct_type.GetNumChildren(omit_empty_base_classes);
+    }
+
+    lldb::ValueObjectSP
+    GetChildAtIndex(size_t idx) override
+    {
+        if (!m_block_struct_type.IsValid())
+        {
+            return lldb::ValueObjectSP();
+        }
+        
+        if (idx >= CalculateNumChildren())
+        {
+            return lldb::ValueObjectSP();
+        }
+        
+        const bool thread_and_frame_only_if_stopped = true;
+        ExecutionContext exe_ctx = m_backend.GetExecutionContextRef().Lock(thread_and_frame_only_if_stopped);
+        const bool transparent_pointers = false;
+        const bool omit_empty_base_classes = false;
+        const bool ignore_array_bounds = false;
+        ValueObject *value_object = nullptr;
+    
+        std::string child_name;
+        uint32_t child_byte_size = 0;
+        int32_t child_byte_offset = 0;
+        uint32_t child_bitfield_bit_size = 0;
+        uint32_t child_bitfield_bit_offset = 0;
+        bool child_is_base_class = false;
+        bool child_is_deref_of_parent = false;
+        uint64_t language_flags = 0;
+        
+        const CompilerType child_type = m_block_struct_type.GetChildCompilerTypeAtIndex(&exe_ctx, idx, transparent_pointers, omit_empty_base_classes, ignore_array_bounds, child_name, child_byte_size, child_byte_offset, child_bitfield_bit_size, child_bitfield_bit_offset, child_is_base_class, child_is_deref_of_parent, value_object, language_flags);
+        
+        ValueObjectSP struct_pointer_sp = m_backend.Cast(m_block_struct_type.GetPointerType());
+        
+        if (!struct_pointer_sp)
+        {
+            return lldb::ValueObjectSP();
+        }
+        
+        Error err;
+        ValueObjectSP struct_sp = struct_pointer_sp->Dereference(err);
+        
+        if (!struct_sp || !err.Success())
+        {
+            return lldb::ValueObjectSP();
+        }
+        
+        ValueObjectSP child_sp(struct_sp->GetSyntheticChildAtOffset(child_byte_offset,
+                                                                    child_type,
+                                                                    true,
+                                                                    ConstString(child_name.c_str(), child_name.size())));
+
+        return child_sp;
+    }
+
+    // return true if this object is now safe to use forever without
+    // ever updating again; the typical (and tested) answer here is
+    // 'false'
+    bool
+    Update() override
+    {
+        return false;
+    }
+
+    // maybe return false if the block pointer is, say, null
+    bool
+    MightHaveChildren() override
+    {
+        return true;
+    }
+
+    size_t
+    GetIndexOfChildWithName(const ConstString &name) override
+    {
+        if (!m_block_struct_type.IsValid())
+            return UINT32_MAX;
+        
+        const bool omit_empty_base_classes = false;
+        return m_block_struct_type.GetIndexOfChildWithName(name.AsCString(), omit_empty_base_classes);
+    }
+
+private:
+    CompilerType m_block_struct_type;
+};
+
+} // namespace formatters
+} // namespace lldb_private
+
+bool
+lldb_private::formatters::BlockPointerSummaryProvider(ValueObject &valobj, Stream &s, const TypeSummaryOptions &)
+{
+    lldb_private::SyntheticChildrenFrontEnd *synthetic_children = BlockPointerSyntheticFrontEndCreator(nullptr, valobj.GetSP());
+    if (!synthetic_children)
+    {
+        return false;
+    }
+
+    synthetic_children->Update();
+
+    static const ConstString s_FuncPtr_name("__FuncPtr");
+    
+    lldb::ValueObjectSP child_sp = synthetic_children->GetChildAtIndex(synthetic_children->GetIndexOfChildWithName(s_FuncPtr_name));
+    
+    if (!child_sp)
+    {
+        return false;
+    }
+    
+    lldb::ValueObjectSP qualified_child_representation_sp = child_sp->GetQualifiedRepresentationIfAvailable(lldb::eDynamicDontRunTarget, true);
+
+    const char *child_value = qualified_child_representation_sp->GetValueAsCString();
+
+    s.Printf("%s", child_value);
+
+    return true;
+}
+
+lldb_private::SyntheticChildrenFrontEnd *
+lldb_private::formatters::BlockPointerSyntheticFrontEndCreator(CXXSyntheticChildren *, lldb::ValueObjectSP valobj_sp)
+{
+    if (!valobj_sp)
+        return nullptr;
+    return new BlockPointerSyntheticFrontEnd(valobj_sp);
+}
diff --git a/lldb/source/Plugins/Language/CPlusPlus/BlockPointer.h b/lldb/source/Plugins/Language/CPlusPlus/BlockPointer.h
new file mode 100644
index 0000000..5e6c748
--- /dev/null
+++ b/lldb/source/Plugins/Language/CPlusPlus/BlockPointer.h
@@ -0,0 +1,27 @@
+//===-- BlockPointer.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_BlockPointer_h_
+#define liblldb_BlockPointer_h_
+
+#include "lldb/lldb-forward.h"
+
+namespace lldb_private
+{
+namespace formatters
+{
+bool
+BlockPointerSummaryProvider(ValueObject &, Stream &, const TypeSummaryOptions &);
+
+SyntheticChildrenFrontEnd *
+BlockPointerSyntheticFrontEndCreator(CXXSyntheticChildren *, lldb::ValueObjectSP);
+} // namespace formatters
+} // namespace lldb_private
+
+#endif // liblldb_BlockPointer_h_
diff --git a/lldb/source/Plugins/Language/CPlusPlus/CMakeLists.txt b/lldb/source/Plugins/Language/CPlusPlus/CMakeLists.txt
index 4efb681..de0dc99 100644
--- a/lldb/source/Plugins/Language/CPlusPlus/CMakeLists.txt
+++ b/lldb/source/Plugins/Language/CPlusPlus/CMakeLists.txt
@@ -1,4 +1,5 @@
 add_lldb_library(lldbPluginCPlusPlusLanguage
+  BlockPointer.cpp
   CPlusPlusLanguage.cpp
   CxxStringTypes.cpp
   LibCxx.cpp
diff --git a/lldb/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.cpp b/lldb/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.cpp
index 829a79e..cf4b129 100644
--- a/lldb/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.cpp
+++ b/lldb/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.cpp
@@ -29,6 +29,7 @@
 #include "lldb/DataFormatters/FormattersHelpers.h"
 #include "lldb/DataFormatters/VectorType.h"
 
+#include "BlockPointer.h"
 #include "CxxStringTypes.h"
 #include "LibCxx.h"
 #include "LibCxxAtomic.h"
@@ -769,6 +770,25 @@
                                             }
                                             return nullptr;
                                         });
+        g_formatters.push_back(
+                               [](lldb_private::ValueObject& valobj,
+                                  lldb::DynamicValueType,
+                                  FormatManager& fmt_mgr) -> TypeSummaryImpl::SharedPointer {
+                                   static CXXFunctionSummaryFormat::SharedPointer formatter_sp(new CXXFunctionSummaryFormat(TypeSummaryImpl::Flags()
+                                                                                                                            .SetCascades(true)
+                                                                                                                            .SetDontShowChildren(true)
+                                                                                                                            .SetHideItemNames(true)
+                                                                                                                            .SetShowMembersOneLiner(true)
+                                                                                                                            .SetSkipPointers(true)
+                                                                                                                            .SetSkipReferences(false),
+                                                                                                                            lldb_private::formatters::BlockPointerSummaryProvider,
+                                                                                                                            "block pointer summary provider"));
+                                   if (valobj.GetCompilerType().IsBlockPointerType(nullptr))
+                                   {
+                                       return formatter_sp;
+                                   }
+                                   return nullptr;
+                               });
     });
     
     return g_formatters;
@@ -796,6 +816,20 @@
                                              }
                                              return nullptr;
                                          });
+        g_formatters.push_back(
+                                         [](lldb_private::ValueObject& valobj,
+                                            lldb::DynamicValueType,
+                                            FormatManager& fmt_mgr) -> SyntheticChildren::SharedPointer {
+                                             static CXXSyntheticChildren::SharedPointer formatter_sp(new CXXSyntheticChildren(SyntheticChildren::Flags().SetCascades(true).SetSkipPointers(true).SetSkipReferences(true).SetNonCacheable(true),
+                                                                                                                              "block pointer synthetic children",
+                                                                                                                              lldb_private::formatters::BlockPointerSyntheticFrontEndCreator));
+                                             if (valobj.GetCompilerType().IsBlockPointerType(nullptr))
+                                             {
+                                                 return formatter_sp;
+                                             }
+                                             return nullptr;
+                                         });
+
     });
     
     return g_formatters;