diff options
Diffstat (limited to 'test/Analysis/inlining/inline-defensive-checks.m')
-rw-r--r-- | test/Analysis/inlining/inline-defensive-checks.m | 129 |
1 files changed, 129 insertions, 0 deletions
diff --git a/test/Analysis/inlining/inline-defensive-checks.m b/test/Analysis/inlining/inline-defensive-checks.m new file mode 100644 index 0000000..0404ee6 --- /dev/null +++ b/test/Analysis/inlining/inline-defensive-checks.m @@ -0,0 +1,129 @@ +// 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; +} |