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