DynDispatchBifurcate.m revision 3f558af01643787d209a133215b0abec81b5fe30
1// RUN: %clang_cc1 -analyze -analyzer-checker=core -analyzer-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@implementation PublicClass 15- (int)getZeroPublic { 16 return 0; 17} 18@end 19 20@interface MyClassWithPublicParent : PublicClass 21- (int)getZeroPublic; 22@end 23@implementation MyClassWithPublicParent 24- (int)getZeroPublic { 25 return 0; 26} 27@end 28 29// Category overrides a public method. 30@interface PublicSubClass (PrvateCat) 31 - (int) getZeroPublic; 32@end 33@implementation PublicSubClass (PrvateCat) 34- (int)getZeroPublic { 35 return 0; 36} 37@end 38 39 40@interface MyClass : MyParent 41- (int)getZero; 42@end 43 44// Since class is private, we assume that it cannot be subclassed. 45// False negative: this class is "privately subclassed". this is very rare 46// in practice. 47@implementation MyClass 48+ (int) testTypeFromParam:(MyParent*) p { 49 int m = 0; 50 int z = [p getZero]; 51 if (z) 52 return 5/m; // false negative 53 return 5/[p getZero];// expected-warning {{Division by zero}} 54} 55 56// Here only one definition is possible, since the declaration is not visible 57// from outside. 58+ (int) testTypeFromParamPrivateChild:(MyClass*) c { 59 int m = 0; 60 int z = [c getZero]; // MyClass overrides getZero to return '1'. 61 if (z) 62 return 5/m; // expected-warning {{Division by zero}} 63 return 5/[c getZero];//no warning 64} 65 66- (int)getZero { 67 return 1; 68} 69@end 70 71// The class is prvate and is not subclassed. 72int testCallToPublicAPIInParent(MyClassWithPublicParent *p) { 73 int m = 0; 74 int z = [p getZeroPublic]; 75 if (z) 76 return 5/m; // no warning 77 return 5/[p getZeroPublic];// expected-warning {{Division by zero}} 78} 79 80// When the called method is public (due to it being defined outside of main file), 81// split the path and analyze both branches. 82// In this case, p can be either the object of type MyParent* or MyClass*: 83// - If it's MyParent*, getZero returns 0. 84// - If it's MyClass*, getZero returns 1 and 'return 5/m' is reachable. 85// Declaration is provate, but p can be a subclass (MyClass*). 86int testCallToPublicAPI(PublicClass *p) { 87 int m = 0; 88 int z = [p getZeroPublic]; 89 if (z) 90 return 5/m; // expected-warning {{Division by zero}} 91 return 5/[p getZeroPublic];// expected-warning {{Division by zero}} 92} 93 94// Even though the method is privately declared in the category, the parent 95// declares the method as public. Assume the instance can be subclassed. 96int testCallToPublicAPICat(PublicSubClass *p) { 97 int m = 0; 98 int z = [p getZeroPublic]; 99 if (z) 100 return 5/m; // expected-warning {{Division by zero}} 101 return 5/[p getZeroPublic];// expected-warning {{Division by zero}} 102} 103