]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - test/Analysis/autoreleasewritechecker_test.m
Vendor import of clang trunk r338150:
[FreeBSD/FreeBSD.git] / test / Analysis / autoreleasewritechecker_test.m
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
4
5
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;
19
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
25
26 typedef int dispatch_semaphore_t;
27 typedef void (^block_t)();
28
29 typedef enum {
30   NSEnumerationConcurrent = (1UL << 0),
31   NSEnumerationReverse = (1UL << 1)
32 } NSEnumerationOptions;
33
34 @interface NSArray
35 - (void)enumerateObjectsUsingBlock:(block_t)block;
36 @end
37
38 @interface NSSet
39 - (void)objectsPassingTest:(block_t)block;
40 @end
41
42 @interface NSDictionary
43 - (void)enumerateKeysAndObjectsUsingBlock:(block_t)block;
44 @end
45
46 @interface NSIndexSet
47 - (void)indexesPassingTest:(block_t)block;
48 - (NSUInteger)indexWithOptions:(NSEnumerationOptions)opts
49                    passingTest:(BOOL (^)(NSUInteger idx, BOOL *stop))predicate;
50 @end
51
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;
56
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);
62
63 void dispatch_semaphore_wait(dispatch_semaphore_t, int);
64 void dispatch_semaphore_signal(dispatch_semaphore_t);
65
66 // No warnings without ARC.
67 #ifdef NOARC
68
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;
75 }
76 #endif
77
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 @end
87
88 @implementation I
89
90 - (BOOL) writeToErrorInBlock:(NSError *__autoreleasing *)error {
91     dispatch_semaphore_t sem = dispatch_semaphore_create(0l);
92     dispatch_async(queue, ^{
93         if (error) {
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}}
95         }
96         dispatch_semaphore_signal(sem);
97     });
98
99     dispatch_semaphore_wait(sem, 100);
100     return 0;
101 }
102
103 - (BOOL) writeToErrorWithDispatchGroup:(NSError *__autoreleasing *)error {
104     dispatch_semaphore_t sem = dispatch_semaphore_create(0l);
105     dispatch_group_async(queue, 0, ^{
106         if (error) {
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}}
108         }
109         dispatch_semaphore_signal(sem);
110     });
111
112     dispatch_semaphore_wait(sem, 100);
113     return 0;
114 }
115
116 - (BOOL) writeToLocalErrorInBlock:(NSError *__autoreleasing *)error {
117     dispatch_semaphore_t sem = dispatch_semaphore_create(0l);
118     dispatch_async(queue, ^{
119         NSError* error2;
120         NSError*__strong* error3 = &error2;
121         if (error) {
122             *error3 = [NSError errorWithDomain:1]; // no-warning
123         }
124         dispatch_semaphore_signal(sem);
125     });
126
127     dispatch_semaphore_wait(sem, 100);
128     return 0;
129 }
130
131 - (BOOL) writeToStrongErrorInBlock:(NSError *__strong *)error {
132     dispatch_semaphore_t sem = dispatch_semaphore_create(0l);
133     dispatch_async(queue, ^{
134         if (error) {
135             *error = [NSError errorWithDomain:2]; // no-warning
136         }
137         dispatch_semaphore_signal(sem);
138     });
139
140     dispatch_semaphore_wait(sem, 100);
141     return 0;
142 }
143
144 - (BOOL) writeToErrorInBlockMultipleTimes:(NSError *__autoreleasing *)error {
145     dispatch_semaphore_t sem = dispatch_semaphore_create(0l);
146     dispatch_async(queue, ^{
147         if (error) {
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}}
149         }
150         dispatch_semaphore_signal(sem);
151     });
152     dispatch_async(queue, ^{
153         if (error) {
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}}
156         }
157         dispatch_semaphore_signal(sem);
158     });
159     *error = [NSError errorWithDomain:1]; // no-warning
160
161     dispatch_semaphore_wait(sem, 100);
162     return 0;
163 }
164
165 - (BOOL) writeToError:(NSError *__autoreleasing *)error {
166     *error = [NSError errorWithDomain:1]; // no-warning
167     return 0;
168 }
169 @end
170
171 BOOL writeToErrorInBlockFromCFunc(NSError *__autoreleasing* error) {
172     dispatch_semaphore_t sem = dispatch_semaphore_create(0l);
173     dispatch_async(queue, ^{
174         if (error) {
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}}
176         }
177         dispatch_semaphore_signal(sem);
178     });
179
180     dispatch_semaphore_wait(sem, 100);
181   return 0;
182 }
183
184 BOOL writeToErrorNoWarning(NSError *__autoreleasing* error) {
185   *error = [NSError errorWithDomain:1]; // no-warning
186   return 0;
187 }
188
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}}
191     }];
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}}
194     }];
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}}
197     }];
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}}
200     }];
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}}
203     return YES;
204     }];
205   return 0;
206 }
207
208 void writeIntoError(NSError **error) {
209   *error = [NSError errorWithDomain:1];
210 }
211
212 extern void readError(NSError *error);
213
214 void writeToErrorWithIteratorNonnull(NSError *__autoreleasing* _Nonnull error, NSDictionary *a) {
215   [a enumerateKeysAndObjectsUsingBlock:^{
216      *error = [NSError errorWithDomain:1]; // expected-warning{{Write to autoreleasing out parameter}}
217   }];
218 }
219
220
221 void escapeErrorFromIterator(NSError *__autoreleasing* _Nonnull error, NSDictionary *a) {
222   [a enumerateKeysAndObjectsUsingBlock:^{
223      writeIntoError(error); // expected-warning{{Capture of autoreleasing out parameter}}
224   }];
225 }
226
227 void noWarningOnRead(NSError *__autoreleasing* error, NSDictionary *a) {
228   [a enumerateKeysAndObjectsUsingBlock:^{
229      NSError* local = *error; // no-warning
230   }];
231 }
232
233 void noWarningOnEscapeRead(NSError *__autoreleasing* error, NSDictionary *a) {
234   [a enumerateKeysAndObjectsUsingBlock:^{
235      readError(*error); // no-warning
236   }];
237 }
238
239 @interface ErrorCapture
240 - (void) captureErrorOut:(NSError**) error;
241 - (void) captureError:(NSError*) error;
242 @end
243
244 void escapeErrorFromIteratorMethod(NSError *__autoreleasing* _Nonnull error,
245                                    NSDictionary *a,
246                                    ErrorCapture *capturer) {
247   [a enumerateKeysAndObjectsUsingBlock:^{
248       [capturer captureErrorOut:error]; // expected-warning{{Capture of autoreleasing out parameter}}
249   }];
250 }
251
252 void noWarningOnEscapeReadMethod(NSError *__autoreleasing* error,
253                                  NSDictionary *a,
254                                  ErrorCapture *capturer) {
255   [a enumerateKeysAndObjectsUsingBlock:^{
256     [capturer captureError:*error]; // no-warning
257   }];
258 }
259
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}}
265   }];
266 }
267
268 typedef void (^errBlock)(NSError *__autoreleasing *error);
269
270 extern void expectError(errBlock);
271
272 void captureAutoreleasingVarFromBlock(NSDictionary *dict) {
273   expectError(^(NSError *__autoreleasing *err) {
274     [dict enumerateKeysAndObjectsUsingBlock:^{
275       writeIntoError(err); // expected-warning{{Capture of autoreleasing out parameter 'err'}}
276     }];
277   });
278 }
279
280 #endif
281