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@end 87 88@implementation I 89 90- (BOOL) writeToErrorInBlock:(NSError *__autoreleasing *)error { 91 dispatch_semaphore_t sem = dispatch_semaphore_create(0l); 92 dispatch_async(queue, ^{ 93 if (error) { 94 *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}} 95 } 96 dispatch_semaphore_signal(sem); 97 }); 98 99 dispatch_semaphore_wait(sem, 100); 100 return 0; 101} 102 103- (BOOL) writeToErrorWithDispatchGroup:(NSError *__autoreleasing *)error { 104 dispatch_semaphore_t sem = dispatch_semaphore_create(0l); 105 dispatch_group_async(queue, 0, ^{ 106 if (error) { 107 *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}} 108 } 109 dispatch_semaphore_signal(sem); 110 }); 111 112 dispatch_semaphore_wait(sem, 100); 113 return 0; 114} 115 116- (BOOL) writeToLocalErrorInBlock:(NSError *__autoreleasing *)error { 117 dispatch_semaphore_t sem = dispatch_semaphore_create(0l); 118 dispatch_async(queue, ^{ 119 NSError* error2; 120 NSError*__strong* error3 = &error2; 121 if (error) { 122 *error3 = [NSError errorWithDomain:1]; // no-warning 123 } 124 dispatch_semaphore_signal(sem); 125 }); 126 127 dispatch_semaphore_wait(sem, 100); 128 return 0; 129} 130 131- (BOOL) writeToStrongErrorInBlock:(NSError *__strong *)error { 132 dispatch_semaphore_t sem = dispatch_semaphore_create(0l); 133 dispatch_async(queue, ^{ 134 if (error) { 135 *error = [NSError errorWithDomain:2]; // no-warning 136 } 137 dispatch_semaphore_signal(sem); 138 }); 139 140 dispatch_semaphore_wait(sem, 100); 141 return 0; 142} 143 144- (BOOL) writeToErrorInBlockMultipleTimes:(NSError *__autoreleasing *)error { 145 dispatch_semaphore_t sem = dispatch_semaphore_create(0l); 146 dispatch_async(queue, ^{ 147 if (error) { 148 *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}} 149 } 150 dispatch_semaphore_signal(sem); 151 }); 152 dispatch_async(queue, ^{ 153 if (error) { 154 *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}} 155 *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}} 156 } 157 dispatch_semaphore_signal(sem); 158 }); 159 *error = [NSError errorWithDomain:1]; // no-warning 160 161 dispatch_semaphore_wait(sem, 100); 162 return 0; 163} 164 165- (BOOL) writeToError:(NSError *__autoreleasing *)error { 166 *error = [NSError errorWithDomain:1]; // no-warning 167 return 0; 168} 169@end 170 171BOOL writeToErrorInBlockFromCFunc(NSError *__autoreleasing* error) { 172 dispatch_semaphore_t sem = dispatch_semaphore_create(0l); 173 dispatch_async(queue, ^{ 174 if (error) { 175 *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}} 176 } 177 dispatch_semaphore_signal(sem); 178 }); 179 180 dispatch_semaphore_wait(sem, 100); 181 return 0; 182} 183 184BOOL writeToErrorNoWarning(NSError *__autoreleasing* error) { 185 *error = [NSError errorWithDomain:1]; // no-warning 186 return 0; 187} 188 189BOOL writeToErrorWithIterator(NSError *__autoreleasing* error, NSArray *a, NSSet *s, NSDictionary *d, NSIndexSet *i) { [a enumerateObjectsUsingBlock:^{ 190 *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}} 191 }]; 192 [d enumerateKeysAndObjectsUsingBlock:^{ 193 *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}} 194 }]; 195 [s objectsPassingTest:^{ 196 *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}} 197 }]; 198 [i indexesPassingTest:^{ 199 *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}} 200 }]; 201 [i indexWithOptions: NSEnumerationReverse passingTest:^(NSUInteger idx, BOOL *stop) { 202 *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}} 203 return YES; 204 }]; 205 return 0; 206} 207 208void writeIntoError(NSError **error) { 209 *error = [NSError errorWithDomain:1]; 210} 211 212extern void readError(NSError *error); 213 214void writeToErrorWithIteratorNonnull(NSError *__autoreleasing* _Nonnull error, NSDictionary *a) { 215 [a enumerateKeysAndObjectsUsingBlock:^{ 216 *error = [NSError errorWithDomain:1]; // expected-warning{{Write to autoreleasing out parameter}} 217 }]; 218} 219 220 221void escapeErrorFromIterator(NSError *__autoreleasing* _Nonnull error, NSDictionary *a) { 222 [a enumerateKeysAndObjectsUsingBlock:^{ 223 writeIntoError(error); // expected-warning{{Capture of autoreleasing out parameter}} 224 }]; 225} 226 227void noWarningOnRead(NSError *__autoreleasing* error, NSDictionary *a) { 228 [a enumerateKeysAndObjectsUsingBlock:^{ 229 NSError* local = *error; // no-warning 230 }]; 231} 232 233void noWarningOnEscapeRead(NSError *__autoreleasing* error, NSDictionary *a) { 234 [a enumerateKeysAndObjectsUsingBlock:^{ 235 readError(*error); // no-warning 236 }]; 237} 238 239@interface ErrorCapture 240- (void) captureErrorOut:(NSError**) error; 241- (void) captureError:(NSError*) error; 242@end 243 244void escapeErrorFromIteratorMethod(NSError *__autoreleasing* _Nonnull error, 245 NSDictionary *a, 246 ErrorCapture *capturer) { 247 [a enumerateKeysAndObjectsUsingBlock:^{ 248 [capturer captureErrorOut:error]; // expected-warning{{Capture of autoreleasing out parameter}} 249 }]; 250} 251 252void noWarningOnEscapeReadMethod(NSError *__autoreleasing* error, 253 NSDictionary *a, 254 ErrorCapture *capturer) { 255 [a enumerateKeysAndObjectsUsingBlock:^{ 256 [capturer captureError:*error]; // no-warning 257 }]; 258} 259 260void multipleErrors(NSError *__autoreleasing* error, NSDictionary *a) { 261 [a enumerateKeysAndObjectsUsingBlock:^{ 262 writeIntoError(error); // expected-warning{{Capture of autoreleasing out parameter}} 263 *error = [NSError errorWithDomain:1]; // expected-warning{{Write to autoreleasing out parameter}} 264 writeIntoError(error); // expected-warning{{Capture of autoreleasing out parameter}} 265 }]; 266} 267 268typedef void (^errBlock)(NSError *__autoreleasing *error); 269 270extern void expectError(errBlock); 271 272void captureAutoreleasingVarFromBlock(NSDictionary *dict) { 273 expectError(^(NSError *__autoreleasing *err) { 274 [dict enumerateKeysAndObjectsUsingBlock:^{ 275 writeIntoError(err); // expected-warning{{Capture of autoreleasing out parameter 'err'}} 276 }]; 277 }); 278} 279 280#endif 281 282