1// RUN: %clang_cc1 -analyze -analyzer-checker=core -analyzer-config suppress-inlined-defensive-checks=true -verify %s 2 3typedef signed char BOOL; 4typedef struct objc_class *Class; 5typedef struct objc_object { 6 Class isa; 7} *id; 8@protocol NSObject - (BOOL)isEqual:(id)object; @end 9@interface NSObject <NSObject> {} 10+(id)alloc; 11+(id)new; 12-(id)init; 13-(id)autorelease; 14-(id)copy; 15- (Class)class; 16-(id)retain; 17@end 18 19// Check that inline defensive checks is triggered for null expressions 20// within CompoundLiteralExpr. 21typedef union { 22 struct dispatch_object_s *_do; 23 struct dispatch_source_s *_ds; 24} dispatch_object_t __attribute__((__transparent_union__)); 25typedef struct dispatch_source_s *dispatch_source_t; 26 27extern __attribute__((visibility("default"))) __attribute__((__nonnull__)) __attribute__((__nothrow__)) 28void 29dispatch_resume(dispatch_object_t object); 30 31@interface AppDelegate : NSObject { 32@protected 33 dispatch_source_t p; 34} 35@end 36@implementation AppDelegate 37- (void)updateDeleteTimer { 38 if (p != ((void*)0)) 39 ; 40} 41- (void)createAndStartDeleteTimer { 42 [self updateDeleteTimer]; 43 dispatch_resume(p); // no warning 44} 45@end 46 47// Test nil receiver suppression. 48// We only suppress on nil receiver if the nil value is directly causing the bug. 49@interface Foo { 50@public 51 int x; 52} 53- (Foo *)getFooPtr; 54@end 55 56Foo *retNil() { 57 return 0; 58} 59 60Foo *retInputOrNil(Foo *p) { 61 if (p) 62 return p; 63 return 0; 64} 65 66void idc(Foo *p) { 67 if (p) 68 ; 69} 70 71int testNilReceiver(Foo* fPtr) { 72 if (fPtr) 73 ; 74 // On a path where fPtr is nil, mem should be nil. 75 Foo *mem = [fPtr getFooPtr]; 76 return mem->x; // expected-warning {{Access to instance variable 'x' results in a dereference of a null pointer}} 77} 78 79int suppressNilReceiverRetNullCond(Foo* fPtr) { 80 unsigned zero = 0; 81 fPtr = retInputOrNil(fPtr); 82 // On a path where fPtr is nzil, mem should be nil. 83 Foo *mem = [fPtr getFooPtr]; 84 return mem->x; 85} 86 87int suppressNilReceiverRetNullCondCast(id fPtr) { 88 unsigned zero = 0; 89 fPtr = retInputOrNil(fPtr); 90 // On a path where fPtr is nzil, mem should be nil. 91 Foo *mem = ((id)([(Foo*)(fPtr) getFooPtr])); 92 return mem->x; 93} 94 95int dontSuppressNilReceiverRetNullCond(Foo* fPtr) { 96 unsigned zero = 0; 97 fPtr = retInputOrNil(fPtr); 98 // On a path where fPtr is nil, mem should be nil. 99 // The warning is not suppressed because the receiver being nil is not 100 // directly related to the value that triggers the warning. 101 Foo *mem = [fPtr getFooPtr]; 102 if (!mem) 103 return 5/zero; // expected-warning {{Division by zero}} 104 return 0; 105} 106 107int dontSuppressNilReceiverRetNull(Foo* fPtr) { 108 unsigned zero = 0; 109 fPtr = retNil(); 110 // On a path where fPtr is nil, mem should be nil. 111 // The warning is not suppressed because the receiver being nil is not 112 // directly related to the value that triggers the warning. 113 Foo *mem = [fPtr getFooPtr]; 114 if (!mem) 115 return 5/zero; // expected-warning {{Division by zero}} 116 return 0; 117} 118 119int dontSuppressNilReceiverIDC(Foo* fPtr) { 120 unsigned zero = 0; 121 idc(fPtr); 122 // On a path where fPtr is nil, mem should be nil. 123 // The warning is not suppressed because the receiver being nil is not 124 // directly related to the value that triggers the warning. 125 Foo *mem = [fPtr getFooPtr]; 126 if (!mem) 127 return 5/zero; // expected-warning {{Division by zero}} 128 return 0; 129} 130