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. 127 int 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*). 141 int 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. 151 int 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. 161 int 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 169 int 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. 178 int 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 185 @end 186 id testDefNotAvailableInlined(DefNotAvailClass *C) { 187 return [C mem]; // expected-warning {{instance method '-mem' not found}} 188 } 189 id testDefNotAvailable(DefNotAvailClass *C) { 190 return testDefNotAvailableInlined(C); 191 }