Run DCE after a LoopFlatten test to reduce spurious output [nfc]
[llvm-project.git] / clang / test / Analysis / autoreleasewritechecker_test.m
blob8eab348193d757a77d76ea9c0c20fe56646754f2
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;
7 #define YES ((BOOL)1)
8 @protocol NSObject  - (BOOL)isEqual:(id)object; @end
9 @interface NSObject <NSObject> {}
10 +(id)alloc;
11 -(id)init;
12 -(id)autorelease;
13 -(id)copy;
14 -(id)retain;
15 @end
16 typedef int NSZone;
17 typedef int NSCoder;
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;
24 @end
26 typedef int dispatch_semaphore_t;
27 typedef void (^block_t)();
29 typedef enum {
30   NSEnumerationConcurrent = (1UL << 0),
31   NSEnumerationReverse = (1UL << 1)
32 } NSEnumerationOptions;
34 @interface NSArray
35 - (void)enumerateObjectsUsingBlock:(block_t)block;
36 @end
38 @interface NSSet
39 - (void)objectsPassingTest:(block_t)block;
40 @end
42 @interface NSDictionary
43 - (void)enumerateKeysAndObjectsUsingBlock:(block_t)block;
44 @end
46 @interface NSIndexSet
47 - (void)indexesPassingTest:(block_t)block;
48 - (NSUInteger)indexWithOptions:(NSEnumerationOptions)opts
49                    passingTest:(BOOL (^)(NSUInteger idx, BOOL *stop))predicate;
50 @end
52 typedef int group_t;
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,
58                           group_t group,
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.
67 #ifdef NOARC
69 // expected-no-diagnostics
70 BOOL writeToErrorWithIterator(NSError ** error, NSArray *a) {
71   [a enumerateObjectsUsingBlock:^{
72     *error = [NSError errorWithDomain:1]; // no-warning
73     }];
74   return 0;
76 #endif
78 #ifdef ARC
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;
86 - (BOOL)writeToErrorInAutoreleasePool:(NSError *__autoreleasing *)error;
87 - (BOOL)writeToStrongErrorInAutoreleasePool:(NSError *__strong *)error;
88 - (BOOL)writeToLocalErrorInAutoreleasePool:(NSError *__autoreleasing *)error;
89 - (BOOL)writeToErrorInAutoreleasePoolMultipleTimes:(NSError *__autoreleasing *)error;
90 @end
92 @implementation I
94 - (BOOL) writeToErrorInBlock:(NSError *__autoreleasing *)error {
95     dispatch_semaphore_t sem = dispatch_semaphore_create(0l);
96     dispatch_async(queue, ^{
97         if (error) {
98             *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}}
99         }
100         dispatch_semaphore_signal(sem);
101     });
103     dispatch_semaphore_wait(sem, 100);
104     return 0;
107 - (BOOL) writeToErrorWithDispatchGroup:(NSError *__autoreleasing *)error {
108     dispatch_semaphore_t sem = dispatch_semaphore_create(0l);
109     dispatch_group_async(queue, 0, ^{
110         if (error) {
111             *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}}
112         }
113         dispatch_semaphore_signal(sem);
114     });
116     dispatch_semaphore_wait(sem, 100);
117     return 0;
120 - (BOOL) writeToLocalErrorInBlock:(NSError *__autoreleasing *)error {
121     dispatch_semaphore_t sem = dispatch_semaphore_create(0l);
122     dispatch_async(queue, ^{
123         NSError* error2;
124         NSError*__strong* error3 = &error2;
125         if (error) {
126             *error3 = [NSError errorWithDomain:1]; // no-warning
127         }
128         dispatch_semaphore_signal(sem);
129     });
131     dispatch_semaphore_wait(sem, 100);
132     return 0;
135 - (BOOL) writeToStrongErrorInBlock:(NSError *__strong *)error {
136     dispatch_semaphore_t sem = dispatch_semaphore_create(0l);
137     dispatch_async(queue, ^{
138         if (error) {
139             *error = [NSError errorWithDomain:2]; // no-warning
140         }
141         dispatch_semaphore_signal(sem);
142     });
144     dispatch_semaphore_wait(sem, 100);
145     return 0;
148 - (BOOL) writeToErrorInBlockMultipleTimes:(NSError *__autoreleasing *)error {
149     dispatch_semaphore_t sem = dispatch_semaphore_create(0l);
150     dispatch_async(queue, ^{
151         if (error) {
152             *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}}
153         }
154         dispatch_semaphore_signal(sem);
155     });
156     dispatch_async(queue, ^{
157         if (error) {
158             *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}}
159             *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}}
160         }
161         dispatch_semaphore_signal(sem);
162     });
163     *error = [NSError errorWithDomain:1]; // no-warning
165     dispatch_semaphore_wait(sem, 100);
166     return 0;
169 - (BOOL)writeToErrorInAutoreleasePool:(NSError *__autoreleasing *)error {
170   @autoreleasepool {
171     if (error) {
172       *error = [NSError errorWithDomain:1]; // expected-warning{{Write to autoreleasing out parameter inside locally-scoped autorelease pool; consider writing first to a strong local variable declared outside of the autorelease pool}}
173     }
174   }
176   return 0;
179 - (BOOL)writeToStrongErrorInAutoreleasePool:(NSError *__strong *)error {
180   @autoreleasepool {
181     if (error) {
182       *error = [NSError errorWithDomain:1]; // no-warning
183     }
184   }
186   return 0;
189 - (BOOL)writeToLocalErrorInAutoreleasePool:(NSError *__autoreleasing *)error {
190   NSError *localError;
191   @autoreleasepool {
192     localError = [NSError errorWithDomain:1]; // no-warning
193   }
195   if (error) {
196     *error = localError; // no-warning
197   }
199   return 0;
202 - (BOOL)writeToErrorInAutoreleasePoolMultipleTimes:(NSError *__autoreleasing *)error {
203   @autoreleasepool {
204     if (error) {
205       *error = [NSError errorWithDomain:1]; // expected-warning{{Write to autoreleasing out parameter inside locally-scoped autorelease pool; consider writing first to a strong local variable declared outside of the autorelease pool}}
206     }
207   }
208   if (error) {
209     *error = [NSError errorWithDomain:1]; // no-warning
210   }
211   @autoreleasepool {
212     if (error) {
213       *error = [NSError errorWithDomain:1]; // expected-warning{{Write to autoreleasing out parameter inside locally-scoped autorelease pool; consider writing first to a strong local variable declared outside of the autorelease pool}}
214       *error = [NSError errorWithDomain:1]; // expected-warning{{Write to autoreleasing out parameter inside locally-scoped autorelease pool; consider writing first to a strong local variable declared outside of the autorelease pool}}
215     }
216   }
218   return 0;
221 - (BOOL) writeToError:(NSError *__autoreleasing *)error {
222     *error = [NSError errorWithDomain:1]; // no-warning
223     return 0;
225 @end
227 BOOL writeToErrorInBlockFromCFunc(NSError *__autoreleasing* error) {
228     dispatch_semaphore_t sem = dispatch_semaphore_create(0l);
229     dispatch_async(queue, ^{
230         if (error) {
231             *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}}
232         }
233         dispatch_semaphore_signal(sem);
234     });
236     dispatch_semaphore_wait(sem, 100);
237   return 0;
240 BOOL writeIntoErrorInAutoreleasePoolFromCFunc(NSError *__autoreleasing *error) {
241   @autoreleasepool {
242     if (error) {
243       *error = [NSError errorWithDomain:1]; // expected-warning{{Write to autoreleasing out parameter inside locally-scoped autorelease pool; consider writing first to a strong local variable declared outside of the autorelease pool}}
244     }
245   }
246   return 0;
249 BOOL writeToErrorNoWarning(NSError *__autoreleasing* error) {
250   *error = [NSError errorWithDomain:1]; // no-warning
251   return 0;
254 BOOL writeToErrorWithIterator(NSError *__autoreleasing* error, NSArray *a, NSSet *s, NSDictionary *d, NSIndexSet *i) { [a enumerateObjectsUsingBlock:^{
255     *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}}
256     }];
257   [d enumerateKeysAndObjectsUsingBlock:^{
258     *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}}
259     }];
260   [s objectsPassingTest:^{
261     *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}}
262     }];
263   [i indexesPassingTest:^{
264     *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}}
265     }];
266   [i indexWithOptions: NSEnumerationReverse passingTest:^(NSUInteger idx, BOOL *stop) {
267     *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}}
268     return YES;
269     }];
270   return 0;
273 void writeIntoError(NSError **error) {
274   *error = [NSError errorWithDomain:1];
277 extern void readError(NSError *error);
279 void writeToErrorWithIteratorNonnull(NSError *__autoreleasing* _Nonnull error, NSDictionary *a) {
280   [a enumerateKeysAndObjectsUsingBlock:^{
281      *error = [NSError errorWithDomain:1]; // expected-warning{{Write to autoreleasing out parameter}}
282   }];
286 void escapeErrorFromIterator(NSError *__autoreleasing* _Nonnull error, NSDictionary *a) {
287   [a enumerateKeysAndObjectsUsingBlock:^{
288      writeIntoError(error); // expected-warning{{Capture of autoreleasing out parameter}}
289   }];
292 void noWarningOnRead(NSError *__autoreleasing* error, NSDictionary *a) {
293   [a enumerateKeysAndObjectsUsingBlock:^{
294      NSError* local = *error; // no-warning
295   }];
298 void noWarningOnEscapeRead(NSError *__autoreleasing* error, NSDictionary *a) {
299   [a enumerateKeysAndObjectsUsingBlock:^{
300      readError(*error); // no-warning
301   }];
304 @interface ErrorCapture
305 - (void) captureErrorOut:(NSError**) error;
306 - (void) captureError:(NSError*) error;
307 @end
309 void escapeErrorFromIteratorMethod(NSError *__autoreleasing* _Nonnull error,
310                                    NSDictionary *a,
311                                    ErrorCapture *capturer) {
312   [a enumerateKeysAndObjectsUsingBlock:^{
313       [capturer captureErrorOut:error]; // expected-warning{{Capture of autoreleasing out parameter}}
314   }];
317 void noWarningOnEscapeReadMethod(NSError *__autoreleasing* error,
318                                  NSDictionary *a,
319                                  ErrorCapture *capturer) {
320   [a enumerateKeysAndObjectsUsingBlock:^{
321     [capturer captureError:*error]; // no-warning
322   }];
325 void multipleErrors(NSError *__autoreleasing* error, NSDictionary *a) {
326   [a enumerateKeysAndObjectsUsingBlock:^{
327      writeIntoError(error); // expected-warning{{Capture of autoreleasing out parameter}}
328      *error = [NSError errorWithDomain:1]; // expected-warning{{Write to autoreleasing out parameter}}
329      writeIntoError(error); // expected-warning{{Capture of autoreleasing out parameter}}
330   }];
333 typedef void (^errBlock)(NSError *__autoreleasing *error);
335 extern void expectError(errBlock);
337 void captureAutoreleasingVarFromBlock(NSDictionary *dict) {
338   expectError(^(NSError *__autoreleasing *err) {
339     [dict enumerateKeysAndObjectsUsingBlock:^{
340       writeIntoError(err); // expected-warning{{Capture of autoreleasing out parameter 'err'}}
341     }];
342   });
345 #endif