blob: 4578a55c7a0798882a953894f78aeae4a9878ba0 [file] [log] [blame]
Dominic Chen184c6242017-03-03 18:02:02 +00001// RUN: %clang_analyze_cc1 -analyzer-checker=core.DivideZero,core.DynamicTypePropagation,osx.cocoa.IncompatibleMethodTypes -w -verify %s
Anna Zaks63282ae2012-07-30 20:31:29 +00002
3#include "InlineObjCInstanceMethod.h"
4
Anna Zaks6ec9c3c2012-11-12 23:40:29 +00005typedef const struct __CFString * CFStringRef;
6typedef const void * CFTypeRef;
7extern CFTypeRef CFRetain(CFTypeRef cf);
8extern void CFRelease(CFTypeRef cf);
9extern CFStringRef getString(void);
10
Anna Zaks63282ae2012-07-30 20:31:29 +000011// Method is defined in the parent; called through self.
12@interface MyParent : NSObject
13- (int)getInt;
Anna Zaks6ec9c3c2012-11-12 23:40:29 +000014- (const struct __CFString *) testCovariantReturnType __attribute__((cf_returns_retained));
Anna Zaks63282ae2012-07-30 20:31:29 +000015@end
16@implementation MyParent
17- (int)getInt {
18 return 0;
19}
Anna Zaks6ec9c3c2012-11-12 23:40:29 +000020
21- (CFStringRef) testCovariantReturnType __attribute__((cf_returns_retained)) {
22 CFStringRef Str = ((void*)0);
23 Str = getString();
24 if (Str) {
25 CFRetain(Str);
26 }
27 return Str;
28}
29
Anna Zaks63282ae2012-07-30 20:31:29 +000030@end
31
32@interface MyClass : MyParent
33@end
34@implementation MyClass
35- (int)testDynDispatchSelf {
36 int y = [self getInt];
37 return 5/y; // expected-warning {{Division by zero}}
38}
39
Anna Zaks150843b2012-08-03 21:43:37 +000040// Get the dynamic type info from a cast (from id to MyClass*).
Anna Zaks63282ae2012-07-30 20:31:29 +000041+ (int)testAllocInit {
42 MyClass *a = [[self alloc] init];
Anna Zaks150843b2012-08-03 21:43:37 +000043 return 5/[a getInt]; // expected-warning {{Division by zero}}
Anna Zaks63282ae2012-07-30 20:31:29 +000044}
45
46// Method is called on inited object.
47+ (int)testAllocInit2 {
48 MyClass *a = [[MyClass alloc] init];
Anna Zaks472dbcf2012-08-06 23:25:39 +000049 return 5/[a getInt]; // expected-warning {{Division by zero}}
Anna Zaks63282ae2012-07-30 20:31:29 +000050}
51
52// Method is called on a parameter.
53+ (int)testParam: (MyClass*) a {
54 return 5/[a getInt]; // expected-warning {{Division by zero}}
55}
56
57// Method is called on a parameter of unnown type.
58+ (int)testParamUnknownType: (id) a {
59 return 5/[a getInt]; // no warning
60}
61
62@end
63
64// TODO: When method is inlined, the attribute reset should be visible.
65@interface TestSettingAnAttributeInCallee : NSObject {
66 int _attribute;
67}
68 - (void) method2;
69@end
70
71@implementation TestSettingAnAttributeInCallee
72- (int) method1 {
73 [self method2];
74 return 5/_attribute; // expected-warning {{Division by zero}}
75}
76
77- (void) method2 {
78 _attribute = 0;
79}
80@end
81
82@interface TestSettingAnAttributeInCaller : NSObject {
83 int _attribute;
84}
85 - (int) method2;
86@end
87
88@implementation TestSettingAnAttributeInCaller
89- (void) method1 {
90 _attribute = 0;
91 [self method2];
92}
93
94- (int) method2 {
95 return 5/_attribute; // expected-warning {{Division by zero}}
96}
Jordan Rose6a97d922012-07-31 18:04:53 +000097@end
98
99
100// Don't crash if we don't know the receiver's region.
101void randomlyMessageAnObject(MyClass *arr[], int i) {
102 (void)[arr[i] getInt];
Jordan Rose1dd2afd2012-10-03 01:08:35 +0000103}
Jordan Roseef77a872012-10-03 16:00:32 +0000104
105
106@interface EvilChild : MyParent
107- (id)getInt;
Anna Zaks6ec9c3c2012-11-12 23:40:29 +0000108- (const struct __CFString *) testCovariantReturnType __attribute__((cf_returns_retained));
Jordan Roseef77a872012-10-03 16:00:32 +0000109@end
110
111@implementation EvilChild
112- (id)getInt { // expected-warning {{types are incompatible}}
113 return self;
114}
Anna Zaks6ec9c3c2012-11-12 23:40:29 +0000115- (CFStringRef) testCovariantReturnType __attribute__((cf_returns_retained)) {
116 CFStringRef Str = ((void*)0);
117 Str = getString();
118 if (Str) {
119 CFRetain(Str);
120 }
121 return Str;
122}
123
Jordan Roseef77a872012-10-03 16:00:32 +0000124@end
125
126int testNonCovariantReturnType() {
127 MyParent *obj = [[EvilChild alloc] init];
128
129 // Devirtualization allows us to directly call -[EvilChild getInt], but
130 // that returns an id, not an int. There is an off-by-default warning for
131 // this, -Woverriding-method-mismatch, and an on-by-default analyzer warning,
132 // osx.cocoa.IncompatibleMethodTypes. This code would probably crash at
133 // runtime, but at least the analyzer shouldn't crash.
134 int x = 1 + [obj getInt];
135
136 [obj release];
137 return 5/(x-1); // no-warning
138}
Anna Zaks6ec9c3c2012-11-12 23:40:29 +0000139
140int testCovariantReturnTypeNoErrorSinceTypesMatch() {
141 MyParent *obj = [[EvilChild alloc] init];
142
143 CFStringRef S = ((void*)0);
144 S = [obj testCovariantReturnType];
145 if (S)
146 CFRelease(S);
147 CFRelease(obj);
148}