diff options
| -rw-r--r-- | clang/lib/StaticAnalyzer/Checkers/ObjCAutoreleaseWriteChecker.cpp | 37 | ||||
| -rw-r--r-- | clang/test/Analysis/autoreleasewritechecker_test.m | 54 |
2 files changed, 75 insertions, 16 deletions
diff --git a/clang/lib/StaticAnalyzer/Checkers/ObjCAutoreleaseWriteChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/ObjCAutoreleaseWriteChecker.cpp index 0433a8aea37..d53827b596e 100644 --- a/clang/lib/StaticAnalyzer/Checkers/ObjCAutoreleaseWriteChecker.cpp +++ b/clang/lib/StaticAnalyzer/Checkers/ObjCAutoreleaseWriteChecker.cpp @@ -51,18 +51,43 @@ public: BugReporter &BR) const; private: std::vector<std::string> SelectorsWithAutoreleasingPool = { + // Common to NSArray, NSSet, NSOrderedSet "enumerateObjectsUsingBlock:", - "enumerateKeysAndObjectsUsingBlock:", - "enumerateKeysAndObjectsWithOptions:usingBlock:", "enumerateObjectsWithOptions:usingBlock:", + + // Common to NSArray and NSOrderedSet "enumerateObjectsAtIndexes:options:usingBlock:", + "indexOfObjectAtIndexes:options:passingTest:", + "indexesOfObjectsAtIndexes:options:passingTest:", + "indexOfObjectPassingTest:", + "indexOfObjectWithOptions:passingTest:", + "indexesOfObjectsPassingTest:", + "indexesOfObjectsWithOptions:passingTest:", + + // NSDictionary + "enumerateKeysAndObjectsUsingBlock:", + "enumerateKeysAndObjectsWithOptions:usingBlock:", + "keysOfEntriesPassingTest:", + "keysOfEntriesWithOptions:passingTest:", + + // NSSet + "objectsPassingTest:", + "objectsWithOptions:passingTest:", + "enumerateIndexPathsWithOptions:usingBlock:", + + // NSIndexSet "enumerateIndexesWithOptions:usingBlock:", "enumerateIndexesUsingBlock:", "enumerateIndexesInRange:options:usingBlock:", "enumerateRangesUsingBlock:", "enumerateRangesWithOptions:usingBlock:", - "enumerateRangesInRange:options:usingBlock:" - "objectWithOptions:passingTest:", + "enumerateRangesInRange:options:usingBlock:", + "indexPassingTest:", + "indexesPassingTest:", + "indexWithOptions:passingTest:", + "indexesWithOptions:passingTest:", + "indexInRange:options:passingTest:", + "indexesInRange:options:passingTest:" }; std::vector<std::string> FunctionsWithAutoreleasingPool = { @@ -95,9 +120,9 @@ static void emitDiagnostics(BoundNodes &Match, const Decl *D, BugReporter &BR, assert(SW); BR.EmitBasicReport( ADC->getDecl(), Checker, - /*Name=*/"Writing into auto-releasing variable from a different queue", + /*Name=*/"Write to autoreleasing out parameter inside autorelease pool", /*Category=*/"Memory", - (llvm::Twine("Writing into an auto-releasing out parameter inside ") + + (llvm::Twine("Write to autoreleasing out parameter inside ") + "autorelease pool that may exit before " + Name + " returns; consider " "writing first to a strong local variable declared outside of the block") .str(), diff --git a/clang/test/Analysis/autoreleasewritechecker_test.m b/clang/test/Analysis/autoreleasewritechecker_test.m index 6b01ad83bc4..98348011b8e 100644 --- a/clang/test/Analysis/autoreleasewritechecker_test.m +++ b/clang/test/Analysis/autoreleasewritechecker_test.m @@ -4,6 +4,7 @@ typedef signed char BOOL; +#define YES ((BOOL)1) @protocol NSObject - (BOOL)isEqual:(id)object; @end @interface NSObject <NSObject> {} +(id)alloc; @@ -14,6 +15,8 @@ typedef signed char BOOL; @end typedef int NSZone; typedef int NSCoder; +typedef unsigned long NSUInteger; + @protocol NSCopying - (id)copyWithZone:(NSZone *)zone; @end @protocol NSCoding - (void)encodeWithCoder:(NSCoder *)aCoder; @end @interface NSError : NSObject <NSCopying, NSCoding> {} @@ -23,8 +26,27 @@ typedef int NSCoder; typedef int dispatch_semaphore_t; typedef void (^block_t)(); +typedef enum { + NSEnumerationConcurrent = (1UL << 0), + NSEnumerationReverse = (1UL << 1) +} NSEnumerationOptions; + @interface NSArray -- (void) enumerateObjectsUsingBlock:(block_t)block; +- (void)enumerateObjectsUsingBlock:(block_t)block; +@end + +@interface NSSet +- (void)objectsPassingTest:(block_t)block; +@end + +@interface NSDictionary +- (void)enumerateKeysAndObjectsUsingBlock:(block_t)block; +@end + +@interface NSIndexSet +- (void)indexesPassingTest:(block_t)block; +- (NSUInteger)indexWithOptions:(NSEnumerationOptions)opts + passingTest:(BOOL (^)(NSUInteger idx, BOOL *stop))predicate; @end typedef int group_t; @@ -69,7 +91,7 @@ BOOL writeToErrorWithIterator(NSError ** error, NSArray *a) { 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}} + *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}} } dispatch_semaphore_signal(sem); }); @@ -82,7 +104,7 @@ BOOL writeToErrorWithIterator(NSError ** error, NSArray *a) { 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}} + *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}} } dispatch_semaphore_signal(sem); }); @@ -123,14 +145,14 @@ BOOL writeToErrorWithIterator(NSError ** error, NSArray *a) { 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}} + *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}} } 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}} + *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}} + *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}} } dispatch_semaphore_signal(sem); }); @@ -150,7 +172,7 @@ 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}} + *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}} } dispatch_semaphore_signal(sem); }); @@ -164,9 +186,21 @@ BOOL writeToErrorNoWarning(NSError *__autoreleasing* error) { 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}} +BOOL writeToErrorWithIterator(NSError *__autoreleasing* error, NSArray *a, NSSet *s, NSDictionary *d, NSIndexSet *i) { [a enumerateObjectsUsingBlock:^{ + *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}} + }]; + [d enumerateKeysAndObjectsUsingBlock:^{ + *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}} + }]; + [s objectsPassingTest:^{ + *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}} + }]; + [i indexesPassingTest:^{ + *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}} + }]; + [i indexWithOptions: NSEnumerationReverse passingTest:^(NSUInteger idx, BOOL *stop) { + *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}} + return YES; }]; return 0; } |

