brintos

brintos / llvm-project-archived public Read only

0
0
Text · 5.8 KiB · 921487a Raw
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