1 // UNSUPPORTED: system-windows
2 // RUN: %clang_analyze_cc1 -DARC -fobjc-arc -analyzer-checker=core,osx.cocoa.AutoreleaseWrite %s -triple x86_64-darwin -fblocks -verify
3 // RUN: %clang_analyze_cc1 -DNOARC -analyzer-checker=core,osx.cocoa.AutoreleaseWrite %s -fblocks -triple x86_64-darwin -verify
6 typedef signed char BOOL;
8 @protocol NSObject - (BOOL)isEqual:(id)object; @end
9 @interface NSObject <NSObject> {}
18 typedef unsigned long NSUInteger;
20 @protocol NSCopying - (id)copyWithZone:(NSZone *)zone; @end
21 @protocol NSCoding - (void)encodeWithCoder:(NSCoder *)aCoder; @end
22 @interface NSError : NSObject <NSCopying, NSCoding> {}
23 + (id)errorWithDomain:(int)domain;
26 typedef int dispatch_semaphore_t;
27 typedef void (^block_t)();
30 NSEnumerationConcurrent = (1UL << 0),
31 NSEnumerationReverse = (1UL << 1)
32 } NSEnumerationOptions;
35 - (void)enumerateObjectsUsingBlock:(block_t)block;
39 - (void)objectsPassingTest:(block_t)block;
42 @interface NSDictionary
43 - (void)enumerateKeysAndObjectsUsingBlock:(block_t)block;
47 - (void)indexesPassingTest:(block_t)block;
48 - (NSUInteger)indexWithOptions:(NSEnumerationOptions)opts
49 passingTest:(BOOL (^)(NSUInteger idx, BOOL *stop))predicate;
53 typedef struct dispatch_queue_s *dispatch_queue_t;
54 typedef void (^dispatch_block_t)(void);
55 extern dispatch_queue_t queue;
57 void dispatch_group_async(dispatch_queue_t queue,
59 dispatch_block_t block);
60 void dispatch_async(dispatch_queue_t queue, dispatch_block_t block);
61 dispatch_semaphore_t dispatch_semaphore_create(int);
63 void dispatch_semaphore_wait(dispatch_semaphore_t, int);
64 void dispatch_semaphore_signal(dispatch_semaphore_t);
66 // No warnings without ARC.
69 // expected-no-diagnostics
70 BOOL writeToErrorWithIterator(NSError ** error, NSArray *a) {
71 [a enumerateObjectsUsingBlock:^{
72 *error = [NSError errorWithDomain:1]; // no-warning
79 @interface I : NSObject
80 - (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;
90 - (BOOL) writeToErrorInBlock:(NSError *__autoreleasing *)error {
91 dispatch_semaphore_t sem = dispatch_semaphore_create(0l);
92 dispatch_async(queue, ^{
94 *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}}
96 dispatch_semaphore_signal(sem);
99 dispatch_semaphore_wait(sem, 100);
103 - (BOOL) writeToErrorWithDispatchGroup:(NSError *__autoreleasing *)error {
104 dispatch_semaphore_t sem = dispatch_semaphore_create(0l);
105 dispatch_group_async(queue, 0, ^{
107 *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}}
109 dispatch_semaphore_signal(sem);
112 dispatch_semaphore_wait(sem, 100);
116 - (BOOL) writeToLocalErrorInBlock:(NSError *__autoreleasing *)error {
117 dispatch_semaphore_t sem = dispatch_semaphore_create(0l);
118 dispatch_async(queue, ^{
120 NSError*__strong* error3 = &error2;
122 *error3 = [NSError errorWithDomain:1]; // no-warning
124 dispatch_semaphore_signal(sem);
127 dispatch_semaphore_wait(sem, 100);
131 - (BOOL) writeToStrongErrorInBlock:(NSError *__strong *)error {
132 dispatch_semaphore_t sem = dispatch_semaphore_create(0l);
133 dispatch_async(queue, ^{
135 *error = [NSError errorWithDomain:2]; // no-warning
137 dispatch_semaphore_signal(sem);
140 dispatch_semaphore_wait(sem, 100);
144 - (BOOL) writeToErrorInBlockMultipleTimes:(NSError *__autoreleasing *)error {
145 dispatch_semaphore_t sem = dispatch_semaphore_create(0l);
146 dispatch_async(queue, ^{
148 *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}}
150 dispatch_semaphore_signal(sem);
152 dispatch_async(queue, ^{
154 *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}}
155 *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}}
157 dispatch_semaphore_signal(sem);
159 *error = [NSError errorWithDomain:1]; // no-warning
161 dispatch_semaphore_wait(sem, 100);
165 - (BOOL) writeToError:(NSError *__autoreleasing *)error {
166 *error = [NSError errorWithDomain:1]; // no-warning
171 BOOL writeToErrorInBlockFromCFunc(NSError *__autoreleasing* error) {
172 dispatch_semaphore_t sem = dispatch_semaphore_create(0l);
173 dispatch_async(queue, ^{
175 *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}}
177 dispatch_semaphore_signal(sem);
180 dispatch_semaphore_wait(sem, 100);
184 BOOL writeToErrorNoWarning(NSError *__autoreleasing* error) {
185 *error = [NSError errorWithDomain:1]; // no-warning
189 BOOL writeToErrorWithIterator(NSError *__autoreleasing* error, NSArray *a, NSSet *s, NSDictionary *d, NSIndexSet *i) { [a enumerateObjectsUsingBlock:^{
190 *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}}
192 [d enumerateKeysAndObjectsUsingBlock:^{
193 *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}}
195 [s objectsPassingTest:^{
196 *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}}
198 [i indexesPassingTest:^{
199 *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}}
201 [i indexWithOptions: NSEnumerationReverse passingTest:^(NSUInteger idx, BOOL *stop) {
202 *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}}
208 void writeIntoError(NSError **error) {
209 *error = [NSError errorWithDomain:1];
212 extern void readError(NSError *error);
214 void writeToErrorWithIteratorNonnull(NSError *__autoreleasing* _Nonnull error, NSDictionary *a) {
215 [a enumerateKeysAndObjectsUsingBlock:^{
216 *error = [NSError errorWithDomain:1]; // expected-warning{{Write to autoreleasing out parameter}}
221 void escapeErrorFromIterator(NSError *__autoreleasing* _Nonnull error, NSDictionary *a) {
222 [a enumerateKeysAndObjectsUsingBlock:^{
223 writeIntoError(error); // expected-warning{{Capture of autoreleasing out parameter}}
227 void noWarningOnRead(NSError *__autoreleasing* error, NSDictionary *a) {
228 [a enumerateKeysAndObjectsUsingBlock:^{
229 NSError* local = *error; // no-warning
233 void noWarningOnEscapeRead(NSError *__autoreleasing* error, NSDictionary *a) {
234 [a enumerateKeysAndObjectsUsingBlock:^{
235 readError(*error); // no-warning
239 @interface ErrorCapture
240 - (void) captureErrorOut:(NSError**) error;
241 - (void) captureError:(NSError*) error;
244 void escapeErrorFromIteratorMethod(NSError *__autoreleasing* _Nonnull error,
246 ErrorCapture *capturer) {
247 [a enumerateKeysAndObjectsUsingBlock:^{
248 [capturer captureErrorOut:error]; // expected-warning{{Capture of autoreleasing out parameter}}
252 void noWarningOnEscapeReadMethod(NSError *__autoreleasing* error,
254 ErrorCapture *capturer) {
255 [a enumerateKeysAndObjectsUsingBlock:^{
256 [capturer captureError:*error]; // no-warning
260 void multipleErrors(NSError *__autoreleasing* error, NSDictionary *a) {
261 [a enumerateKeysAndObjectsUsingBlock:^{
262 writeIntoError(error); // expected-warning{{Capture of autoreleasing out parameter}}
263 *error = [NSError errorWithDomain:1]; // expected-warning{{Write to autoreleasing out parameter}}
264 writeIntoError(error); // expected-warning{{Capture of autoreleasing out parameter}}
268 typedef void (^errBlock)(NSError *__autoreleasing *error);
270 extern void expectError(errBlock);
272 void captureAutoreleasingVarFromBlock(NSDictionary *dict) {
273 expectError(^(NSError *__autoreleasing *err) {
274 [dict enumerateKeysAndObjectsUsingBlock:^{
275 writeIntoError(err); // expected-warning{{Capture of autoreleasing out parameter 'err'}}