1// RUN: %clang_analyze_cc1 -analyzer-checker=core,osx.cocoa.NilArg,osx.cocoa.RetainCount -analyzer-output=text -analyzer-config suppress-null-return-paths=false -fblocks -verify %s 2// RUN: %clang_analyze_cc1 -analyzer-checker=core,osx.cocoa.NilArg,osx.cocoa.RetainCount -analyzer-output=plist-multi-file -analyzer-config suppress-null-return-paths=false -fblocks %s -o %t.plist 3// RUN: %normalize_plist <%t.plist | diff -ub %S/Inputs/expected-plists/path-notes.m.plist - 4 5typedef struct dispatch_queue_s *dispatch_queue_t; 6typedef void (^dispatch_block_t)(void); 7void dispatch_sync(dispatch_queue_t, dispatch_block_t); 8 9typedef long dispatch_once_t; 10// Note: The real dispatch_once has all parameters marked nonnull. 11// We don't do that here so that we can trigger a null dereference inside 12// the synthesized body. 13void dispatch_once(dispatch_once_t *predicate, dispatch_block_t block); 14 15 16@interface Test 17@property int *p; 18@end 19 20typedef unsigned long NSUInteger; 21typedef signed char BOOL; 22typedef struct _NSZone NSZone; 23@class NSInvocation, NSMethodSignature, NSCoder, NSString, NSEnumerator; 24@protocol NSObject 25@end 26@protocol NSCopying 27- (id)copyWithZone:(NSZone *)zone; 28@end 29@protocol NSMutableCopying 30- (id)mutableCopyWithZone:(NSZone *)zone; 31@end 32@protocol NSCoding 33- (void)encodeWithCoder:(NSCoder *)aCoder; 34@end 35@protocol NSFastEnumeration 36@end 37@protocol NSSecureCoding <NSCoding> 38@required 39+ (BOOL)supportsSecureCoding; 40@end 41@interface NSObject <NSObject> {} 42- (id)init; 43+ (id)alloc; 44- (id)autorelease; 45@end 46@interface NSArray : NSObject <NSCopying, NSMutableCopying, NSSecureCoding, NSFastEnumeration> 47 48- (NSUInteger)count; 49- (id)objectAtIndex:(NSUInteger)index; 50 51@end 52 53@interface NSArray (NSExtendedArray) 54- (NSArray *)arrayByAddingObject:(id)anObject; 55- (void)setObject:(id)obj atIndexedSubscript:(NSUInteger)idx __attribute__((availability(macosx,introduced=10.8))); 56@end 57 58@interface NSArray (NSArrayCreation) 59+ (instancetype)arrayWithObjects:(const id [])objects count:(NSUInteger)cnt; 60@end 61 62@interface NSMutableArray : NSArray 63 64- (void)addObject:(id)anObject; 65- (void)insertObject:(id)anObject atIndex:(NSUInteger)index; 66- (void)removeLastObject; 67- (void)removeObjectAtIndex:(NSUInteger)index; 68- (void)replaceObjectAtIndex:(NSUInteger)index withObject:(id)anObject; 69 70@end 71 72int *getZeroIfNil(Test *x) { 73 return x.p; 74 // expected-note@-1 {{'p' not called because the receiver is nil}} 75 // expected-note@-2 {{Returning null pointer}} 76} 77 78void testReturnZeroIfNil() { 79 *getZeroIfNil(0) = 1; // expected-warning{{Dereference of null pointer}} 80 // expected-note@-1 {{Calling 'getZeroIfNil'}} 81 // expected-note@-2 {{Passing nil object reference via 1st parameter 'x'}} 82 // expected-note@-3 {{Returning from 'getZeroIfNil'}} 83 // expected-note@-4 {{Dereference of null pointer}} 84} 85 86 87int testDispatchSyncInlining() { 88 extern dispatch_queue_t globalQueue; 89 90 __block int x; 91 92 // expected-note@+2 {{Calling 'dispatch_sync'}} 93 // expected-note@+1 {{Returning from 'dispatch_sync'}} 94 dispatch_sync(globalQueue, ^{ 95 // expected-note@-1 {{Calling anonymous block}} 96 // expected-note@-2 {{Returning to caller}} 97 x = 0; 98 // expected-note@-1 {{The value 0 is assigned to 'x'}} 99 }); 100 101 return 1 / x; // expected-warning{{Division by zero}} 102 // expected-note@-1 {{Division by zero}} 103} 104 105int testDispatchSyncInliningNoPruning(int coin) { 106 // This tests exactly the same case as above, except on a bug report where 107 // path pruning is disabled (an uninitialized variable capture). 108 // In this case 109 extern dispatch_queue_t globalQueue; 110 111 __block int y; 112 113 // expected-note@+1 {{Calling 'dispatch_sync'}} 114 dispatch_sync(globalQueue, ^{ 115 // expected-note@-1 {{Calling anonymous block}} 116 int x; 117 // expected-note@-1 {{'x' declared without an initial value}} 118 ^{ y = x; }(); // expected-warning{{Variable 'x' is uninitialized when captured by block}} 119 // expected-note@-1 {{'x' is uninitialized when captured by block}} 120 }); 121 122 return y; 123} 124 125 126@interface PointerWrapper 127- (int *)getPtr; 128@end 129 130id getNil() { 131 return 0; 132} 133 134void testNilReceiverHelper(int *x) { 135 *x = 1; // expected-warning {{Dereference of null pointer}} 136 // expected-note@-1 {{Dereference of null pointer (loaded from variable 'x')}} 137} 138 139void testNilReceiver(id *x, id *y, id *z) { 140 // FIXME: Should say "Assuming pointer value is null" instead. 141 // For some reason we're displaying different notes for 142 // tracked and untracked pointers. 143 if (*y) {} // expected-note {{Assuming the condition is false}} 144 // expected-note@-1 {{Taking false branch}} 145 if (*x) { // expected-note {{Assuming pointer value is null}} 146 // expected-note@-1 {{Taking false branch}} 147 return; 148 } 149 // FIXME: Should say "Assuming pointer value is null" instead. 150 if (*z) {} // expected-note {{Assuming the condition is false}} 151 // expected-note@-1 {{Taking false branch}} 152 testNilReceiverHelper([*x getPtr]); 153 // expected-note@-1 {{'getPtr' not called because the receiver is nil}} 154 // expected-note@-2 {{Passing null pointer value via 1st parameter 'x'}} 155 // expected-note@-3 {{Calling 'testNilReceiverHelper'}} 156} 157 158id testCreateArrayLiteral(id myNil) { 159 if (myNil) // expected-note {{Assuming 'myNil' is nil}} 160 ; // expected-note@-1 {{Taking false branch}} 161 return @[ @"a", myNil, @"c" ]; // expected-warning {{Array element cannot be nil}} 162 //expected-note@-1 {{Array element cannot be nil}} 163} 164 165// <rdar://problem/14611722> 166id testAutoreleaseTakesEffectInDispatch() { 167 static dispatch_once_t token = 0; 168 dispatch_once(&token, ^{}); 169 170 id x = [[[[NSObject alloc] init] autorelease] autorelease]; 171 // expected-note@-1 {{Method returns an instance of NSObject with a +1 retain count}} 172 // expected-note@-2 {{Object autoreleased}} 173 // expected-note@-3 {{Object autoreleased}} 174 175 dispatch_once(&token, ^{}); // don't crash, don't warn here 176 177 return x; // expected-warning{{Object autoreleased too many times}} 178 // expected-note@-1 {{Object was autoreleased 2 times but the object has a +0 retain count}} 179} 180 181void testNullDereferenceInDispatch() { 182 dispatch_once(0, ^{}); // no-warning, don't crash 183} 184 185