forked from OSchip/llvm-project
130 lines
3.2 KiB
Objective-C
130 lines
3.2 KiB
Objective-C
// RUN: %clang_cc1 -analyze -analyzer-checker=core -analyzer-config suppress-inlined-defensive-checks=true -verify %s
|
|
|
|
typedef signed char BOOL;
|
|
typedef struct objc_class *Class;
|
|
typedef struct objc_object {
|
|
Class isa;
|
|
} *id;
|
|
@protocol NSObject - (BOOL)isEqual:(id)object; @end
|
|
@interface NSObject <NSObject> {}
|
|
+(id)alloc;
|
|
+(id)new;
|
|
-(id)init;
|
|
-(id)autorelease;
|
|
-(id)copy;
|
|
- (Class)class;
|
|
-(id)retain;
|
|
@end
|
|
|
|
// Check that inline defensive checks is triggered for null expressions
|
|
// within CompoundLiteralExpr.
|
|
typedef union {
|
|
struct dispatch_object_s *_do;
|
|
struct dispatch_source_s *_ds;
|
|
} dispatch_object_t __attribute__((__transparent_union__));
|
|
typedef struct dispatch_source_s *dispatch_source_t;
|
|
|
|
extern __attribute__((visibility("default"))) __attribute__((__nonnull__)) __attribute__((__nothrow__))
|
|
void
|
|
dispatch_resume(dispatch_object_t object);
|
|
|
|
@interface AppDelegate : NSObject {
|
|
@protected
|
|
dispatch_source_t p;
|
|
}
|
|
@end
|
|
@implementation AppDelegate
|
|
- (void)updateDeleteTimer {
|
|
if (p != ((void*)0))
|
|
;
|
|
}
|
|
- (void)createAndStartDeleteTimer {
|
|
[self updateDeleteTimer];
|
|
dispatch_resume(p); // no warning
|
|
}
|
|
@end
|
|
|
|
// Test nil receiver suppression.
|
|
// We only suppress on nil receiver if the nil value is directly causing the bug.
|
|
@interface Foo {
|
|
@public
|
|
int x;
|
|
}
|
|
- (Foo *)getFooPtr;
|
|
@end
|
|
|
|
Foo *retNil() {
|
|
return 0;
|
|
}
|
|
|
|
Foo *retInputOrNil(Foo *p) {
|
|
if (p)
|
|
return p;
|
|
return 0;
|
|
}
|
|
|
|
void idc(Foo *p) {
|
|
if (p)
|
|
;
|
|
}
|
|
|
|
int testNilReceiver(Foo* fPtr) {
|
|
if (fPtr)
|
|
;
|
|
// On a path where fPtr is nil, mem should be nil.
|
|
Foo *mem = [fPtr getFooPtr];
|
|
return mem->x; // expected-warning {{Access to instance variable 'x' results in a dereference of a null pointer}}
|
|
}
|
|
|
|
int suppressNilReceiverRetNullCond(Foo* fPtr) {
|
|
unsigned zero = 0;
|
|
fPtr = retInputOrNil(fPtr);
|
|
// On a path where fPtr is nzil, mem should be nil.
|
|
Foo *mem = [fPtr getFooPtr];
|
|
return mem->x;
|
|
}
|
|
|
|
int suppressNilReceiverRetNullCondCast(id fPtr) {
|
|
unsigned zero = 0;
|
|
fPtr = retInputOrNil(fPtr);
|
|
// On a path where fPtr is nzil, mem should be nil.
|
|
Foo *mem = ((id)([(Foo*)(fPtr) getFooPtr]));
|
|
return mem->x;
|
|
}
|
|
|
|
int dontSuppressNilReceiverRetNullCond(Foo* fPtr) {
|
|
unsigned zero = 0;
|
|
fPtr = retInputOrNil(fPtr);
|
|
// On a path where fPtr is nil, mem should be nil.
|
|
// The warning is not suppressed because the receiver being nil is not
|
|
// directly related to the value that triggers the warning.
|
|
Foo *mem = [fPtr getFooPtr];
|
|
if (!mem)
|
|
return 5/zero; // expected-warning {{Division by zero}}
|
|
return 0;
|
|
}
|
|
|
|
int dontSuppressNilReceiverRetNull(Foo* fPtr) {
|
|
unsigned zero = 0;
|
|
fPtr = retNil();
|
|
// On a path where fPtr is nil, mem should be nil.
|
|
// The warning is not suppressed because the receiver being nil is not
|
|
// directly related to the value that triggers the warning.
|
|
Foo *mem = [fPtr getFooPtr];
|
|
if (!mem)
|
|
return 5/zero; // expected-warning {{Division by zero}}
|
|
return 0;
|
|
}
|
|
|
|
int dontSuppressNilReceiverIDC(Foo* fPtr) {
|
|
unsigned zero = 0;
|
|
idc(fPtr);
|
|
// On a path where fPtr is nil, mem should be nil.
|
|
// The warning is not suppressed because the receiver being nil is not
|
|
// directly related to the value that triggers the warning.
|
|
Foo *mem = [fPtr getFooPtr];
|
|
if (!mem)
|
|
return 5/zero; // expected-warning {{Division by zero}}
|
|
return 0;
|
|
}
|