From c530ba98a9ee2ab97fcae2fd28a366050aa35919 Mon Sep 17 00:00:00 2001 From: Sean Callanan Date: Mon, 2 May 2016 21:15:31 +0000 Subject: [PATCH] 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. llvm-svn: 268307 --- lldb/include/lldb/Symbol/ClangASTContext.h | 11 + lldb/include/lldb/Symbol/CompilerType.h | 3 + lldb/include/lldb/Symbol/GoASTContext.h | 2 + lldb/include/lldb/Symbol/JavaASTContext.h | 3 + lldb/include/lldb/Symbol/TypeSystem.h | 3 + lldb/lldb.xcodeproj/project.pbxproj | 8 + .../lldbsuite/test/lang/c/blocks/TestBlocks.py | 1 - .../Plugins/Language/CPlusPlus/BlockPointer.cpp | 225 +++++++++++++++++++++ .../Plugins/Language/CPlusPlus/BlockPointer.h | 27 +++ .../Plugins/Language/CPlusPlus/CMakeLists.txt | 1 + .../Language/CPlusPlus/CPlusPlusLanguage.cpp | 34 ++++ .../SymbolFile/DWARF/DWARFASTParserClang.cpp | 38 ++++ lldb/source/Symbol/ClangASTContext.cpp | 80 +++++++- lldb/source/Symbol/CompilerType.cpp | 7 + lldb/source/Symbol/GoASTContext.cpp | 6 + lldb/source/Symbol/JavaASTContext.cpp | 6 + 16 files changed, 450 insertions(+), 5 deletions(-) create mode 100644 lldb/source/Plugins/Language/CPlusPlus/BlockPointer.cpp create mode 100644 lldb/source/Plugins/Language/CPlusPlus/BlockPointer.h diff --git a/lldb/include/lldb/Symbol/ClangASTContext.h b/lldb/include/lldb/Symbol/ClangASTContext.h index edfa3d1..593440c 100644 --- a/lldb/include/lldb/Symbol/ClangASTContext.h +++ b/lldb/include/lldb/Symbol/ClangASTContext.h @@ -303,6 +303,11 @@ public: } CompilerType + CreateStructForIdentifier (const ConstString &type_name, + const std::initializer_list< std::pair < const char *, CompilerType > >& type_fields, + bool packed = false); + + CompilerType GetOrCreateStructForIdentifier (const ConstString &type_name, const std::initializer_list< std::pair < const char *, CompilerType > >& type_fields, bool packed = false); @@ -476,6 +481,9 @@ public: SetFunctionParameters (clang::FunctionDecl *function_decl, clang::ParmVarDecl **params, unsigned num_params); + + CompilerType + CreateBlockPointerType (const CompilerType &function_type); //------------------------------------------------------------------ // Array Types @@ -683,6 +691,9 @@ public: IsFunctionPointerType (lldb::opaque_compiler_type_t type) override; bool + IsBlockPointerType (lldb::opaque_compiler_type_t type, CompilerType *function_pointer_type_ptr) override; + + bool IsIntegerType (lldb::opaque_compiler_type_t type, bool &is_signed) override; static bool diff --git a/lldb/include/lldb/Symbol/CompilerType.h b/lldb/include/lldb/Symbol/CompilerType.h index 4f3ecc5..c2d1d75 100644 --- a/lldb/include/lldb/Symbol/CompilerType.h +++ b/lldb/include/lldb/Symbol/CompilerType.h @@ -149,6 +149,9 @@ public: IsFunctionPointerType () const; bool + IsBlockPointerType (CompilerType *function_pointer_type_ptr) const; + + bool IsIntegerType (bool &is_signed) const; bool diff --git a/lldb/include/lldb/Symbol/GoASTContext.h b/lldb/include/lldb/Symbol/GoASTContext.h index 09d79ba..d37ddfa 100644 --- a/lldb/include/lldb/Symbol/GoASTContext.h +++ b/lldb/include/lldb/Symbol/GoASTContext.h @@ -176,6 +176,8 @@ class GoASTContext : public TypeSystem CompilerType GetFunctionArgumentAtIndex(lldb::opaque_compiler_type_t type, const size_t index) override; bool IsFunctionPointerType(lldb::opaque_compiler_type_t type) override; + + bool IsBlockPointerType (lldb::opaque_compiler_type_t type, CompilerType *function_pointer_type_ptr) override; bool IsIntegerType(lldb::opaque_compiler_type_t type, bool &is_signed) override; diff --git a/lldb/include/lldb/Symbol/JavaASTContext.h b/lldb/include/lldb/Symbol/JavaASTContext.h index 7d9e801..12f162d 100644 --- a/lldb/include/lldb/Symbol/JavaASTContext.h +++ b/lldb/include/lldb/Symbol/JavaASTContext.h @@ -121,6 +121,9 @@ public: bool IsFunctionPointerType(lldb::opaque_compiler_type_t type) override; + + bool + IsBlockPointerType (lldb::opaque_compiler_type_t type, CompilerType *function_pointer_type_ptr) override; bool IsIntegerType(lldb::opaque_compiler_type_t type, bool &is_signed) override; diff --git a/lldb/include/lldb/Symbol/TypeSystem.h b/lldb/include/lldb/Symbol/TypeSystem.h index 7a0bd4f..06a6b2f 100644 --- a/lldb/include/lldb/Symbol/TypeSystem.h +++ b/lldb/include/lldb/Symbol/TypeSystem.h @@ -210,6 +210,9 @@ public: IsFunctionPointerType (lldb::opaque_compiler_type_t type) = 0; virtual bool + IsBlockPointerType (lldb::opaque_compiler_type_t type, CompilerType *function_pointer_type_ptr) = 0; + + virtual bool IsIntegerType (lldb::opaque_compiler_type_t type, bool &is_signed) = 0; virtual bool diff --git a/lldb/lldb.xcodeproj/project.pbxproj b/lldb/lldb.xcodeproj/project.pbxproj index 2f6d134..681e2e2 100644 --- a/lldb/lldb.xcodeproj/project.pbxproj +++ b/lldb/lldb.xcodeproj/project.pbxproj @@ -693,6 +693,8 @@ 49DA65031485C92A005FF180 /* AppleObjCDeclVendor.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 49DA65021485C92A005FF180 /* AppleObjCDeclVendor.cpp */; }; 49DCF6FE170E6B4A0092F75E /* IRMemoryMap.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 49DCF6FD170E6B4A0092F75E /* IRMemoryMap.cpp */; }; 49DCF702170E70120092F75E /* Materializer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 49DCF700170E70120092F75E /* Materializer.cpp */; }; + 49DEF1221CD7BD90006A7C7D /* BlockPointer.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = 49DEF1201CD7BD90006A7C7D /* BlockPointer.h */; }; + 49DEF1251CD7C6DF006A7C7D /* BlockPointer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 49DEF11F1CD7BD90006A7C7D /* BlockPointer.cpp */; }; 49E4F66B1C9CAD16008487EA /* DiagnosticManager.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 49E4F6681C9CAD12008487EA /* DiagnosticManager.cpp */; }; 4C0083401B9F9BA900D5CF24 /* UtilityFunction.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4C00833F1B9F9BA900D5CF24 /* UtilityFunction.cpp */; }; 4C2479BD1BA39295009C9A7B /* FunctionCaller.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4C0083321B9A5DE200D5CF24 /* FunctionCaller.cpp */; }; @@ -1119,6 +1121,7 @@ dstPath = "$(DEVELOPER_DIR)/usr/share/man/man1/"; dstSubfolderSpec = 0; files = ( + 49DEF1221CD7BD90006A7C7D /* BlockPointer.h in CopyFiles */, AF90106515AB7D3600FF120D /* lldb.1 in CopyFiles */, ); runOnlyForDeploymentPostprocessing = 1; @@ -2346,6 +2349,8 @@ 49DCF6FD170E6B4A0092F75E /* IRMemoryMap.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = IRMemoryMap.cpp; path = source/Expression/IRMemoryMap.cpp; sourceTree = ""; }; 49DCF6FF170E6FD90092F75E /* Materializer.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = Materializer.h; path = include/lldb/Expression/Materializer.h; sourceTree = ""; }; 49DCF700170E70120092F75E /* Materializer.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = Materializer.cpp; path = source/Expression/Materializer.cpp; sourceTree = ""; }; + 49DEF11F1CD7BD90006A7C7D /* BlockPointer.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = BlockPointer.cpp; path = Language/CPlusPlus/BlockPointer.cpp; sourceTree = ""; }; + 49DEF1201CD7BD90006A7C7D /* BlockPointer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = BlockPointer.h; path = Language/CPlusPlus/BlockPointer.h; sourceTree = ""; }; 49E45FA911F660DC008F7B28 /* CompilerType.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CompilerType.h; path = include/lldb/Symbol/CompilerType.h; sourceTree = ""; }; 49E45FAD11F660FE008F7B28 /* CompilerType.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = CompilerType.cpp; path = source/Symbol/CompilerType.cpp; sourceTree = ""; }; 49E4F6681C9CAD12008487EA /* DiagnosticManager.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = DiagnosticManager.cpp; path = source/Expression/DiagnosticManager.cpp; sourceTree = ""; }; @@ -5586,6 +5591,8 @@ 945261B01B9A11BE00BF138D /* Formatters */ = { isa = PBXGroup; children = ( + 49DEF1201CD7BD90006A7C7D /* BlockPointer.h */, + 49DEF11F1CD7BD90006A7C7D /* BlockPointer.cpp */, 945261B41B9A11E800BF138D /* CxxStringTypes.h */, 945261B31B9A11E800BF138D /* CxxStringTypes.cpp */, 945261B61B9A11E800BF138D /* LibCxx.h */, @@ -7047,6 +7054,7 @@ 26E152261419CAD4007967D0 /* ObjectFilePECOFF.cpp in Sources */, B2462247141AD37D00F3D409 /* OptionGroupWatchpoint.cpp in Sources */, 94B638631B8FB7F1004FE1E4 /* ObjCPlusPlusLanguage.cpp in Sources */, + 49DEF1251CD7C6DF006A7C7D /* BlockPointer.cpp in Sources */, 49A71FE7141FFA5C00D59478 /* IRInterpreter.cpp in Sources */, 49A71FE8141FFACF00D59478 /* DataEncoder.cpp in Sources */, 23DDF226196C3EE600BB8417 /* CommandOptionValidators.cpp in Sources */, diff --git a/lldb/packages/Python/lldbsuite/test/lang/c/blocks/TestBlocks.py b/lldb/packages/Python/lldbsuite/test/lang/c/blocks/TestBlocks.py index c1099c3..0cc9456 100644 --- a/lldb/packages/Python/lldbsuite/test/lang/c/blocks/TestBlocks.py +++ b/lldb/packages/Python/lldbsuite/test/lang/c/blocks/TestBlocks.py @@ -36,7 +36,6 @@ class BlocksTestCase(TestBase): self.wait_for_breakpoint() - @unittest2.expectedFailure("rdar://problem/10413887 - Call blocks in expressions") @skipUnlessDarwin def test_expr(self): self.launch_common() 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(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 @@ CPlusPlusLanguage::GetHardcodedSummaries () } 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 @@ CPlusPlusLanguage::GetHardcodedSynthetics () } 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; diff --git a/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp b/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp index 9451e49..2d5b6e1 100644 --- a/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp +++ b/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp @@ -368,6 +368,44 @@ DWARFASTParserClang::ParseTypeFromDWARF (const SymbolContext& sc, if (!clang_type && (encoding_data_type == Type::eEncodingIsPointerUID || encoding_data_type == Type::eEncodingIsTypedefUID) && sc.comp_unit != NULL) { + if (tag == DW_TAG_pointer_type) + { + DWARFDIE target_die = die.GetReferencedDIE(DW_AT_type); + + if (target_die.GetAttributeValueAsUnsigned(DW_AT_APPLE_block, 0)) + { + // Blocks have a __FuncPtr inside them which is a pointer to a function of the proper type. + + for (DWARFDIE child_die = target_die.GetFirstChild(); + child_die.IsValid(); + child_die = child_die.GetSibling()) + { + if (!strcmp(child_die.GetAttributeValueAsString(DW_AT_name, ""), "__FuncPtr")) + { + DWARFDIE function_pointer_type = child_die.GetReferencedDIE(DW_AT_type); + + if (function_pointer_type) + { + DWARFDIE function_type = function_pointer_type.GetReferencedDIE(DW_AT_type); + + bool function_type_is_new_pointer; + TypeSP lldb_function_type_sp = ParseTypeFromDWARF(sc, function_type, log, &function_type_is_new_pointer); + + if (lldb_function_type_sp) + { + clang_type = m_ast.CreateBlockPointerType(lldb_function_type_sp->GetForwardCompilerType()); + encoding_data_type = Type::eEncodingIsUID; + encoding_uid.Clear(); + resolve_state = Type::eResolveStateFull; + } + } + + break; + } + } + } + } + bool translation_unit_is_objc = (sc.comp_unit->GetLanguage() == eLanguageTypeObjC || sc.comp_unit->GetLanguage() == eLanguageTypeObjC_plus_plus); if (translation_unit_is_objc) diff --git a/lldb/source/Symbol/ClangASTContext.cpp b/lldb/source/Symbol/ClangASTContext.cpp index 6b61646..5905a9a 100644 --- a/lldb/source/Symbol/ClangASTContext.cpp +++ b/lldb/source/Symbol/ClangASTContext.cpp @@ -89,6 +89,7 @@ #include "lldb/Target/ObjCLanguageRuntime.h" #include "lldb/Target/Process.h" #include "lldb/Target/Target.h" +#include "lldb/Utility/LLDBAssert.h" #include "Plugins/SymbolFile/DWARF/DWARFASTParserClang.h" #include "Plugins/SymbolFile/PDB/PDBASTParser.h" @@ -2044,6 +2045,13 @@ ClangASTContext::SetFunctionParameters (FunctionDecl *function_decl, ParmVarDecl function_decl->setParams (ArrayRef(params, num_params)); } +CompilerType +ClangASTContext::CreateBlockPointerType (const CompilerType &function_type) +{ + QualType block_type = m_ast_ap->getBlockPointerType(clang::QualType::getFromOpaquePtr(function_type.GetOpaqueQualType())); + + return CompilerType (this, block_type.getAsOpaquePtr()); +} #pragma mark Array Types @@ -2081,13 +2089,17 @@ ClangASTContext::CreateArrayType (const CompilerType &element_type, } CompilerType -ClangASTContext::GetOrCreateStructForIdentifier (const ConstString &type_name, - const std::initializer_list< std::pair < const char *, CompilerType > >& type_fields, - bool packed) +ClangASTContext::CreateStructForIdentifier (const ConstString &type_name, + const std::initializer_list< std::pair < const char *, CompilerType > >& type_fields, + bool packed) { CompilerType type; - if ((type = GetTypeForIdentifier(type_name)).IsValid()) + if (!type_name.IsEmpty() && (type = GetTypeForIdentifier(type_name)).IsValid()) + { + lldbassert("Trying to create a type for an existing name"); return type; + } + type = CreateRecordType(nullptr, lldb::eAccessPublic, type_name.GetCString(), clang::TTK_Struct, lldb::eLanguageTypeC); StartTagDeclarationDefinition(type); for (const auto& field : type_fields) @@ -2098,6 +2110,20 @@ ClangASTContext::GetOrCreateStructForIdentifier (const ConstString &type_name, return type; } +CompilerType +ClangASTContext::GetOrCreateStructForIdentifier (const ConstString &type_name, + const std::initializer_list< std::pair < const char *, CompilerType > >& type_fields, + bool packed) +{ + CompilerType type; + if ((type = GetTypeForIdentifier(type_name)).IsValid()) + return type; + + return CreateStructForIdentifier (type_name, + type_fields, + packed); +} + #pragma mark Enumeration Types CompilerType @@ -3177,6 +3203,52 @@ ClangASTContext::IsFunctionPointerType (lldb::opaque_compiler_type_t type) } bool +ClangASTContext::IsBlockPointerType (lldb::opaque_compiler_type_t type, CompilerType *function_pointer_type_ptr) +{ + if (type) + { + clang::QualType qual_type (GetCanonicalQualType(type)); + + if (qual_type->isBlockPointerType()) + { + if (function_pointer_type_ptr) + { + const clang::BlockPointerType *block_pointer_type = qual_type->getAs(); + QualType pointee_type = block_pointer_type->getPointeeType(); + QualType function_pointer_type = m_ast_ap->getPointerType(pointee_type); + *function_pointer_type_ptr = CompilerType (getASTContext(), function_pointer_type); + } + return true; + } + + const clang::Type::TypeClass type_class = qual_type->getTypeClass(); + switch (type_class) + { + default: + break; + case clang::Type::Typedef: + return IsBlockPointerType (llvm::cast(qual_type)->getDecl()->getUnderlyingType().getAsOpaquePtr(), function_pointer_type_ptr); + case clang::Type::Auto: + return IsBlockPointerType (llvm::cast(qual_type)->getDeducedType().getAsOpaquePtr(), function_pointer_type_ptr); + case clang::Type::Elaborated: + return IsBlockPointerType (llvm::cast(qual_type)->getNamedType().getAsOpaquePtr(), function_pointer_type_ptr); + case clang::Type::Paren: + return IsBlockPointerType (llvm::cast(qual_type)->desugar().getAsOpaquePtr(), function_pointer_type_ptr); + + case clang::Type::LValueReference: + case clang::Type::RValueReference: + { + const clang::ReferenceType *reference_type = llvm::cast(qual_type.getTypePtr()); + if (reference_type) + return IsBlockPointerType(reference_type->getPointeeType().getAsOpaquePtr(), function_pointer_type_ptr); + } + break; + } + } + return false; +} + +bool ClangASTContext::IsIntegerType (lldb::opaque_compiler_type_t type, bool &is_signed) { if (!type) diff --git a/lldb/source/Symbol/CompilerType.cpp b/lldb/source/Symbol/CompilerType.cpp index 000a949..e5be597 100644 --- a/lldb/source/Symbol/CompilerType.cpp +++ b/lldb/source/Symbol/CompilerType.cpp @@ -177,7 +177,14 @@ CompilerType::IsFunctionPointerType () const if (IsValid()) return m_type_system->IsFunctionPointerType(m_type); return false; +} +bool +CompilerType::IsBlockPointerType (CompilerType *function_pointer_type_ptr) const +{ + if (IsValid()) + return m_type_system->IsBlockPointerType(m_type, function_pointer_type_ptr); + return 0; } bool diff --git a/lldb/source/Symbol/GoASTContext.cpp b/lldb/source/Symbol/GoASTContext.cpp index 1993f23..faca778 100644 --- a/lldb/source/Symbol/GoASTContext.cpp +++ b/lldb/source/Symbol/GoASTContext.cpp @@ -538,6 +538,12 @@ GoASTContext::IsFunctionPointerType(lldb::opaque_compiler_type_t type) } bool +GoASTContext::IsBlockPointerType (lldb::opaque_compiler_type_t type, CompilerType *function_pointer_type_ptr) +{ + return false; +} + +bool GoASTContext::IsIntegerType(lldb::opaque_compiler_type_t type, bool &is_signed) { is_signed = false; diff --git a/lldb/source/Symbol/JavaASTContext.cpp b/lldb/source/Symbol/JavaASTContext.cpp index 8f06eef..1cc1472 100644 --- a/lldb/source/Symbol/JavaASTContext.cpp +++ b/lldb/source/Symbol/JavaASTContext.cpp @@ -629,6 +629,12 @@ JavaASTContext::IsFunctionPointerType(lldb::opaque_compiler_type_t type) } bool +JavaASTContext::IsBlockPointerType (lldb::opaque_compiler_type_t type, CompilerType *function_pointer_type_ptr) +{ + return false; +} + +bool JavaASTContext::IsIntegerType(lldb::opaque_compiler_type_t type, bool &is_signed) { if (JavaPrimitiveType *ptype = llvm::dyn_cast(static_cast(type))) -- 2.7.4