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