1*67e74705SXin Li// RUN: %clang_cc1 -analyze -analyzer-checker=core,osx -analyzer-config ipa=dynamic-bifurcate -verify %s 2*67e74705SXin Li 3*67e74705SXin Li#include "InlineObjCInstanceMethod.h" 4*67e74705SXin Li 5*67e74705SXin Li@interface MyParent : NSObject 6*67e74705SXin Li- (int)getZero; 7*67e74705SXin Li@end 8*67e74705SXin Li@implementation MyParent 9*67e74705SXin Li- (int)getZero { 10*67e74705SXin Li return 0; 11*67e74705SXin Li} 12*67e74705SXin Li@end 13*67e74705SXin Li 14*67e74705SXin Li@interface PublicClass () { 15*67e74705SXin Li int value2; 16*67e74705SXin Li} 17*67e74705SXin Li@property (readwrite) int value1; 18*67e74705SXin Li- (void)setValue2:(int)newValue2; 19*67e74705SXin Li@end 20*67e74705SXin Li 21*67e74705SXin Li@implementation PublicClass 22*67e74705SXin Li 23*67e74705SXin Li- (int)getZeroPublic { 24*67e74705SXin Li return 0; 25*67e74705SXin Li} 26*67e74705SXin Li 27*67e74705SXin Li@synthesize value1; 28*67e74705SXin Li 29*67e74705SXin Li- (int)value2 { 30*67e74705SXin Li return value2; 31*67e74705SXin Li} 32*67e74705SXin Li- (void)setValue2:(int)newValue { 33*67e74705SXin Li value2 = newValue; 34*67e74705SXin Li} 35*67e74705SXin Li 36*67e74705SXin Li- (int)value3 { 37*67e74705SXin Li return value3; 38*67e74705SXin Li} 39*67e74705SXin Li- (void)setValue3:(int)newValue { 40*67e74705SXin Li value3 = newValue; 41*67e74705SXin Li} 42*67e74705SXin Li 43*67e74705SXin Li@end 44*67e74705SXin Li 45*67e74705SXin Li@interface MyClassWithPublicParent : PublicClass 46*67e74705SXin Li- (int)getZeroPublic; 47*67e74705SXin Li@end 48*67e74705SXin Li@implementation MyClassWithPublicParent 49*67e74705SXin Li- (int)getZeroPublic { 50*67e74705SXin Li return 0; 51*67e74705SXin Li} 52*67e74705SXin Li@end 53*67e74705SXin Li 54*67e74705SXin Li// Category overrides a public method. 55*67e74705SXin Li@interface PublicSubClass (PrvateCat) 56*67e74705SXin Li - (int) getZeroPublic; 57*67e74705SXin Li@end 58*67e74705SXin Li@implementation PublicSubClass (PrvateCat) 59*67e74705SXin Li- (int)getZeroPublic { 60*67e74705SXin Li return 0; 61*67e74705SXin Li} 62*67e74705SXin Li@end 63*67e74705SXin Li 64*67e74705SXin Li 65*67e74705SXin Li@interface MyClass : MyParent { 66*67e74705SXin Li int value; 67*67e74705SXin Li} 68*67e74705SXin Li- (int)getZero; 69*67e74705SXin Li@property int value; 70*67e74705SXin Li@end 71*67e74705SXin Li 72*67e74705SXin Li// Since class is private, we assume that it cannot be subclassed. 73*67e74705SXin Li// False negative: this class is "privately subclassed". this is very rare 74*67e74705SXin Li// in practice. 75*67e74705SXin Li@implementation MyClass 76*67e74705SXin Li+ (int) testTypeFromParam:(MyParent*) p { 77*67e74705SXin Li int m = 0; 78*67e74705SXin Li int z = [p getZero]; 79*67e74705SXin Li if (z) 80*67e74705SXin Li return 5/m; // false negative 81*67e74705SXin Li return 5/[p getZero];// expected-warning {{Division by zero}} 82*67e74705SXin Li} 83*67e74705SXin Li 84*67e74705SXin Li// Here only one definition is possible, since the declaration is not visible 85*67e74705SXin Li// from outside. 86*67e74705SXin Li+ (int) testTypeFromParamPrivateChild:(MyClass*) c { 87*67e74705SXin Li int m = 0; 88*67e74705SXin Li int z = [c getZero]; // MyClass overrides getZero to return '1'. 89*67e74705SXin Li if (z) 90*67e74705SXin Li return 5/m; // expected-warning {{Division by zero}} 91*67e74705SXin Li return 5/[c getZero];//no warning 92*67e74705SXin Li} 93*67e74705SXin Li 94*67e74705SXin Li- (int)getZero { 95*67e74705SXin Li return 1; 96*67e74705SXin Li} 97*67e74705SXin Li 98*67e74705SXin Li- (int)value { 99*67e74705SXin Li return value; 100*67e74705SXin Li} 101*67e74705SXin Li 102*67e74705SXin Li- (void)setValue:(int)newValue { 103*67e74705SXin Li value = newValue; 104*67e74705SXin Li} 105*67e74705SXin Li 106*67e74705SXin Li// Test ivar access. 107*67e74705SXin Li- (int) testIvarInSelf { 108*67e74705SXin Li value = 0; 109*67e74705SXin Li return 5/value; // expected-warning {{Division by zero}} 110*67e74705SXin Li} 111*67e74705SXin Li 112*67e74705SXin Li+ (int) testIvar: (MyClass*) p { 113*67e74705SXin Li p.value = 0; 114*67e74705SXin Li return 5/p.value; // expected-warning {{Division by zero}} 115*67e74705SXin Li} 116*67e74705SXin Li 117*67e74705SXin Li// Test simple property access. 118*67e74705SXin Li+ (int) testProperty: (MyClass*) p { 119*67e74705SXin Li int x= 0; 120*67e74705SXin Li [p setValue:0]; 121*67e74705SXin Li return 5/[p value]; // expected-warning {{Division by zero}} 122*67e74705SXin Li} 123*67e74705SXin Li 124*67e74705SXin Li@end 125*67e74705SXin Li 126*67e74705SXin Li// The class is prvate and is not subclassed. 127*67e74705SXin Liint testCallToPublicAPIInParent(MyClassWithPublicParent *p) { 128*67e74705SXin Li int m = 0; 129*67e74705SXin Li int z = [p getZeroPublic]; 130*67e74705SXin Li if (z) 131*67e74705SXin Li return 5/m; // no warning 132*67e74705SXin Li return 5/[p getZeroPublic];// expected-warning {{Division by zero}} 133*67e74705SXin Li} 134*67e74705SXin Li 135*67e74705SXin Li// When the called method is public (due to it being defined outside of main file), 136*67e74705SXin Li// split the path and analyze both branches. 137*67e74705SXin Li// In this case, p can be either the object of type MyParent* or MyClass*: 138*67e74705SXin Li// - If it's MyParent*, getZero returns 0. 139*67e74705SXin Li// - If it's MyClass*, getZero returns 1 and 'return 5/m' is reachable. 140*67e74705SXin Li// Declaration is provate, but p can be a subclass (MyClass*). 141*67e74705SXin Liint testCallToPublicAPI(PublicClass *p) { 142*67e74705SXin Li int m = 0; 143*67e74705SXin Li int z = [p getZeroPublic]; 144*67e74705SXin Li if (z) 145*67e74705SXin Li return 5/m; // expected-warning {{Division by zero}} 146*67e74705SXin Li return 5/[p getZeroPublic];// expected-warning {{Division by zero}} 147*67e74705SXin Li} 148*67e74705SXin Li 149*67e74705SXin Li// Even though the method is privately declared in the category, the parent 150*67e74705SXin Li// declares the method as public. Assume the instance can be subclassed. 151*67e74705SXin Liint testCallToPublicAPICat(PublicSubClass *p) { 152*67e74705SXin Li int m = 0; 153*67e74705SXin Li int z = [p getZeroPublic]; 154*67e74705SXin Li if (z) 155*67e74705SXin Li return 5/m; // expected-warning {{Division by zero}} 156*67e74705SXin Li return 5/[p getZeroPublic];// expected-warning {{Division by zero}} 157*67e74705SXin Li} 158*67e74705SXin Li 159*67e74705SXin Li// Test public property - properties should always be inlined, regardless 160*67e74705SXin Li// weither they are "public" or private. 161*67e74705SXin Liint testPublicProperty(PublicClass *p) { 162*67e74705SXin Li int x = 0; 163*67e74705SXin Li p.value3 = 0; 164*67e74705SXin Li if (p.value3 != 0) 165*67e74705SXin Li return 5/x; 166*67e74705SXin Li return 5/p.value3;// expected-warning {{Division by zero}} 167*67e74705SXin Li} 168*67e74705SXin Li 169*67e74705SXin Liint testExtension(PublicClass *p) { 170*67e74705SXin Li int x = 0; 171*67e74705SXin Li [p setValue2:0]; 172*67e74705SXin Li if ([p value2] != 0) 173*67e74705SXin Li return 5/x; // expected-warning {{Division by zero}} 174*67e74705SXin Li return 5/[p value2]; // expected-warning {{Division by zero}} 175*67e74705SXin Li} 176*67e74705SXin Li 177*67e74705SXin Li// TODO: we do not handle synthesized properties yet. 178*67e74705SXin Liint testPropertySynthesized(PublicClass *p) { 179*67e74705SXin Li [p setValue1:0]; 180*67e74705SXin Li return 5/[p value1]; 181*67e74705SXin Li} 182*67e74705SXin Li 183*67e74705SXin Li// Test definition not available edge case. 184*67e74705SXin Li@interface DefNotAvailClass : NSObject // expected-note {{receiver is instance of class declared here}} 185*67e74705SXin Li@end 186*67e74705SXin Liid testDefNotAvailableInlined(DefNotAvailClass *C) { 187*67e74705SXin Li return [C mem]; // expected-warning {{instance method '-mem' not found}} 188*67e74705SXin Li} 189*67e74705SXin Liid testDefNotAvailable(DefNotAvailClass *C) { 190*67e74705SXin Li return testDefNotAvailableInlined(C); 191*67e74705SXin Li} 192