InlineObjCClassMethod.m revision 6fbe0317aa38dbac22a29f7519c52db838aa1990
1// RUN: %clang_cc1 -analyze -analyzer-checker=core -verify %s 2 3// Test inlining of ObjC class methods. 4 5typedef signed char BOOL; 6typedef struct objc_class *Class; 7typedef struct objc_object { 8 Class isa; 9} *id; 10@protocol NSObject - (BOOL)isEqual:(id)object; @end 11@interface NSObject <NSObject> {} 12+(id)alloc; 13-(id)init; 14-(id)autorelease; 15-(id)copy; 16- (Class)class; 17-(id)retain; 18@end 19 20// Vanila: ObjC class method is called by name. 21@interface MyParent : NSObject 22+ (int)getInt; 23@end 24@interface MyClass : MyParent 25+ (int)getInt; 26@end 27@implementation MyClass 28+ (int)testClassMethodByName { 29 int y = [MyClass getInt]; 30 return 5/y; // expected-warning {{Division by zero}} 31} 32+ (int)getInt { 33 return 0; 34} 35@end 36 37// The definition is defined by the parent. Make sure we find it and inline. 38@interface MyParentDIP : NSObject 39+ (int)getInt; 40@end 41@interface MyClassDIP : MyParentDIP 42@end 43@implementation MyClassDIP 44+ (int)testClassMethodByName { 45 int y = [MyClassDIP getInt]; 46 return 5/y; // expected-warning {{Division by zero}} 47} 48@end 49@implementation MyParentDIP 50+ (int)getInt { 51 return 0; 52} 53@end 54 55// ObjC class method is called by name. Definition is in the category. 56@interface AAA : NSObject 57@end 58@interface AAA (MyCat) 59+ (int)getInt; 60@end 61int foo() { 62 int y = [AAA getInt]; 63 return 5/y; // expected-warning {{Division by zero}} 64} 65@implementation AAA 66@end 67@implementation AAA (MyCat) 68+ (int)getInt { 69 return 0; 70} 71@end 72 73// There is no declaration in the class but there is one in the parent. Make 74// sure we pick the definition from the class and not the parent. 75@interface MyParentTricky : NSObject 76+ (int)getInt; 77@end 78@interface MyClassTricky : MyParentTricky 79@end 80@implementation MyParentTricky 81+ (int)getInt { 82 return 0; 83} 84@end 85@implementation MyClassTricky 86+ (int)getInt { 87 return 1; 88} 89+ (int)testClassMethodByName { 90 int y = [MyClassTricky getInt]; 91 return 5/y; // no-warning 92} 93@end 94 95// ObjC class method is called by unknown class declaration (passed in as a 96// parameter). We should not inline in such case. 97@interface MyParentUnknown : NSObject 98+ (int)getInt; 99@end 100@interface MyClassUnknown : MyParentUnknown 101+ (int)getInt; 102@end 103@implementation MyClassUnknown 104+ (int)testClassVariableByUnknownVarDecl: (Class)cl { 105 int y = [cl getInt]; 106 return 3/y; // no-warning 107} 108+ (int)getInt { 109 return 0; 110} 111@end 112 113 114// False negative. 115// ObjC class method call through a decl with a known type. 116// We should be able to track the type of currentClass and inline this call. 117// Note, [self class] could be a subclass. Do we still want to inline here? 118@interface MyClassKT : NSObject 119@end 120@interface MyClassKT (MyCatKT) 121+ (int)getInt; 122@end 123@implementation MyClassKT (MyCatKT) 124+ (int)getInt { 125 return 0; 126} 127@end 128@implementation MyClassKT 129- (int)testClassMethodByKnownVarDecl { 130 Class currentClass = [self class]; 131 int y = [currentClass getInt]; 132 return 5/y; // Would be great to get a warning here. 133} 134@end 135