summaryrefslogtreecommitdiffstats
path: root/clang/test
diff options
context:
space:
mode:
authorArtem Dergachev <artem.dergachev@gmail.com>2016-12-08 14:05:48 +0000
committerArtem Dergachev <artem.dergachev@gmail.com>2016-12-08 14:05:48 +0000
commita4e2541a7088e109ba52215bf338f0d362eadcff (patch)
tree9988e7a00f682facd717c246253c8c15ebb4e55b /clang/test
parentc49fd8c47791572c142af48ac10c9e6bb486c03f (diff)
downloadbcm5719-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.m80
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
OpenPOWER on IntegriCloud