xref: /aosp_15_r20/external/clang/test/Analysis/inlining/InlineObjCInstanceMethod.m (revision 67e74705e28f6214e480b399dd47ea732279e315)
1*67e74705SXin Li// RUN: %clang --analyze -Xanalyzer -analyzer-checker=osx.cocoa.IncompatibleMethodTypes,osx.coreFoundation.CFRetainRelease -Xclang -verify %s
2*67e74705SXin Li
3*67e74705SXin Li#include "InlineObjCInstanceMethod.h"
4*67e74705SXin Li
5*67e74705SXin Litypedef const struct __CFString * CFStringRef;
6*67e74705SXin Litypedef const void * CFTypeRef;
7*67e74705SXin Liextern CFTypeRef CFRetain(CFTypeRef cf);
8*67e74705SXin Liextern void CFRelease(CFTypeRef cf);
9*67e74705SXin Liextern CFStringRef getString(void);
10*67e74705SXin Li
11*67e74705SXin Li// Method is defined in the parent; called through self.
12*67e74705SXin Li@interface MyParent : NSObject
13*67e74705SXin Li- (int)getInt;
14*67e74705SXin Li- (const struct __CFString *) testCovariantReturnType __attribute__((cf_returns_retained));
15*67e74705SXin Li@end
16*67e74705SXin Li@implementation MyParent
17*67e74705SXin Li- (int)getInt {
18*67e74705SXin Li    return 0;
19*67e74705SXin Li}
20*67e74705SXin Li
21*67e74705SXin Li- (CFStringRef) testCovariantReturnType __attribute__((cf_returns_retained)) {
22*67e74705SXin Li  CFStringRef Str = ((void*)0);
23*67e74705SXin Li  Str = getString();
24*67e74705SXin Li  if (Str) {
25*67e74705SXin Li    CFRetain(Str);
26*67e74705SXin Li  }
27*67e74705SXin Li  return Str;
28*67e74705SXin Li}
29*67e74705SXin Li
30*67e74705SXin Li@end
31*67e74705SXin Li
32*67e74705SXin Li@interface MyClass : MyParent
33*67e74705SXin Li@end
34*67e74705SXin Li@implementation MyClass
35*67e74705SXin Li- (int)testDynDispatchSelf {
36*67e74705SXin Li  int y = [self getInt];
37*67e74705SXin Li  return 5/y; // expected-warning {{Division by zero}}
38*67e74705SXin Li}
39*67e74705SXin Li
40*67e74705SXin Li// Get the dynamic type info from a cast (from id to MyClass*).
41*67e74705SXin Li+ (int)testAllocInit {
42*67e74705SXin Li  MyClass *a = [[self alloc] init];
43*67e74705SXin Li  return 5/[a getInt]; // expected-warning {{Division by zero}}
44*67e74705SXin Li}
45*67e74705SXin Li
46*67e74705SXin Li// Method is called on inited object.
47*67e74705SXin Li+ (int)testAllocInit2 {
48*67e74705SXin Li  MyClass *a = [[MyClass alloc] init];
49*67e74705SXin Li  return 5/[a getInt]; // expected-warning {{Division by zero}}
50*67e74705SXin Li}
51*67e74705SXin Li
52*67e74705SXin Li// Method is called on a parameter.
53*67e74705SXin Li+ (int)testParam: (MyClass*) a {
54*67e74705SXin Li  return 5/[a getInt]; // expected-warning {{Division by zero}}
55*67e74705SXin Li}
56*67e74705SXin Li
57*67e74705SXin Li// Method is called on a parameter of unnown type.
58*67e74705SXin Li+ (int)testParamUnknownType: (id) a {
59*67e74705SXin Li  return 5/[a getInt]; // no warning
60*67e74705SXin Li}
61*67e74705SXin Li
62*67e74705SXin Li@end
63*67e74705SXin Li
64*67e74705SXin Li// TODO: When method is inlined, the attribute reset should be visible.
65*67e74705SXin Li@interface TestSettingAnAttributeInCallee : NSObject {
66*67e74705SXin Li  int _attribute;
67*67e74705SXin Li}
68*67e74705SXin Li  - (void) method2;
69*67e74705SXin Li@end
70*67e74705SXin Li
71*67e74705SXin Li@implementation TestSettingAnAttributeInCallee
72*67e74705SXin Li- (int) method1 {
73*67e74705SXin Li  [self method2];
74*67e74705SXin Li  return 5/_attribute; // expected-warning {{Division by zero}}
75*67e74705SXin Li}
76*67e74705SXin Li
77*67e74705SXin Li- (void) method2 {
78*67e74705SXin Li  _attribute = 0;
79*67e74705SXin Li}
80*67e74705SXin Li@end
81*67e74705SXin Li
82*67e74705SXin Li@interface TestSettingAnAttributeInCaller : NSObject {
83*67e74705SXin Li  int _attribute;
84*67e74705SXin Li}
85*67e74705SXin Li  - (int) method2;
86*67e74705SXin Li@end
87*67e74705SXin Li
88*67e74705SXin Li@implementation TestSettingAnAttributeInCaller
89*67e74705SXin Li- (void) method1 {
90*67e74705SXin Li  _attribute = 0;
91*67e74705SXin Li  [self method2];
92*67e74705SXin Li}
93*67e74705SXin Li
94*67e74705SXin Li- (int) method2 {
95*67e74705SXin Li  return 5/_attribute; // expected-warning {{Division by zero}}
96*67e74705SXin Li}
97*67e74705SXin Li@end
98*67e74705SXin Li
99*67e74705SXin Li
100*67e74705SXin Li// Don't crash if we don't know the receiver's region.
101*67e74705SXin Livoid randomlyMessageAnObject(MyClass *arr[], int i) {
102*67e74705SXin Li  (void)[arr[i] getInt];
103*67e74705SXin Li}
104*67e74705SXin Li
105*67e74705SXin Li
106*67e74705SXin Li@interface EvilChild : MyParent
107*67e74705SXin Li- (id)getInt;
108*67e74705SXin Li- (const struct __CFString *) testCovariantReturnType __attribute__((cf_returns_retained));
109*67e74705SXin Li@end
110*67e74705SXin Li
111*67e74705SXin Li@implementation EvilChild
112*67e74705SXin Li- (id)getInt { // expected-warning {{types are incompatible}}
113*67e74705SXin Li  return self;
114*67e74705SXin Li}
115*67e74705SXin Li- (CFStringRef) testCovariantReturnType __attribute__((cf_returns_retained)) {
116*67e74705SXin Li  CFStringRef Str = ((void*)0);
117*67e74705SXin Li  Str = getString();
118*67e74705SXin Li  if (Str) {
119*67e74705SXin Li    CFRetain(Str);
120*67e74705SXin Li  }
121*67e74705SXin Li  return Str;
122*67e74705SXin Li}
123*67e74705SXin Li
124*67e74705SXin Li@end
125*67e74705SXin Li
126*67e74705SXin Liint testNonCovariantReturnType() {
127*67e74705SXin Li  MyParent *obj = [[EvilChild alloc] init];
128*67e74705SXin Li
129*67e74705SXin Li  // Devirtualization allows us to directly call -[EvilChild getInt], but
130*67e74705SXin Li  // that returns an id, not an int. There is an off-by-default warning for
131*67e74705SXin Li  // this, -Woverriding-method-mismatch, and an on-by-default analyzer warning,
132*67e74705SXin Li  // osx.cocoa.IncompatibleMethodTypes. This code would probably crash at
133*67e74705SXin Li  // runtime, but at least the analyzer shouldn't crash.
134*67e74705SXin Li  int x = 1 + [obj getInt];
135*67e74705SXin Li
136*67e74705SXin Li  [obj release];
137*67e74705SXin Li  return 5/(x-1); // no-warning
138*67e74705SXin Li}
139*67e74705SXin Li
140*67e74705SXin Liint testCovariantReturnTypeNoErrorSinceTypesMatch() {
141*67e74705SXin Li  MyParent *obj = [[EvilChild alloc] init];
142*67e74705SXin Li
143*67e74705SXin Li  CFStringRef S = ((void*)0);
144*67e74705SXin Li  S = [obj testCovariantReturnType];
145*67e74705SXin Li  if (S)
146*67e74705SXin Li    CFRelease(S);
147*67e74705SXin Li  CFRelease(obj);
148*67e74705SXin Li}
149