[clang][NFC] simplify the unset check in `ParseLabeledStatement` (#117430)
[llvm-project.git] / clang / test / Analysis / stack-capture-leak-arc.mm
blob921487a86ca4d3de9161e01cf7bf44c28a83e421
1 // RUN: %clang_analyze_cc1 -triple x86_64-apple-darwin10 -analyzer-checker=core,alpha.core.StackAddressAsyncEscape -fblocks -fobjc-arc -verify %s
3 typedef struct dispatch_queue_s *dispatch_queue_t;
4 typedef void (^dispatch_block_t)(void);
5 void dispatch_async(dispatch_queue_t queue, dispatch_block_t block);
6 typedef long dispatch_once_t;
7 void dispatch_once(dispatch_once_t *predicate, dispatch_block_t block);
8 typedef long dispatch_time_t;
9 void dispatch_after(dispatch_time_t when, dispatch_queue_t queue, dispatch_block_t block);
10 void dispatch_barrier_sync(dispatch_queue_t queue, dispatch_block_t block);
11 void f(int);
13 extern dispatch_queue_t queue;
14 extern dispatch_once_t *predicate;
15 extern dispatch_time_t when;
17 void test_block_expr_async() {
18   int x = 123;
19   int *p = &x;
21   dispatch_async(queue, ^{
22     *p = 321;
23   });
24   // expected-warning@-3 {{Address of stack memory associated with local variable 'x' \
25 is captured by an asynchronously-executed block}}
28 void test_block_expr_once_no_leak() {
29   int x = 123;
30   int *p = &x;
31   // synchronous, no warning
32   dispatch_once(predicate, ^{
33     *p = 321;
34   });
37 void test_block_expr_after() {
38   int x = 123;
39   int *p = &x;
40   dispatch_after(when, queue, ^{
41     *p = 321;
42   });
43   // expected-warning@-3 {{Address of stack memory associated with local variable 'x' \
44 is captured by an asynchronously-executed block}}
47 void test_block_expr_async_no_leak() {
48   int x = 123;
49   int *p = &x;
50   // no leak
51   dispatch_async(queue, ^{
52     int y = x;
53     ++y;
54   });
57 void test_block_var_async() {
58   int x = 123;
59   int *p = &x;
60   void (^b)(void) = ^void(void) {
61     *p = 1; 
62   };
63   dispatch_async(queue, b);
64   // expected-warning@-1 {{Address of stack memory associated with local variable 'x' \
65 is captured by an asynchronously-executed block}}
68 void test_block_with_ref_async() {
69   int x = 123;
70   int &r = x;
71   void (^b)(void) = ^void(void) {
72     r = 1; 
73   };
74   dispatch_async(queue, b);
75   // expected-warning@-1 {{Address of stack memory associated with local variable 'x' \
76 is captured by an asynchronously-executed block}}
79 dispatch_block_t get_leaking_block() {
80   int leaked_x = 791;
81   int *p = &leaked_x;
82   return ^void(void) {
83     *p = 1; 
84   };
85   // expected-warning@-3 {{Address of stack memory associated with local variable 'leaked_x' \
86 is captured by a returned block}}
89 void test_returned_from_func_block_async() {
90   dispatch_async(queue, get_leaking_block());
91   // expected-warning@-1 {{Address of stack memory associated with local variable 'leaked_x' \
92 is captured by an asynchronously-executed block}}
95 // synchronous, no leak
96 void test_block_var_once() {
97   int x = 123;
98   int *p = &x;
99   void (^b)(void) = ^void(void) {
100     *p = 1; 
101   };
102   dispatch_once(predicate, b); // no-warning
105 void test_block_var_after() {
106   int x = 123;
107   int *p = &x;
108   void (^b)(void) = ^void(void) {
109     *p = 1; 
110   };
111   dispatch_after(when, queue, b);
112   // expected-warning@-1 {{Address of stack memory associated with local variable 'x' \
113 is captured by an asynchronously-executed block}}
116 void test_block_var_async_no_leak() {
117   int x = 123;
118   int *p = &x;
119   void (^b)(void) = ^void(void) {
120     int y = x;
121     ++y; 
122   };
123   dispatch_async(queue, b); // no-warning
126 void test_block_inside_block_async_no_leak() {
127   int x = 123;
128   int *p = &x;
129   void (^inner)(void) = ^void(void) {
130     int y = x;
131     ++y; 
132   };
133   void (^outer)(void) = ^void(void) {
134     int z = x;
135     ++z;
136     inner(); 
137   };
138   dispatch_async(queue, outer); // no-warning
141 dispatch_block_t accept_and_pass_back_block(dispatch_block_t block) {
142   block();
143   return block; // no-warning
146 void test_passing_continuation_no_leak() {
147   int x = 123;
148   int *p = &x;
149   void (^cont)(void) = ^void(void) {
150     *p = 128;
151   };
152   accept_and_pass_back_block(cont); // no-warning
155 @interface NSObject
156 @end
157 @protocol OS_dispatch_semaphore
158 @end
159 typedef NSObject<OS_dispatch_semaphore> *dispatch_semaphore_t;
160 dispatch_semaphore_t dispatch_semaphore_create(long value);
161 long dispatch_semaphore_wait(dispatch_semaphore_t dsema, dispatch_time_t timeout);
162 long dispatch_semaphore_signal(dispatch_semaphore_t dsema);
164 void test_no_leaks_on_semaphore_pattern() {
165   int x = 0;
166   int *p = &x;
167   dispatch_semaphore_t semaphore = dispatch_semaphore_create(0);
168   dispatch_async(queue, ^{
169     *p = 1;
170     // Some work.
171     dispatch_semaphore_signal(semaphore);
172   }); // no-warning
174   // Do some other work concurrently with the asynchronous work
175   // Wait for the asynchronous work to finish
176   dispatch_semaphore_wait(semaphore, 1000);
179 void test_dispatch_barrier_sync() {
180   int buf[16];
181   for (int n = 0; n < 16; ++n) {
182     int *ptr = &buf[n];
183     // FIXME: Should not warn. The dispatch_barrier_sync() call ensures
184     // that the block does not outlive 'buf'.
185     dispatch_async(queue, ^{ // expected-warning{{Address of stack memory associated with local variable 'buf' is captured by an asynchronously-executed block}}
186       (void)ptr;
187     });
188   }
189   dispatch_barrier_sync(queue, ^{});
192 void output_block(dispatch_block_t * blk) {
193   int x = 0;
194   *blk = ^{ f(x); };
197 // Block objects themselves can never leak under ARC.
198 void test_no_block_leak() {
199   __block dispatch_block_t blk;
200   int x = 0;
201   dispatch_block_t p = ^{
202     blk = ^{
203       f(x);
204     };
205   };
206   p();
207   blk();
208   output_block(&blk);
209   blk();
212 // Block objects do not leak under ARC but stack variables of
213 // non-object kind indirectly referred by a block can leak.
214 dispatch_block_t test_block_referencing_variable_leak() {
215   int x = 0;
216   __block int * p = &x;
217   __block int * q = &x;
218   
219   dispatch_async(queue, ^{// expected-warning {{Address of stack memory associated with local variable 'x' is captured by an asynchronously-executed block \
220 [alpha.core.StackAddressAsyncEscape]}}
221       ++(*p);
222     });
223   return (dispatch_block_t) ^{// expected-warning {{Address of stack memory associated with local variable 'x' is captured by a returned block \
224 [core.StackAddressEscape]}}
225     ++(*q);
226   };