347 lines · plain
1// UNSUPPORTED: system-windows2// RUN: %clang_analyze_cc1 -DARC -fobjc-arc -analyzer-checker=core,osx.cocoa.AutoreleaseWrite %s -triple x86_64-darwin -fblocks -verify3// RUN: %clang_analyze_cc1 -DNOARC -analyzer-checker=core,osx.cocoa.AutoreleaseWrite %s -fblocks -triple x86_64-darwin -verify4 5 6typedef signed char BOOL;7#define YES ((BOOL)1)8@protocol NSObject - (BOOL)isEqual:(id)object; @end9@interface NSObject <NSObject> {}10+(id)alloc;11-(id)init;12-(id)autorelease;13-(id)copy;14-(id)retain;15@end16typedef int NSZone;17typedef int NSCoder;18typedef unsigned long NSUInteger;19 20@protocol NSCopying - (id)copyWithZone:(NSZone *)zone; @end21@protocol NSCoding - (void)encodeWithCoder:(NSCoder *)aCoder; @end22@interface NSError : NSObject <NSCopying, NSCoding> {}23+ (id)errorWithDomain:(int)domain;24@end25 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 NSArray35- (void)enumerateObjectsUsingBlock:(block_t)block;36@end37 38@interface NSSet39- (void)objectsPassingTest:(block_t)block;40@end41 42@interface NSDictionary43- (void)enumerateKeysAndObjectsUsingBlock:(block_t)block;44@end45 46@interface NSIndexSet47- (void)indexesPassingTest:(block_t)block;48- (NSUInteger)indexWithOptions:(NSEnumerationOptions)opts49 passingTest:(BOOL (^)(NSUInteger idx, BOOL *stop))predicate;50@end51 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 NOARC68 69// expected-no-diagnostics70BOOL writeToErrorWithIterator(NSError ** error, NSArray *a) {71 [a enumerateObjectsUsingBlock:^{72 *error = [NSError errorWithDomain:1]; // no-warning73 }];74 return 0;75}76#endif77 78#ifdef ARC79@interface I : NSObject80- (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@end91 92@implementation I93 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-warning127 }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-warning140 }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-warning164 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-warning183 }184 }185 186 return 0;187}188 189- (BOOL)writeToLocalErrorInAutoreleasePool:(NSError *__autoreleasing *)error {190 NSError *localError;191 @autoreleasepool {192 localError = [NSError errorWithDomain:1]; // no-warning193 }194 195 if (error) {196 *error = localError; // no-warning197 }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-warning210 }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-warning223 return 0;224}225@end226 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-warning251 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-warning295 }];296}297 298void noWarningOnEscapeRead(NSError *__autoreleasing* error, NSDictionary *a) {299 [a enumerateKeysAndObjectsUsingBlock:^{300 readError(*error); // no-warning301 }];302}303 304@interface ErrorCapture305- (void) captureErrorOut:(NSError**) error;306- (void) captureError:(NSError*) error;307@end308 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-warning322 }];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#endif346 347