1// RUN: %clang_analyze_cc1 -triple x86_64-apple-darwin10 -analyzer-checker=core,alpha.core.StackAddressAsyncEscape -fblocks -verify %s
2
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);
6extern dispatch_queue_t queue;
7
8void test_block_inside_block_async_no_leak() {
9  int x = 123;
10  int *p = &x;
11  void (^inner)(void) = ^void(void) {
12    int y = x;
13    ++y;
14  };
15  // Block_copy(...) copies the captured block ("inner") too,
16  // there is no leak in this case.
17  dispatch_async(queue, ^void(void) {
18    int z = x;
19    ++z;
20    inner();
21  }); // no-warning
22}
23
24dispatch_block_t test_block_inside_block_async_leak() {
25  int x = 123;
26  void (^inner)(void) = ^void(void) {
27    int y = x;
28    ++y;
29  };
30  void (^outer)(void) = ^void(void) {
31    int z = x;
32    ++z;
33    inner();
34  };
35  return outer; // expected-warning-re{{Address of stack-allocated block declared on line {{.+}} is captured by a returned block}}
36}
37
38