[TypeSystem] Fix inspection of Objective-C object types

ptr_refs exposed a problem in ClangASTContext's implementation: it
uses an accessor to downcast a QualType to an
ObjCObjectPointerType, but the accessor is not fully general.
getAs() is the safer way to go.

I've added a test case that uses ptr_refs in a way that would
crash before the fix.

<rdar://problem/31363513>

llvm-svn: 303110
This commit is contained in:
Sean Callanan 2017-05-15 19:55:20 +00:00
parent 8b96c7e9b5
commit 732a6f432e
4 changed files with 98 additions and 4 deletions

View File

@ -0,0 +1,5 @@
LEVEL = ../../../make
OBJC_SOURCES := main.m
include $(LEVEL)/Makefile.rules

View File

@ -0,0 +1,50 @@
"""
Test the ptr_refs tool on Darwin with Objective-C
"""
from __future__ import print_function
import os
import lldb
from lldbsuite.test.decorators import *
from lldbsuite.test.lldbtest import *
from lldbsuite.test import lldbutil
class TestPtrRefsObjC(TestBase):
mydir = TestBase.compute_mydir(__file__)
@skipUnlessDarwin
def test_ptr_refs(self):
"""Test the ptr_refs tool on Darwin with Objective-C"""
self.build()
exe_name = 'a.out'
exe = os.path.join(os.getcwd(), exe_name)
target = self.dbg.CreateTarget(exe)
self.assertTrue(target, VALID_TARGET)
main_file_spec = lldb.SBFileSpec('main.m')
breakpoint = target.BreakpointCreateBySourceRegex(
'break', main_file_spec)
self.assertTrue(breakpoint and
breakpoint.GetNumLocations() == 1,
VALID_BREAKPOINT)
process = target.LaunchSimple(
None, None, self.get_process_working_directory())
self.assertTrue(process, PROCESS_IS_VALID)
# Frame #0 should be on self.line1 and the break condition should hold.
thread = lldbutil.get_stopped_thread(
process, lldb.eStopReasonBreakpoint)
self.assertTrue(
thread.IsValid(),
"There should be a thread stopped due to breakpoint condition")
frame = thread.GetFrameAtIndex(0)
self.dbg.HandleCommand("script import lldb.macosx.heap")
self.expect("ptr_refs self", substrs=["malloc", "stack"])

View File

@ -0,0 +1,39 @@
//===-- main.c --------------------------------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#import <Foundation/Foundation.h>
@interface MyClass : NSObject {
};
-(void)test;
@end
@implementation MyClass
-(void)test {
printf("%p\n", self); // break here
}
@end
@interface MyOwner : NSObject {
@public id ownedThing; // should be id, to test <rdar://problem/31363513>
};
@end
@implementation MyOwner
@end
int main (int argc, char const *argv[]) {
@autoreleasepool {
MyOwner *owner = [[MyOwner alloc] init];
owner->ownedThing = [[MyClass alloc] init];
[(MyClass*)owner->ownedThing test];
}
return 0;
}

View File

@ -4493,7 +4493,7 @@ ClangASTContext::GetNumMemberFunctions(lldb::opaque_compiler_type_t type) {
case clang::Type::ObjCObjectPointer: {
const clang::ObjCObjectPointerType *objc_class_type =
qual_type->getAsObjCInterfacePointerType();
qual_type->getAs<clang::ObjCObjectPointerType>();
const clang::ObjCInterfaceType *objc_interface_type =
objc_class_type->getInterfaceType();
if (objc_interface_type &&
@ -4602,7 +4602,7 @@ ClangASTContext::GetMemberFunctionAtIndex(lldb::opaque_compiler_type_t type,
case clang::Type::ObjCObjectPointer: {
const clang::ObjCObjectPointerType *objc_class_type =
qual_type->getAsObjCInterfacePointerType();
qual_type->getAs<clang::ObjCObjectPointerType>();
const clang::ObjCInterfaceType *objc_interface_type =
objc_class_type->getInterfaceType();
if (objc_interface_type &&
@ -5671,7 +5671,7 @@ uint32_t ClangASTContext::GetNumFields(lldb::opaque_compiler_type_t type) {
case clang::Type::ObjCObjectPointer: {
const clang::ObjCObjectPointerType *objc_class_type =
qual_type->getAsObjCInterfacePointerType();
qual_type->getAs<clang::ObjCObjectPointerType>();
const clang::ObjCInterfaceType *objc_interface_type =
objc_class_type->getInterfaceType();
if (objc_interface_type &&
@ -5819,7 +5819,7 @@ CompilerType ClangASTContext::GetFieldAtIndex(lldb::opaque_compiler_type_t type,
case clang::Type::ObjCObjectPointer: {
const clang::ObjCObjectPointerType *objc_class_type =
qual_type->getAsObjCInterfacePointerType();
qual_type->getAs<clang::ObjCObjectPointerType>();
const clang::ObjCInterfaceType *objc_interface_type =
objc_class_type->getInterfaceType();
if (objc_interface_type &&