228 lines · plain
1// RUN: %clang_analyze_cc1 -triple x86_64-apple-darwin10 -analyzer-checker=core,alpha.core.StackAddressAsyncEscape -fblocks -fobjc-arc -verify %s2 3typedef struct dispatch_queue_s *dispatch_queue_t;4typedef void (^dispatch_block_t)(void);5void dispatch_async(dispatch_queue_t queue, dispatch_block_t block);6typedef long dispatch_once_t;7void dispatch_once(dispatch_once_t *predicate, dispatch_block_t block);8typedef long dispatch_time_t;9void dispatch_after(dispatch_time_t when, dispatch_queue_t queue, dispatch_block_t block);10void dispatch_barrier_sync(dispatch_queue_t queue, dispatch_block_t block);11void f(int);12 13extern dispatch_queue_t queue;14extern dispatch_once_t *predicate;15extern dispatch_time_t when;16 17void test_block_expr_async() {18 int x = 123;19 int *p = &x;20 21 dispatch_async(queue, ^{22 *p = 321;23 });24 // expected-warning@-3 {{Address of stack memory associated with local variable 'x' \25is captured by an asynchronously-executed block}}26}27 28void test_block_expr_once_no_leak() {29 int x = 123;30 int *p = &x;31 // synchronous, no warning32 dispatch_once(predicate, ^{33 *p = 321;34 });35}36 37void 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' \44is captured by an asynchronously-executed block}}45}46 47void test_block_expr_async_no_leak() {48 int x = 123;49 int *p = &x;50 // no leak51 dispatch_async(queue, ^{52 int y = x;53 ++y;54 });55}56 57void 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' \65is captured by an asynchronously-executed block}}66}67 68void 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' \76is captured by an asynchronously-executed block}}77}78 79dispatch_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' \86is captured by a returned block}}87}88 89void 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' \92is captured by an asynchronously-executed block}}93}94 95// synchronous, no leak96void 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-warning103}104 105void 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' \113is captured by an asynchronously-executed block}}114}115 116void 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-warning124}125 126void 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-warning139}140 141dispatch_block_t accept_and_pass_back_block(dispatch_block_t block) {142 block();143 return block; // no-warning144}145 146void 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-warning153}154 155@interface NSObject156@end157@protocol OS_dispatch_semaphore158@end159typedef NSObject<OS_dispatch_semaphore> *dispatch_semaphore_t;160dispatch_semaphore_t dispatch_semaphore_create(long value);161long dispatch_semaphore_wait(dispatch_semaphore_t dsema, dispatch_time_t timeout);162long dispatch_semaphore_signal(dispatch_semaphore_t dsema);163 164void 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-warning173 174 // Do some other work concurrently with the asynchronous work175 // Wait for the asynchronous work to finish176 dispatch_semaphore_wait(semaphore, 1000);177}178 179void 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 ensures184 // 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, ^{});190}191 192void output_block(dispatch_block_t * blk) {193 int x = 0;194 *blk = ^{ f(x); };195}196 197// Block objects themselves can never leak under ARC.198void 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();210}211 212// Block objects do not leak under ARC but stack variables of213// non-object kind indirectly referred by a block can leak.214dispatch_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 };227}228