1// UNSUPPORTED: system-windows 2// RUN: %clang_analyze_cc1 -DARC -fobjc-arc -analyzer-checker=core,osx.cocoa.AutoreleaseWrite %s -triple x86_64-darwin -fblocks -verify 3// RUN: %clang_analyze_cc1 -DNOARC -analyzer-checker=core,osx.cocoa.AutoreleaseWrite %s -fblocks -triple x86_64-darwin -verify 4 5 6typedef signed char BOOL; 7#define YES ((BOOL)1) 8@protocol NSObject - (BOOL)isEqual:(id)object; @end 9@interface NSObject <NSObject> {} 10+(id)alloc; 11-(id)init; 12-(id)autorelease; 13-(id)copy; 14-(id)retain; 15@end 16typedef int NSZone; 17typedef int NSCoder; 18typedef unsigned long NSUInteger; 19 20@protocol NSCopying - (id)copyWithZone:(NSZone *)zone; @end 21@protocol NSCoding - (void)encodeWithCoder:(NSCoder *)aCoder; @end 22@interface NSError : NSObject <NSCopying, NSCoding> {} 23+ (id)errorWithDomain:(int)domain; 24@end 25 26typedef int dispatch_semaphore_t; 27typedef void (^block_t)(); 28 29typedef enum { 30 NSEnumerationConcurrent = (1UL << 0), 31 NSEnumerationReverse = (1UL << 1) 32} NSEnumerationOptions; 33 34@interface NSArray 35- (void)enumerateObjectsUsingBlock:(block_t)block; 36@end 37 38@interface NSSet 39- (void)objectsPassingTest:(block_t)block; 40@end 41 42@interface NSDictionary 43- (void)enumerateKeysAndObjectsUsingBlock:(block_t)block; 44@end 45 46@interface NSIndexSet 47- (void)indexesPassingTest:(block_t)block; 48- (NSUInteger)indexWithOptions:(NSEnumerationOptions)opts 49 passingTest:(BOOL (^)(NSUInteger idx, BOOL *stop))predicate; 50@end 51 52typedef int group_t; 53typedef struct dispatch_queue_s *dispatch_queue_t; 54typedef void (^dispatch_block_t)(void); 55extern dispatch_queue_t queue; 56 57void dispatch_group_async(dispatch_queue_t queue, 58 group_t group, 59 dispatch_block_t block); 60void dispatch_async(dispatch_queue_t queue, dispatch_block_t block); 61dispatch_semaphore_t dispatch_semaphore_create(int); 62 63void dispatch_semaphore_wait(dispatch_semaphore_t, int); 64void dispatch_semaphore_signal(dispatch_semaphore_t); 65 66// No warnings without ARC. 67#ifdef NOARC 68 69// expected-no-diagnostics 70BOOL writeToErrorWithIterator(NSError ** error, NSArray *a) { 71 [a enumerateObjectsUsingBlock:^{ 72 *error = [NSError errorWithDomain:1]; // no-warning 73 }]; 74 return 0; 75} 76#endif 77 78#ifdef ARC 79@interface I : NSObject 80- (BOOL) writeToStrongErrorInBlock:(NSError *__strong *)error; 81- (BOOL) writeToErrorInBlock:(NSError *__autoreleasing *)error; 82- (BOOL) writeToLocalErrorInBlock:(NSError **)error; 83- (BOOL) writeToErrorInBlockMultipleTimes:(NSError *__autoreleasing *)error; 84- (BOOL) writeToError:(NSError *__autoreleasing *)error; 85- (BOOL) writeToErrorWithDispatchGroup:(NSError *__autoreleasing *)error; 86- (BOOL)writeToErrorInAutoreleasePool:(NSError *__autoreleasing *)error; 87- (BOOL)writeToStrongErrorInAutoreleasePool:(NSError *__strong *)error; 88- (BOOL)writeToLocalErrorInAutoreleasePool:(NSError *__autoreleasing *)error; 89- (BOOL)writeToErrorInAutoreleasePoolMultipleTimes:(NSError *__autoreleasing *)error; 90@end 91 92@implementation I 93 94- (BOOL) writeToErrorInBlock:(NSError *__autoreleasing *)error { 95 dispatch_semaphore_t sem = dispatch_semaphore_create(0l); 96 dispatch_async(queue, ^{ 97 if (error) { 98 *error = [NSError errorWithDomain:1]; // expected-warning{{Write to autoreleasing out parameter inside autorelease pool that may exit before method returns; consider writing first to a strong local variable declared outside of the block}} 99 } 100 dispatch_semaphore_signal(sem); 101 }); 102 103 dispatch_semaphore_wait(sem, 100); 104 return 0; 105} 106 107- (BOOL) writeToErrorWithDispatchGroup:(NSError *__autoreleasing *)error { 108 dispatch_semaphore_t sem = dispatch_semaphore_create(0l); 109 dispatch_group_async(queue, 0, ^{ 110 if (error) { 111 *error = [NSError errorWithDomain:1]; // expected-warning{{Write to autoreleasing out parameter inside autorelease pool that may exit before method returns; consider writing first to a strong local variable declared outside of the block}} 112 } 113 dispatch_semaphore_signal(sem); 114 }); 115 116 dispatch_semaphore_wait(sem, 100); 117 return 0; 118} 119 120- (BOOL) writeToLocalErrorInBlock:(NSError *__autoreleasing *)error { 121 dispatch_semaphore_t sem = dispatch_semaphore_create(0l); 122 dispatch_async(queue, ^{ 123 NSError* error2; 124 NSError*__strong* error3 = &error2; 125 if (error) { 126 *error3 = [NSError errorWithDomain:1]; // no-warning 127 } 128 dispatch_semaphore_signal(sem); 129 }); 130 131 dispatch_semaphore_wait(sem, 100); 132 return 0; 133} 134 135- (BOOL) writeToStrongErrorInBlock:(NSError *__strong *)error { 136 dispatch_semaphore_t sem = dispatch_semaphore_create(0l); 137 dispatch_async(queue, ^{ 138 if (error) { 139 *error = [NSError errorWithDomain:2]; // no-warning 140 } 141 dispatch_semaphore_signal(sem); 142 }); 143 144 dispatch_semaphore_wait(sem, 100); 145 return 0; 146} 147 148- (BOOL) writeToErrorInBlockMultipleTimes:(NSError *__autoreleasing *)error { 149 dispatch_semaphore_t sem = dispatch_semaphore_create(0l); 150 dispatch_async(queue, ^{ 151 if (error) { 152 *error = [NSError errorWithDomain:1]; // expected-warning{{Write to autoreleasing out parameter inside autorelease pool that may exit before method returns; consider writing first to a strong local variable declared outside of the block}} 153 } 154 dispatch_semaphore_signal(sem); 155 }); 156 dispatch_async(queue, ^{ 157 if (error) { 158 *error = [NSError errorWithDomain:1]; // expected-warning{{Write to autoreleasing out parameter inside autorelease pool that may exit before method returns; consider writing first to a strong local variable declared outside of the block}} 159 *error = [NSError errorWithDomain:1]; // expected-warning{{Write to autoreleasing out parameter inside autorelease pool that may exit before method returns; consider writing first to a strong local variable declared outside of the block}} 160 } 161 dispatch_semaphore_signal(sem); 162 }); 163 *error = [NSError errorWithDomain:1]; // no-warning 164 165 dispatch_semaphore_wait(sem, 100); 166 return 0; 167} 168 169- (BOOL)writeToErrorInAutoreleasePool:(NSError *__autoreleasing *)error { 170 @autoreleasepool { 171 if (error) { 172 *error = [NSError errorWithDomain:1]; // expected-warning{{Write to autoreleasing out parameter inside locally-scoped autorelease pool; consider writing first to a strong local variable declared outside of the autorelease pool}} 173 } 174 } 175 176 return 0; 177} 178 179- (BOOL)writeToStrongErrorInAutoreleasePool:(NSError *__strong *)error { 180 @autoreleasepool { 181 if (error) { 182 *error = [NSError errorWithDomain:1]; // no-warning 183 } 184 } 185 186 return 0; 187} 188 189- (BOOL)writeToLocalErrorInAutoreleasePool:(NSError *__autoreleasing *)error { 190 NSError *localError; 191 @autoreleasepool { 192 localError = [NSError errorWithDomain:1]; // no-warning 193 } 194 195 if (error) { 196 *error = localError; // no-warning 197 } 198 199 return 0; 200} 201 202- (BOOL)writeToErrorInAutoreleasePoolMultipleTimes:(NSError *__autoreleasing *)error { 203 @autoreleasepool { 204 if (error) { 205 *error = [NSError errorWithDomain:1]; // expected-warning{{Write to autoreleasing out parameter inside locally-scoped autorelease pool; consider writing first to a strong local variable declared outside of the autorelease pool}} 206 } 207 } 208 if (error) { 209 *error = [NSError errorWithDomain:1]; // no-warning 210 } 211 @autoreleasepool { 212 if (error) { 213 *error = [NSError errorWithDomain:1]; // expected-warning{{Write to autoreleasing out parameter inside locally-scoped autorelease pool; consider writing first to a strong local variable declared outside of the autorelease pool}} 214 *error = [NSError errorWithDomain:1]; // expected-warning{{Write to autoreleasing out parameter inside locally-scoped autorelease pool; consider writing first to a strong local variable declared outside of the autorelease pool}} 215 } 216 } 217 218 return 0; 219} 220 221- (BOOL) writeToError:(NSError *__autoreleasing *)error { 222 *error = [NSError errorWithDomain:1]; // no-warning 223 return 0; 224} 225@end 226 227BOOL writeToErrorInBlockFromCFunc(NSError *__autoreleasing* error) { 228 dispatch_semaphore_t sem = dispatch_semaphore_create(0l); 229 dispatch_async(queue, ^{ 230 if (error) { 231 *error = [NSError errorWithDomain:1]; // expected-warning{{Write to autoreleasing out parameter inside autorelease pool that may exit before function returns; consider writing first to a strong local variable declared outside of the block}} 232 } 233 dispatch_semaphore_signal(sem); 234 }); 235 236 dispatch_semaphore_wait(sem, 100); 237 return 0; 238} 239 240BOOL writeIntoErrorInAutoreleasePoolFromCFunc(NSError *__autoreleasing *error) { 241 @autoreleasepool { 242 if (error) { 243 *error = [NSError errorWithDomain:1]; // expected-warning{{Write to autoreleasing out parameter inside locally-scoped autorelease pool; consider writing first to a strong local variable declared outside of the autorelease pool}} 244 } 245 } 246 return 0; 247} 248 249BOOL writeToErrorNoWarning(NSError *__autoreleasing* error) { 250 *error = [NSError errorWithDomain:1]; // no-warning 251 return 0; 252} 253 254BOOL writeToErrorWithIterator(NSError *__autoreleasing* error, NSArray *a, NSSet *s, NSDictionary *d, NSIndexSet *i) { [a enumerateObjectsUsingBlock:^{ 255 *error = [NSError errorWithDomain:1]; // expected-warning{{Write to autoreleasing out parameter inside autorelease pool that may exit before function returns; consider writing first to a strong local variable declared outside of the block}} 256 }]; 257 [d enumerateKeysAndObjectsUsingBlock:^{ 258 *error = [NSError errorWithDomain:1]; // expected-warning{{Write to autoreleasing out parameter inside autorelease pool that may exit before function returns; consider writing first to a strong local variable declared outside of the block}} 259 }]; 260 [s objectsPassingTest:^{ 261 *error = [NSError errorWithDomain:1]; // expected-warning{{Write to autoreleasing out parameter inside autorelease pool that may exit before function returns; consider writing first to a strong local variable declared outside of the block}} 262 }]; 263 [i indexesPassingTest:^{ 264 *error = [NSError errorWithDomain:1]; // expected-warning{{Write to autoreleasing out parameter inside autorelease pool that may exit before function returns; consider writing first to a strong local variable declared outside of the block}} 265 }]; 266 [i indexWithOptions: NSEnumerationReverse passingTest:^(NSUInteger idx, BOOL *stop) { 267 *error = [NSError errorWithDomain:1]; // expected-warning{{Write to autoreleasing out parameter inside autorelease pool that may exit before function returns; consider writing first to a strong local variable declared outside of the block}} 268 return YES; 269 }]; 270 return 0; 271} 272 273void writeIntoError(NSError **error) { 274 *error = [NSError errorWithDomain:1]; 275} 276 277extern void readError(NSError *error); 278 279void writeToErrorWithIteratorNonnull(NSError *__autoreleasing* _Nonnull error, NSDictionary *a) { 280 [a enumerateKeysAndObjectsUsingBlock:^{ 281 *error = [NSError errorWithDomain:1]; // expected-warning{{Write to autoreleasing out parameter}} 282 }]; 283} 284 285 286void escapeErrorFromIterator(NSError *__autoreleasing* _Nonnull error, NSDictionary *a) { 287 [a enumerateKeysAndObjectsUsingBlock:^{ 288 writeIntoError(error); // expected-warning{{Capture of autoreleasing out parameter}} 289 }]; 290} 291 292void noWarningOnRead(NSError *__autoreleasing* error, NSDictionary *a) { 293 [a enumerateKeysAndObjectsUsingBlock:^{ 294 NSError* local = *error; // no-warning 295 }]; 296} 297 298void noWarningOnEscapeRead(NSError *__autoreleasing* error, NSDictionary *a) { 299 [a enumerateKeysAndObjectsUsingBlock:^{ 300 readError(*error); // no-warning 301 }]; 302} 303 304@interface ErrorCapture 305- (void) captureErrorOut:(NSError**) error; 306- (void) captureError:(NSError*) error; 307@end 308 309void escapeErrorFromIteratorMethod(NSError *__autoreleasing* _Nonnull error, 310 NSDictionary *a, 311 ErrorCapture *capturer) { 312 [a enumerateKeysAndObjectsUsingBlock:^{ 313 [capturer captureErrorOut:error]; // expected-warning{{Capture of autoreleasing out parameter}} 314 }]; 315} 316 317void noWarningOnEscapeReadMethod(NSError *__autoreleasing* error, 318 NSDictionary *a, 319 ErrorCapture *capturer) { 320 [a enumerateKeysAndObjectsUsingBlock:^{ 321 [capturer captureError:*error]; // no-warning 322 }]; 323} 324 325void multipleErrors(NSError *__autoreleasing* error, NSDictionary *a) { 326 [a enumerateKeysAndObjectsUsingBlock:^{ 327 writeIntoError(error); // expected-warning{{Capture of autoreleasing out parameter}} 328 *error = [NSError errorWithDomain:1]; // expected-warning{{Write to autoreleasing out parameter}} 329 writeIntoError(error); // expected-warning{{Capture of autoreleasing out parameter}} 330 }]; 331} 332 333typedef void (^errBlock)(NSError *__autoreleasing *error); 334 335extern void expectError(errBlock); 336 337void captureAutoreleasingVarFromBlock(NSDictionary *dict) { 338 expectError(^(NSError *__autoreleasing *err) { 339 [dict enumerateKeysAndObjectsUsingBlock:^{ 340 writeIntoError(err); // expected-warning{{Capture of autoreleasing out parameter 'err'}} 341 }]; 342 }); 343} 344 345#endif 346 347