diff options
| author | George Karpenkov <ekarpenkov@apple.com> | 2018-03-29 20:55:34 +0000 |
|---|---|---|
| committer | George Karpenkov <ekarpenkov@apple.com> | 2018-03-29 20:55:34 +0000 |
| commit | d676ba0f28ee263bc68f6992ca237cdf9395be21 (patch) | |
| tree | 1921f3ffea8f7d5bbaa53fdccc07ea43abda63a3 /clang/test | |
| parent | 309e29d5327519551df54ad1dba88c0643eb6f09 (diff) | |
| download | bcm5719-llvm-d676ba0f28ee263bc68f6992ca237cdf9395be21.tar.gz bcm5719-llvm-d676ba0f28ee263bc68f6992ca237cdf9395be21.zip | |
[analyzer] Path-insensitive checker for writes into an auto-releasing pointer
from the wrong auto-releasing pool, as such writes may crash.
rdar://25301111
Differential Revision: https://reviews.llvm.org/D44722
llvm-svn: 328827
Diffstat (limited to 'clang/test')
| -rw-r--r-- | clang/test/Analysis/autoreleasewritechecker_test.m | 171 |
1 files changed, 171 insertions, 0 deletions
diff --git a/clang/test/Analysis/autoreleasewritechecker_test.m b/clang/test/Analysis/autoreleasewritechecker_test.m new file mode 100644 index 00000000000..ff839f42832 --- /dev/null +++ b/clang/test/Analysis/autoreleasewritechecker_test.m @@ -0,0 +1,171 @@ +// RUN: %clang_analyze_cc1 -DARC -fobjc-arc -analyzer-checker=core,osx.cocoa.AutoreleaseWrite %s -fblocks -verify + + +typedef signed char BOOL; +@protocol NSObject - (BOOL)isEqual:(id)object; @end +@interface NSObject <NSObject> {} ++(id)alloc; +-(id)init; +-(id)autorelease; +-(id)copy; +-(id)retain; +@end +typedef int NSZone; +typedef int NSCoder; +@protocol NSCopying - (id)copyWithZone:(NSZone *)zone; @end +@protocol NSCoding - (void)encodeWithCoder:(NSCoder *)aCoder; @end +@interface NSError : NSObject <NSCopying, NSCoding> {} ++ (id)errorWithDomain:(int)domain; +@end + +typedef int dispatch_semaphore_t; +typedef void (^block_t)(); + +@interface NSArray +- (void) enumerateObjectsUsingBlock:(block_t)block; +@end + +typedef int group_t; +typedef struct dispatch_queue_s *dispatch_queue_t; +typedef void (^dispatch_block_t)(void); +extern dispatch_queue_t queue; + +void dispatch_group_async(dispatch_queue_t queue, + group_t group, + dispatch_block_t block); +void dispatch_async(dispatch_queue_t queue, dispatch_block_t block); +dispatch_semaphore_t dispatch_semaphore_create(int); + +void dispatch_semaphore_wait(dispatch_semaphore_t, int); +void dispatch_semaphore_signal(dispatch_semaphore_t); + +// No warnings without ARC. +#ifdef NOARC + +// expected-no-diagnostics +BOOL writeToErrorWithIterator(NSError ** error, NSArray *a) { + [a enumerateObjectsUsingBlock:^{ + *error = [NSError errorWithDomain:1]; // no-warning + }]; + return 0; +} +#endif + +#ifdef ARC +@interface I : NSObject +- (BOOL) writeToStrongErrorInBlock:(NSError *__strong *)error; +- (BOOL) writeToErrorInBlock:(NSError *__autoreleasing *)error; +- (BOOL) writeToLocalErrorInBlock:(NSError **)error; +- (BOOL) writeToErrorInBlockMultipleTimes:(NSError *__autoreleasing *)error; +- (BOOL) writeToError:(NSError *__autoreleasing *)error; +- (BOOL) writeToErrorWithDispatchGroup:(NSError *__autoreleasing *)error; +@end + +@implementation I + +- (BOOL) writeToErrorInBlock:(NSError *__autoreleasing *)error { + dispatch_semaphore_t sem = dispatch_semaphore_create(0l); + dispatch_async(queue, ^{ + if (error) { + *error = [NSError errorWithDomain:1]; // expected-warning{{Writing into an auto-releasing out parameter inside autorelease pool that may exit before method returns}} + } + dispatch_semaphore_signal(sem); + }); + + dispatch_semaphore_wait(sem, 100); + return 0; +} + +- (BOOL) writeToErrorWithDispatchGroup:(NSError *__autoreleasing *)error { + dispatch_semaphore_t sem = dispatch_semaphore_create(0l); + dispatch_group_async(queue, 0, ^{ + if (error) { + *error = [NSError errorWithDomain:1]; // expected-warning{{Writing into an auto-releasing out}} + } + dispatch_semaphore_signal(sem); + }); + + dispatch_semaphore_wait(sem, 100); + return 0; +} + +- (BOOL) writeToLocalErrorInBlock:(NSError *__autoreleasing *)error { + dispatch_semaphore_t sem = dispatch_semaphore_create(0l); + dispatch_async(queue, ^{ + NSError* error2; + NSError*__strong* error3 = &error2; + if (error) { + *error3 = [NSError errorWithDomain:1]; // no-warning + } + dispatch_semaphore_signal(sem); + }); + + dispatch_semaphore_wait(sem, 100); + return 0; +} + +- (BOOL) writeToStrongErrorInBlock:(NSError *__strong *)error { + dispatch_semaphore_t sem = dispatch_semaphore_create(0l); + dispatch_async(queue, ^{ + if (error) { + *error = [NSError errorWithDomain:2]; // no-warning + } + dispatch_semaphore_signal(sem); + }); + + dispatch_semaphore_wait(sem, 100); + return 0; +} + +- (BOOL) writeToErrorInBlockMultipleTimes:(NSError *__autoreleasing *)error { + dispatch_semaphore_t sem = dispatch_semaphore_create(0l); + dispatch_async(queue, ^{ + if (error) { + *error = [NSError errorWithDomain:1]; // expected-warning{{Writing into an auto-releasing out}} + } + dispatch_semaphore_signal(sem); + }); + dispatch_async(queue, ^{ + if (error) { + *error = [NSError errorWithDomain:1]; // expected-warning{{Writing into an auto-releasing out}} + *error = [NSError errorWithDomain:1]; // expected-warning{{Writing into an auto-releasing out}} + } + dispatch_semaphore_signal(sem); + }); + *error = [NSError errorWithDomain:1]; // no-warning + + dispatch_semaphore_wait(sem, 100); + return 0; +} + +- (BOOL) writeToError:(NSError *__autoreleasing *)error { + *error = [NSError errorWithDomain:1]; // no-warning + return 0; +} +@end + +BOOL writeToErrorInBlockFromCFunc(NSError *__autoreleasing* error) { + dispatch_semaphore_t sem = dispatch_semaphore_create(0l); + dispatch_async(queue, ^{ + if (error) { + *error = [NSError errorWithDomain:1]; // expected-warning{{Writing into an auto-releasing out}} + } + dispatch_semaphore_signal(sem); + }); + + dispatch_semaphore_wait(sem, 100); + return 0; +} + +BOOL writeToErrorNoWarning(NSError *__autoreleasing* error) { + *error = [NSError errorWithDomain:1]; // no-warning + return 0; +} + +BOOL writeToErrorWithIterator(NSError *__autoreleasing* error, NSArray *a) { + [a enumerateObjectsUsingBlock:^{ + *error = [NSError errorWithDomain:1]; // expected-warning{{Writing into an auto-releasing out parameter inside autorelease pool that may exit before function returns; consider writing first to a strong local variable declared outside of the block}} + }]; + return 0; +} +#endif |

