diff options
| author | Artem Dergachev <artem.dergachev@gmail.com> | 2016-12-08 14:05:48 +0000 |
|---|---|---|
| committer | Artem Dergachev <artem.dergachev@gmail.com> | 2016-12-08 14:05:48 +0000 |
| commit | a4e2541a7088e109ba52215bf338f0d362eadcff (patch) | |
| tree | 9988e7a00f682facd717c246253c8c15ebb4e55b /clang/test | |
| parent | c49fd8c47791572c142af48ac10c9e6bb486c03f (diff) | |
| download | bcm5719-llvm-a4e2541a7088e109ba52215bf338f0d362eadcff.tar.gz bcm5719-llvm-a4e2541a7088e109ba52215bf338f0d362eadcff.zip | |
[analyzer] Add dispatch_data_create as a special case in RetainCountChecker.
This function receives a callback block. The analyzer suspects that this block
may be used to take care of releasing the libdispatch object returned from
the function. In fact, it doesn't - it only releases the raw data buffer.
Inform the analyzer about that. Fixes the resulting false negatives.
rdar://problem/22280098
Differential Revision: https://reviews.llvm.org/D27409
llvm-svn: 289047
Diffstat (limited to 'clang/test')
| -rw-r--r-- | clang/test/Analysis/retain-release-arc.m | 80 |
1 files changed, 80 insertions, 0 deletions
diff --git a/clang/test/Analysis/retain-release-arc.m b/clang/test/Analysis/retain-release-arc.m index e27f519ea69..616e00917fd 100644 --- a/clang/test/Analysis/retain-release-arc.m +++ b/clang/test/Analysis/retain-release-arc.m @@ -1,6 +1,8 @@ // RUN: %clang_cc1 -triple x86_64-apple-darwin10 -analyze -analyzer-checker=core,osx.coreFoundation.CFRetainRelease,osx.cocoa.ClassRelease,osx.cocoa.RetainCount -fobjc-arc -fblocks -verify -Wno-objc-root-class %s -analyzer-output=text // RUN: %clang_cc1 -triple x86_64-apple-darwin10 -analyze -analyzer-checker=core,osx.coreFoundation.CFRetainRelease,osx.cocoa.ClassRelease,osx.cocoa.RetainCount -fblocks -verify -Wno-objc-root-class %s -analyzer-output=text +typedef __typeof(sizeof(int)) size_t; + #define HAS_ARC __has_feature(objc_arc) typedef unsigned long long CFOptionFlags; @@ -45,6 +47,41 @@ typedef struct _NSZone NSZone; @interface NSDictionary : NSObject @end +#define OS_OBJECT_RETURNS_RETAINED __attribute__((__ns_returns_retained__)) +#define DISPATCH_RETURNS_RETAINED OS_OBJECT_RETURNS_RETAINED + +@protocol OS_dispatch_object +@end +@protocol OS_dispatch_data <OS_dispatch_object> +@end +@protocol OS_dispatch_queue <OS_dispatch_object> +@end + +typedef NSObject<OS_dispatch_object> *dispatch_object_t; +typedef NSObject<OS_dispatch_data> *dispatch_data_t; +typedef NSObject<OS_dispatch_queue> *dispatch_queue_t; + +typedef void (^dispatch_block_t)(void); + +dispatch_queue_t dispatch_get_main_queue(void); + +DISPATCH_RETURNS_RETAINED dispatch_data_t +dispatch_data_create(const void *buffer, size_t size, + dispatch_queue_t _Nullable queue, + dispatch_block_t _Nullable destructor); + +void _dispatch_object_validate(dispatch_object_t object); + +#define dispatch_retain(object) \ + __extension__({ dispatch_object_t _o = (object); \ + _dispatch_object_validate(_o); \ + (void)[_o retain]; }) +#define dispatch_release(object) \ + __extension__({ dispatch_object_t _o = (object); \ + _dispatch_object_validate(_o); \ + [_o release]; }) + + @interface SomeClass @end @@ -84,3 +121,46 @@ typedef struct _NSZone NSZone; } @end +int buf[1024]; + +void libdispatch_leaked_data() { + dispatch_data_t data = dispatch_data_create(buf, 1024, + dispatch_get_main_queue(), ^{}); +} +#if !HAS_ARC + // expected-warning@-2{{Potential leak of an object stored into 'data'}} + // expected-note@-5{{Call to function 'dispatch_data_create' returns an Objective-C object with a +1 retain count}} + // expected-note@-4{{Object leaked: object allocated and stored into 'data' is not referenced later in this execution path and has a retain count of +1}} +#endif + +void libdispatch_dispatch_released_data() { + dispatch_data_t data = dispatch_data_create(buf, 1024, + dispatch_get_main_queue(), ^{}); +#if !HAS_ARC + dispatch_release(data); // no-warning +#endif +} + +void libdispatch_objc_released_data() { + dispatch_data_t data = dispatch_data_create(buf, 1024, + dispatch_get_main_queue(), ^{}); +#if !HAS_ARC + [data release]; // no-warning +#endif +} + +void libdispatch_leaked_retained_data() { + dispatch_data_t data = dispatch_data_create(buf, 1024, + dispatch_get_main_queue(), ^{}); +#if !HAS_ARC + dispatch_retain(data); + [data release]; +#endif +} +#if !HAS_ARC +// expected-warning@-2{{Potential leak of an object stored into 'data'}} +// expected-note@-9{{Call to function 'dispatch_data_create' returns an Objective-C object with a +1 retain count}} +// expected-note@-7{{Reference count incremented. The object now has a +2 retain count}} +// expected-note@-7{{Reference count decremented. The object now has a +1 retain count}} +// expected-note@-6{{Object leaked: object allocated and stored into 'data' is not referenced later in this execution path and has a retain count of +1}} +#endif |

