1*67e74705SXin Li// RUN: %clang --analyze -Xanalyzer -analyzer-checker=osx.cocoa.IncompatibleMethodTypes,osx.coreFoundation.CFRetainRelease -Xclang -verify %s 2*67e74705SXin Li 3*67e74705SXin Li#include "InlineObjCInstanceMethod.h" 4*67e74705SXin Li 5*67e74705SXin Litypedef const struct __CFString * CFStringRef; 6*67e74705SXin Litypedef const void * CFTypeRef; 7*67e74705SXin Liextern CFTypeRef CFRetain(CFTypeRef cf); 8*67e74705SXin Liextern void CFRelease(CFTypeRef cf); 9*67e74705SXin Liextern CFStringRef getString(void); 10*67e74705SXin Li 11*67e74705SXin Li// Method is defined in the parent; called through self. 12*67e74705SXin Li@interface MyParent : NSObject 13*67e74705SXin Li- (int)getInt; 14*67e74705SXin Li- (const struct __CFString *) testCovariantReturnType __attribute__((cf_returns_retained)); 15*67e74705SXin Li@end 16*67e74705SXin Li@implementation MyParent 17*67e74705SXin Li- (int)getInt { 18*67e74705SXin Li return 0; 19*67e74705SXin Li} 20*67e74705SXin Li 21*67e74705SXin Li- (CFStringRef) testCovariantReturnType __attribute__((cf_returns_retained)) { 22*67e74705SXin Li CFStringRef Str = ((void*)0); 23*67e74705SXin Li Str = getString(); 24*67e74705SXin Li if (Str) { 25*67e74705SXin Li CFRetain(Str); 26*67e74705SXin Li } 27*67e74705SXin Li return Str; 28*67e74705SXin Li} 29*67e74705SXin Li 30*67e74705SXin Li@end 31*67e74705SXin Li 32*67e74705SXin Li@interface MyClass : MyParent 33*67e74705SXin Li@end 34*67e74705SXin Li@implementation MyClass 35*67e74705SXin Li- (int)testDynDispatchSelf { 36*67e74705SXin Li int y = [self getInt]; 37*67e74705SXin Li return 5/y; // expected-warning {{Division by zero}} 38*67e74705SXin Li} 39*67e74705SXin Li 40*67e74705SXin Li// Get the dynamic type info from a cast (from id to MyClass*). 41*67e74705SXin Li+ (int)testAllocInit { 42*67e74705SXin Li MyClass *a = [[self alloc] init]; 43*67e74705SXin Li return 5/[a getInt]; // expected-warning {{Division by zero}} 44*67e74705SXin Li} 45*67e74705SXin Li 46*67e74705SXin Li// Method is called on inited object. 47*67e74705SXin Li+ (int)testAllocInit2 { 48*67e74705SXin Li MyClass *a = [[MyClass alloc] init]; 49*67e74705SXin Li return 5/[a getInt]; // expected-warning {{Division by zero}} 50*67e74705SXin Li} 51*67e74705SXin Li 52*67e74705SXin Li// Method is called on a parameter. 53*67e74705SXin Li+ (int)testParam: (MyClass*) a { 54*67e74705SXin Li return 5/[a getInt]; // expected-warning {{Division by zero}} 55*67e74705SXin Li} 56*67e74705SXin Li 57*67e74705SXin Li// Method is called on a parameter of unnown type. 58*67e74705SXin Li+ (int)testParamUnknownType: (id) a { 59*67e74705SXin Li return 5/[a getInt]; // no warning 60*67e74705SXin Li} 61*67e74705SXin Li 62*67e74705SXin Li@end 63*67e74705SXin Li 64*67e74705SXin Li// TODO: When method is inlined, the attribute reset should be visible. 65*67e74705SXin Li@interface TestSettingAnAttributeInCallee : NSObject { 66*67e74705SXin Li int _attribute; 67*67e74705SXin Li} 68*67e74705SXin Li - (void) method2; 69*67e74705SXin Li@end 70*67e74705SXin Li 71*67e74705SXin Li@implementation TestSettingAnAttributeInCallee 72*67e74705SXin Li- (int) method1 { 73*67e74705SXin Li [self method2]; 74*67e74705SXin Li return 5/_attribute; // expected-warning {{Division by zero}} 75*67e74705SXin Li} 76*67e74705SXin Li 77*67e74705SXin Li- (void) method2 { 78*67e74705SXin Li _attribute = 0; 79*67e74705SXin Li} 80*67e74705SXin Li@end 81*67e74705SXin Li 82*67e74705SXin Li@interface TestSettingAnAttributeInCaller : NSObject { 83*67e74705SXin Li int _attribute; 84*67e74705SXin Li} 85*67e74705SXin Li - (int) method2; 86*67e74705SXin Li@end 87*67e74705SXin Li 88*67e74705SXin Li@implementation TestSettingAnAttributeInCaller 89*67e74705SXin Li- (void) method1 { 90*67e74705SXin Li _attribute = 0; 91*67e74705SXin Li [self method2]; 92*67e74705SXin Li} 93*67e74705SXin Li 94*67e74705SXin Li- (int) method2 { 95*67e74705SXin Li return 5/_attribute; // expected-warning {{Division by zero}} 96*67e74705SXin Li} 97*67e74705SXin Li@end 98*67e74705SXin Li 99*67e74705SXin Li 100*67e74705SXin Li// Don't crash if we don't know the receiver's region. 101*67e74705SXin Livoid randomlyMessageAnObject(MyClass *arr[], int i) { 102*67e74705SXin Li (void)[arr[i] getInt]; 103*67e74705SXin Li} 104*67e74705SXin Li 105*67e74705SXin Li 106*67e74705SXin Li@interface EvilChild : MyParent 107*67e74705SXin Li- (id)getInt; 108*67e74705SXin Li- (const struct __CFString *) testCovariantReturnType __attribute__((cf_returns_retained)); 109*67e74705SXin Li@end 110*67e74705SXin Li 111*67e74705SXin Li@implementation EvilChild 112*67e74705SXin Li- (id)getInt { // expected-warning {{types are incompatible}} 113*67e74705SXin Li return self; 114*67e74705SXin Li} 115*67e74705SXin Li- (CFStringRef) testCovariantReturnType __attribute__((cf_returns_retained)) { 116*67e74705SXin Li CFStringRef Str = ((void*)0); 117*67e74705SXin Li Str = getString(); 118*67e74705SXin Li if (Str) { 119*67e74705SXin Li CFRetain(Str); 120*67e74705SXin Li } 121*67e74705SXin Li return Str; 122*67e74705SXin Li} 123*67e74705SXin Li 124*67e74705SXin Li@end 125*67e74705SXin Li 126*67e74705SXin Liint testNonCovariantReturnType() { 127*67e74705SXin Li MyParent *obj = [[EvilChild alloc] init]; 128*67e74705SXin Li 129*67e74705SXin Li // Devirtualization allows us to directly call -[EvilChild getInt], but 130*67e74705SXin Li // that returns an id, not an int. There is an off-by-default warning for 131*67e74705SXin Li // this, -Woverriding-method-mismatch, and an on-by-default analyzer warning, 132*67e74705SXin Li // osx.cocoa.IncompatibleMethodTypes. This code would probably crash at 133*67e74705SXin Li // runtime, but at least the analyzer shouldn't crash. 134*67e74705SXin Li int x = 1 + [obj getInt]; 135*67e74705SXin Li 136*67e74705SXin Li [obj release]; 137*67e74705SXin Li return 5/(x-1); // no-warning 138*67e74705SXin Li} 139*67e74705SXin Li 140*67e74705SXin Liint testCovariantReturnTypeNoErrorSinceTypesMatch() { 141*67e74705SXin Li MyParent *obj = [[EvilChild alloc] init]; 142*67e74705SXin Li 143*67e74705SXin Li CFStringRef S = ((void*)0); 144*67e74705SXin Li S = [obj testCovariantReturnType]; 145*67e74705SXin Li if (S) 146*67e74705SXin Li CFRelease(S); 147*67e74705SXin Li CFRelease(obj); 148*67e74705SXin Li} 149