InlineObjCInstanceMethod.m revision ff63227817217cd33c587e054d4892285b8e00c6
1// RUN: %clang --analyze -Xanalyzer -analyzer-checker=osx.cocoa.IncompatibleMethodTypes -Xclang -verify %s
2
3#include "InlineObjCInstanceMethod.h"
4
5// Method is defined in the parent; called through self.
6@interface MyParent : NSObject
7- (int)getInt;
8@end
9@implementation MyParent
10- (int)getInt {
11    return 0;
12}
13@end
14
15@interface MyClass : MyParent
16@end
17@implementation MyClass
18- (int)testDynDispatchSelf {
19  int y = [self getInt];
20  return 5/y; // expected-warning {{Division by zero}}
21}
22
23// Get the dynamic type info from a cast (from id to MyClass*).
24+ (int)testAllocInit {
25  MyClass *a = [[self alloc] init];
26  return 5/[a getInt]; // expected-warning {{Division by zero}}
27}
28
29// Method is called on inited object.
30+ (int)testAllocInit2 {
31  MyClass *a = [[MyClass alloc] init];
32  return 5/[a getInt]; // expected-warning {{Division by zero}}
33}
34
35// Method is called on a parameter.
36+ (int)testParam: (MyClass*) a {
37  return 5/[a getInt]; // expected-warning {{Division by zero}}
38}
39
40// Method is called on a parameter of unnown type.
41+ (int)testParamUnknownType: (id) a {
42  return 5/[a getInt]; // no warning
43}
44
45@end
46
47// TODO: When method is inlined, the attribute reset should be visible.
48@interface TestSettingAnAttributeInCallee : NSObject {
49  int _attribute;
50}
51  - (void) method2;
52@end
53
54@implementation TestSettingAnAttributeInCallee
55- (int) method1 {
56  [self method2];
57  return 5/_attribute; // expected-warning {{Division by zero}}
58}
59
60- (void) method2 {
61  _attribute = 0;
62}
63@end
64
65@interface TestSettingAnAttributeInCaller : NSObject {
66  int _attribute;
67}
68  - (int) method2;
69@end
70
71@implementation TestSettingAnAttributeInCaller
72- (void) method1 {
73  _attribute = 0;
74  [self method2];
75}
76
77- (int) method2 {
78  return 5/_attribute; // expected-warning {{Division by zero}}
79}
80@end
81
82
83// Don't crash if we don't know the receiver's region.
84void randomlyMessageAnObject(MyClass *arr[], int i) {
85  (void)[arr[i] getInt];
86}
87
88
89@interface EvilChild : MyParent
90- (id)getInt;
91@end
92
93@implementation EvilChild
94- (id)getInt { // expected-warning {{types are incompatible}}
95  return self;
96}
97@end
98
99int testNonCovariantReturnType() {
100  MyParent *obj = [[EvilChild alloc] init];
101
102  // Devirtualization allows us to directly call -[EvilChild getInt], but
103  // that returns an id, not an int. There is an off-by-default warning for
104  // this, -Woverriding-method-mismatch, and an on-by-default analyzer warning,
105  // osx.cocoa.IncompatibleMethodTypes. This code would probably crash at
106  // runtime, but at least the analyzer shouldn't crash.
107  int x = 1 + [obj getInt];
108
109  [obj release];
110  return 5/(x-1); // no-warning
111}
112