<rdar://problem/15180638>
authorEnrico Granata <egranata@apple.com>
Wed, 9 Oct 2013 00:13:17 +0000 (00:13 +0000)
committerEnrico Granata <egranata@apple.com>
Wed, 9 Oct 2013 00:13:17 +0000 (00:13 +0000)
Making GetNumberOfDirectBaseClasses() work for ObjC pointers, and for classes for which we don't have full debug info

llvm-svn: 192255

lldb/source/Symbol/ClangASTType.cpp
lldb/test/lang/objc/objc-baseclass-sbtype/Makefile [new file with mode: 0644]
lldb/test/lang/objc/objc-baseclass-sbtype/TestObjCBaseClassSBType.py [new file with mode: 0644]
lldb/test/lang/objc/objc-baseclass-sbtype/main.m [new file with mode: 0644]

index e675af5..9e7d52a 100644 (file)
@@ -2281,26 +2281,29 @@ ClangASTType::GetNumDirectBaseClasses () const
             break;
             
         case clang::Type::ObjCObjectPointer:
+            count = GetPointeeType().GetNumDirectBaseClasses();
+            break;
+            
+        case clang::Type::ObjCObject:
             if (GetCompleteType())
             {
-                const ObjCObjectPointerType *objc_class_type = qual_type->getAsObjCInterfacePointerType();
+                const ObjCObjectType *objc_class_type = qual_type->getAsObjCQualifiedInterfaceType();
                 if (objc_class_type)
                 {
-                    ObjCInterfaceDecl *class_interface_decl = objc_class_type->getInterfaceDecl();
+                    ObjCInterfaceDecl *class_interface_decl = objc_class_type->getInterface();
+                    
                     if (class_interface_decl && class_interface_decl->getSuperClass())
                         count = 1;
                 }
             }
             break;
-            
-        case clang::Type::ObjCObject:
         case clang::Type::ObjCInterface:
             if (GetCompleteType())
             {
-                const ObjCObjectType *objc_class_type = qual_type->getAsObjCQualifiedInterfaceType();
-                if (objc_class_type)
+                const ObjCInterfaceType *objc_interface_type = qual_type->getAs<ObjCInterfaceType>();
+                if (objc_interface_type)
                 {
-                    ObjCInterfaceDecl *class_interface_decl = objc_class_type->getInterface();
+                    ObjCInterfaceDecl *class_interface_decl = objc_interface_type->getInterface();
                     
                     if (class_interface_decl && class_interface_decl->getSuperClass())
                         count = 1;
@@ -2482,12 +2485,16 @@ ClangASTType::GetDirectBaseClassAtIndex (size_t idx, uint32_t *bit_offset_ptr) c
             break;
             
         case clang::Type::ObjCObjectPointer:
+            return GetPointeeType().GetDirectBaseClassAtIndex(idx,bit_offset_ptr);
+            
+        case clang::Type::ObjCObject:
             if (idx == 0 && GetCompleteType())
             {
-                const ObjCObjectPointerType *objc_class_type = qual_type->getAsObjCInterfacePointerType();
+                const ObjCObjectType *objc_class_type = qual_type->getAsObjCQualifiedInterfaceType();
                 if (objc_class_type)
                 {
-                    ObjCInterfaceDecl *class_interface_decl = objc_class_type->getInterfaceDecl();
+                    ObjCInterfaceDecl *class_interface_decl = objc_class_type->getInterface();
+                    
                     if (class_interface_decl)
                     {
                         ObjCInterfaceDecl *superclass_interface_decl = class_interface_decl->getSuperClass();
@@ -2501,15 +2508,13 @@ ClangASTType::GetDirectBaseClassAtIndex (size_t idx, uint32_t *bit_offset_ptr) c
                 }
             }
             break;
-            
-        case clang::Type::ObjCObject:
         case clang::Type::ObjCInterface:
             if (idx == 0 && GetCompleteType())
             {
-                const ObjCObjectType *objc_class_type = qual_type->getAsObjCQualifiedInterfaceType();
-                if (objc_class_type)
+                const ObjCObjectType *objc_interface_type = qual_type->getAs<ObjCInterfaceType>();
+                if (objc_interface_type)
                 {
-                    ObjCInterfaceDecl *class_interface_decl = objc_class_type->getInterface();
+                    ObjCInterfaceDecl *class_interface_decl = objc_interface_type->getInterface();
                     
                     if (class_interface_decl)
                     {
diff --git a/lldb/test/lang/objc/objc-baseclass-sbtype/Makefile b/lldb/test/lang/objc/objc-baseclass-sbtype/Makefile
new file mode 100644 (file)
index 0000000..a607659
--- /dev/null
@@ -0,0 +1,6 @@
+LEVEL = ../../../make
+
+OBJC_SOURCES := main.m
+LDFLAGS = $(CFLAGS) -lobjc -framework AppKit
+
+include $(LEVEL)/Makefile.rules
diff --git a/lldb/test/lang/objc/objc-baseclass-sbtype/TestObjCBaseClassSBType.py b/lldb/test/lang/objc/objc-baseclass-sbtype/TestObjCBaseClassSBType.py
new file mode 100644 (file)
index 0000000..0a98469
--- /dev/null
@@ -0,0 +1,75 @@
+"""
+Use lldb Python API to test base class resolution for ObjC classes
+"""
+
+import os, time
+import re
+import unittest2
+import lldb, lldbutil
+from lldbtest import *
+
+class ObjCDynamicValueTestCase(TestBase):
+
+    mydir = os.path.join("lang", "objc", "objc-baseclass-sbtype")
+
+    @unittest2.skipUnless(sys.platform.startswith("darwin"), "requires Darwin")
+    @python_api_test
+    @dsym_test
+    def test_get_baseclass_with_dsym(self):
+        """Test fetching ObjC base class info."""
+        if self.getArchitecture() == 'i386':
+            # rdar://problem/9946499
+            self.skipTest("Dynamic types for ObjC V1 runtime not implemented")
+        self.buildDsym()
+        self.do_get_baseclass_info()
+
+    @unittest2.skipUnless(sys.platform.startswith("darwin"), "requires Darwin")
+    @python_api_test
+    @dwarf_test
+    def test_get_baseclass_with_dwarf(self):
+        """Test fetching ObjC dynamic values."""
+        if self.getArchitecture() == 'i386':
+            # rdar://problem/9946499
+            self.skipTest("Dynamic types for ObjC V1 runtime not implemented")
+        self.buildDwarf()
+        self.do_get_baseclass_info()
+
+    def setUp(self):
+        # Call super's setUp().                                                                                                           
+        TestBase.setUp(self)
+
+        self.line = line_number('main.m', '// Set breakpoint here.')
+
+    def do_get_baseclass_info(self):
+        """Make sure we get dynamic values correctly both for compiled in classes and dynamic ones"""
+        exe = os.path.join(os.getcwd(), "a.out")
+
+        # Create a target from the debugger.
+
+        target = self.dbg.CreateTarget (exe)
+        self.assertTrue(target, VALID_TARGET)
+
+        # Set up our breakpoints:
+
+        target.BreakpointCreateByLocation('main.m', self.line)
+        process = target.LaunchSimple (None, None, os.getcwd())
+
+        self.assertTrue(process.GetState() == lldb.eStateStopped,
+                        PROCESS_STOPPED)
+
+        button = self.frame().FindVariable("button")
+        button_ptr_type = button.GetType()
+        button_pte_type = button_ptr_type.GetPointeeType()
+        self.assertTrue(button_ptr_type.GetNumberOfDirectBaseClasses() == 1, "NSButton * has one base class")
+        self.assertTrue(button_pte_type.GetNumberOfDirectBaseClasses() == 1, "NSButton has one base class")
+
+        self.assertTrue(button_ptr_type.GetDirectBaseClassAtIndex(0).IsValid(), "NSButton * has a valid base class")
+        self.assertTrue(button_pte_type.GetDirectBaseClassAtIndex(0).IsValid(), "NSButton * has a valid base class")
+
+        self.assertTrue(button_ptr_type.GetDirectBaseClassAtIndex(0).GetName() == button_pte_type.GetDirectBaseClassAtIndex(0).GetName(), "NSButton and its pointer type don't agree on their base class")
+
+if __name__ == '__main__':
+    import atexit
+    lldb.SBDebugger.Initialize()
+    atexit.register(lambda: lldb.SBDebugger.Terminate())
+    unittest2.main()
diff --git a/lldb/test/lang/objc/objc-baseclass-sbtype/main.m b/lldb/test/lang/objc/objc-baseclass-sbtype/main.m
new file mode 100644 (file)
index 0000000..8427f00
--- /dev/null
@@ -0,0 +1,9 @@
+#import <AppKit/AppKit.h>
+
+int main ()
+{
+       NSButton *button = [NSButton new];
+       NSLog(@"a"); // Set breakpoint here.
+       return 0;
+}
+