diff options
-rw-r--r-- | lldb/include/lldb/Symbol/Type.h | 5 | ||||
-rw-r--r-- | lldb/source/Symbol/ClangASTContext.cpp | 172 | ||||
-rw-r--r-- | lldb/source/Symbol/Type.cpp | 7 | ||||
-rw-r--r-- | lldb/test/python_api/objc_type/Makefile | 9 | ||||
-rw-r--r-- | lldb/test/python_api/objc_type/TestObjCType.py | 79 | ||||
-rw-r--r-- | lldb/test/python_api/objc_type/main.m | 52 |
6 files changed, 274 insertions, 50 deletions
diff --git a/lldb/include/lldb/Symbol/Type.h b/lldb/include/lldb/Symbol/Type.h index 19cf4c84bc6..a85d1cd31f2 100644 --- a/lldb/include/lldb/Symbol/Type.h +++ b/lldb/include/lldb/Symbol/Type.h @@ -444,6 +444,9 @@ public: { return m_type_sp; } + + ConstString + GetName (); bool GetDescription (lldb_private::Stream &strm, @@ -524,6 +527,8 @@ public: m_bitfield_bit_size (0), m_is_bitfield (false) { + if (m_type_impl_sp) + m_name = m_type_impl_sp->GetName(); } const lldb::TypeImplSP & diff --git a/lldb/source/Symbol/ClangASTContext.cpp b/lldb/source/Symbol/ClangASTContext.cpp index 73ed50931e1..8ec89e74060 100644 --- a/lldb/source/Symbol/ClangASTContext.cpp +++ b/lldb/source/Symbol/ClangASTContext.cpp @@ -3384,6 +3384,19 @@ ClangASTContext::GetNumDirectBaseClasses (clang::ASTContext *ast, clang_type_t c } break; + case clang::Type::ObjCObjectPointer: + if (GetCompleteQualType (ast, qual_type)) + { + const ObjCObjectPointerType *objc_class_type = qual_type->getAsObjCInterfacePointerType(); + if (objc_class_type) + { + ObjCInterfaceDecl *class_interface_decl = objc_class_type->getInterfaceDecl(); + if (class_interface_decl && class_interface_decl->getSuperClass()) + count = 1; + } + } + break; + case clang::Type::ObjCObject: case clang::Type::ObjCInterface: if (GetCompleteQualType (ast, qual_type)) @@ -3498,6 +3511,20 @@ ClangASTContext::GetNumFields (clang::ASTContext *ast, clang_type_t clang_type) count = ClangASTContext::GetNumFields(ast, cast<clang::ParenType>(qual_type)->desugar().getAsOpaquePtr()); break; + case clang::Type::ObjCObjectPointer: + if (GetCompleteQualType (ast, qual_type)) + { + const ObjCObjectPointerType *objc_class_type = qual_type->getAsObjCInterfacePointerType(); + if (objc_class_type) + { + ObjCInterfaceDecl *class_interface_decl = objc_class_type->getInterfaceDecl(); + + if (class_interface_decl) + count = class_interface_decl->ivar_size(); + } + } + break; + case clang::Type::ObjCObject: case clang::Type::ObjCInterface: if (GetCompleteQualType (ast, qual_type)) @@ -3561,6 +3588,27 @@ ClangASTContext::GetDirectBaseClassAtIndex (clang::ASTContext *ast, } } break; + + case clang::Type::ObjCObjectPointer: + if (idx == 0 && GetCompleteQualType (ast, qual_type)) + { + const ObjCObjectPointerType *objc_class_type = qual_type->getAsObjCInterfacePointerType(); + if (objc_class_type) + { + ObjCInterfaceDecl *class_interface_decl = objc_class_type->getInterfaceDecl(); + if (class_interface_decl) + { + ObjCInterfaceDecl *superclass_interface_decl = class_interface_decl->getSuperClass(); + if (superclass_interface_decl) + { + if (bit_offset_ptr) + *bit_offset_ptr = 0; + return ast->getObjCInterfaceType(superclass_interface_decl).getAsOpaquePtr(); + } + } + } + } + break; case clang::Type::ObjCObject: case clang::Type::ObjCInterface: @@ -3675,10 +3723,69 @@ ClangASTContext::GetVirtualBaseClassAtIndex (clang::ASTContext *ast, return NULL; } +static clang_type_t +GetObjCFieldAtIndex (clang::ASTContext *ast, + ObjCInterfaceDecl * class_interface_decl, + size_t idx, + std::string& name, + uint64_t *bit_offset_ptr, + uint32_t *bitfield_bit_size_ptr, + bool *is_bitfield_ptr) +{ + if (class_interface_decl) + { + if (idx < (class_interface_decl->ivar_size())) + { + ObjCInterfaceDecl::ivar_iterator ivar_pos, ivar_end = class_interface_decl->ivar_end(); + uint32_t ivar_idx = 0; + + for (ivar_pos = class_interface_decl->ivar_begin(); ivar_pos != ivar_end; ++ivar_pos, ++ivar_idx) + { + if (ivar_idx == idx) + { + const ObjCIvarDecl* ivar_decl = *ivar_pos; + + QualType ivar_qual_type(ivar_decl->getType()); + + name.assign(ivar_decl->getNameAsString()); + + if (bit_offset_ptr) + { + const ASTRecordLayout &interface_layout = ast->getASTObjCInterfaceLayout(class_interface_decl); + *bit_offset_ptr = interface_layout.getFieldOffset (ivar_idx); + } + + const bool is_bitfield = ivar_pos->isBitField(); + + if (bitfield_bit_size_ptr) + { + *bitfield_bit_size_ptr = 0; + + if (is_bitfield && ast) + { + Expr *bitfield_bit_size_expr = ivar_pos->getBitWidth(); + llvm::APSInt bitfield_apsint; + if (bitfield_bit_size_expr && bitfield_bit_size_expr->EvaluateAsInt(bitfield_apsint, *ast)) + { + *bitfield_bit_size_ptr = bitfield_apsint.getLimitedValue(); + } + } + } + if (is_bitfield_ptr) + *is_bitfield_ptr = is_bitfield; + + return ivar_qual_type.getAsOpaquePtr(); + } + } + } + } + return NULL; +} + clang_type_t -ClangASTContext::GetFieldAtIndex (clang::ASTContext *ast, +ClangASTContext::GetFieldAtIndex (clang::ASTContext *ast, clang_type_t clang_type, - size_t idx, + size_t idx, std::string& name, uint64_t *bit_offset_ptr, uint32_t *bitfield_bit_size_ptr, @@ -3739,6 +3846,18 @@ ClangASTContext::GetFieldAtIndex (clang::ASTContext *ast, } break; + case clang::Type::ObjCObjectPointer: + if (GetCompleteQualType (ast, qual_type)) + { + const ObjCObjectPointerType *objc_class_type = qual_type->getAsObjCInterfacePointerType(); + if (objc_class_type) + { + ObjCInterfaceDecl *class_interface_decl = objc_class_type->getInterfaceDecl(); + return GetObjCFieldAtIndex(ast, class_interface_decl, idx, name, bit_offset_ptr, bitfield_bit_size_ptr, is_bitfield_ptr); + } + } + break; + case clang::Type::ObjCObject: case clang::Type::ObjCInterface: if (GetCompleteQualType (ast, qual_type)) @@ -3748,54 +3867,7 @@ ClangASTContext::GetFieldAtIndex (clang::ASTContext *ast, if (objc_class_type) { ObjCInterfaceDecl *class_interface_decl = objc_class_type->getInterface(); - - if (class_interface_decl) - { - if (idx < (class_interface_decl->ivar_size())) - { - ObjCInterfaceDecl::ivar_iterator ivar_pos, ivar_end = class_interface_decl->ivar_end(); - uint32_t ivar_idx = 0; - - for (ivar_pos = class_interface_decl->ivar_begin(); ivar_pos != ivar_end; ++ivar_pos, ++ivar_idx) - { - if (ivar_idx == idx) - { - const ObjCIvarDecl* ivar_decl = *ivar_pos; - - QualType ivar_qual_type(ivar_decl->getType()); - - name.assign(ivar_decl->getNameAsString()); - - if (bit_offset_ptr) - { - const ASTRecordLayout &interface_layout = ast->getASTObjCInterfaceLayout(class_interface_decl); - *bit_offset_ptr = interface_layout.getFieldOffset (ivar_idx); - } - - const bool is_bitfield = ivar_pos->isBitField(); - - if (bitfield_bit_size_ptr) - { - *bitfield_bit_size_ptr = 0; - - if (is_bitfield && ast) - { - Expr *bitfield_bit_size_expr = ivar_pos->getBitWidth(); - llvm::APSInt bitfield_apsint; - if (bitfield_bit_size_expr && bitfield_bit_size_expr->EvaluateAsInt(bitfield_apsint, *ast)) - { - *bitfield_bit_size_ptr = bitfield_apsint.getLimitedValue(); - } - } - } - if (is_bitfield_ptr) - *is_bitfield_ptr = is_bitfield; - - return ivar_qual_type.getAsOpaquePtr(); - } - } - } - } + return GetObjCFieldAtIndex(ast, class_interface_decl, idx, name, bit_offset_ptr, bitfield_bit_size_ptr, is_bitfield_ptr); } } break; diff --git a/lldb/source/Symbol/Type.cpp b/lldb/source/Symbol/Type.cpp index 1795a0ddb17..4d540c8dd1b 100644 --- a/lldb/source/Symbol/Type.cpp +++ b/lldb/source/Symbol/Type.cpp @@ -982,3 +982,10 @@ TypeImpl::GetDescription (lldb_private::Stream &strm, return true; } +ConstString +TypeImpl::GetName () +{ + if (m_clang_ast_type.IsValid()) + return m_clang_ast_type.GetConstQualifiedTypeName(); + return ConstString(); +} diff --git a/lldb/test/python_api/objc_type/Makefile b/lldb/test/python_api/objc_type/Makefile new file mode 100644 index 00000000000..4562b048d20 --- /dev/null +++ b/lldb/test/python_api/objc_type/Makefile @@ -0,0 +1,9 @@ +LEVEL = ../../make + +OBJC_SOURCES := main.m + +CFLAGS_EXTRAS += -w + +include $(LEVEL)/Makefile.rules + +LDFLAGS += -framework Cocoa diff --git a/lldb/test/python_api/objc_type/TestObjCType.py b/lldb/test/python_api/objc_type/TestObjCType.py new file mode 100644 index 00000000000..35f83c4b15e --- /dev/null +++ b/lldb/test/python_api/objc_type/TestObjCType.py @@ -0,0 +1,79 @@ +""" +Test SBType for ObjC classes. +""" + +import os, time +import re +import unittest2 +import lldb, lldbutil +from lldbtest import * + +class ObjCSBTypeTestCase(TestBase): + + mydir = os.path.join("python_api", "objc_type") + + @unittest2.skipUnless(sys.platform.startswith("darwin"), "requires Darwin") + @python_api_test + @dsym_test + def test_with_dsym(self): + """Test SBType for ObjC classes.""" + self.buildDsym() + self.objc_sbtype_test() + + @unittest2.skipUnless(sys.platform.startswith("darwin"), "requires Darwin") + @python_api_test + @dwarf_test + def test_with_dwarf(self): + """Test SBType for ObjC classes.""" + self.buildDwarf() + self.objc_sbtype_test() + + def setUp(self): + # Call super's setUp(). + TestBase.setUp(self) + self.line = line_number("main.m", '// Break at this line') + + def objc_sbtype_test(self): + """Exercise SBType and SBTypeList API.""" + exe = os.path.join(os.getcwd(), "a.out") + + # Create a target by the debugger. + target = self.dbg.CreateTarget(exe) + self.assertTrue(target, VALID_TARGET) + + # Create the breakpoint inside function 'main'. + breakpoint = target.BreakpointCreateByLocation("main.m", self.line) + self.assertTrue(breakpoint, VALID_BREAKPOINT) + + # Now launch the process, and do not stop at entry point. + process = target.LaunchSimple(None, None, os.getcwd()) + self.assertTrue(process, PROCESS_IS_VALID) + + + + # Get Frame #0. + self.assertTrue(process.GetState() == lldb.eStateStopped) + thread = lldbutil.get_stopped_thread(process, lldb.eStopReasonBreakpoint) + self.assertTrue(thread.IsValid(), "There should be a thread stopped due to breakpoint condition") + + aBar = self.frame().FindVariable("aBar") + aBarType = aBar.GetType() + self.assertTrue(aBarType.IsValid(), "Bar should be a valid data type") + self.assertTrue(aBarType.GetName() == "Bar *", "Bar has the right name") + + self.assertTrue(aBarType.GetNumberOfDirectBaseClasses() == 1, "Bar has a superclass") + aFooType = aBarType.GetDirectBaseClassAtIndex(0) + + self.assertTrue(aFooType.IsValid(), "Foo should be a valid data type") + self.assertTrue(aFooType.GetName() == "Foo", "Foo has the right name") + + self.assertTrue(aBarType.GetNumberOfFields() == 1, "Bar has a field") + aBarField = aBarType.GetFieldAtIndex(0) + + self.assertTrue(aBarField.GetName() == "_iVar", "The field has the right name") + +if __name__ == '__main__': + import atexit + lldb.SBDebugger.Initialize() + atexit.register(lambda: lldb.SBDebugger.Terminate()) + unittest2.main() diff --git a/lldb/test/python_api/objc_type/main.m b/lldb/test/python_api/objc_type/main.m new file mode 100644 index 00000000000..f63f0c5040e --- /dev/null +++ b/lldb/test/python_api/objc_type/main.m @@ -0,0 +1,52 @@ +//===-- main.m ------------------------------------------------*- ObjC -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#import <Cocoa/Cocoa.h> + +@interface Foo: NSObject +{} +- (id) init; +@end + +@interface Bar: Foo +{ + int _iVar; +} +- (id) init; +@end + +@implementation Foo + +- (id) init +{ + self = [super init]; + return self; +} + +@end + +@implementation Bar + +- (id) init +{ + self = [super init]; + if (self) + self->_iVar = 5; + return self; +} + +@end + +int main() +{ + Bar* aBar = [Bar new]; + id nothing = [aBar noSuchSelector]; // Break at this line + return 0; +} + |