1 // RUN: %clang_cc1 -std=c++11 -fsyntax-only -verify %s -fblocks
2 
3 void tovoid(void*);
4 
5 void tovoid_test(int (^f)(int, int)) {
6   tovoid(f);
7 }
8 
9 void reference_lvalue_test(int& (^f)()) {
10   f() = 10;
11 }
12 
13 // PR 7165
14 namespace test1 {
15   void g(void (^)());
16   struct Foo {
17     void foo();
testtest1::Foo18     void test() {
19       (void) ^{ foo(); };
20     }
21   };
22 }
23 
24 namespace test2 {
25   int repeat(int value, int (^block)(int), unsigned n) {
26     while (n--) value = block(value);
27     return value;
28   }
29 
30   class Power {
31     int base;
32 
33   public:
Power(int base)34     Power(int base) : base(base) {}
calculate(unsigned n)35     int calculate(unsigned n) {
36       return repeat(1, ^(int v) { return v * base; }, n);
37     }
38   };
39 
test()40   int test() {
41     return Power(2).calculate(10);
42   }
43 }
44 
45 // rdar: // 8382559
46 namespace radar8382559 {
47   void func(bool& outHasProperty);
48 
test3()49   int test3() {
50     __attribute__((__blocks__(byref))) bool hasProperty = false;
51     bool has = true;
52 
53     bool (^b)() = ^ {
54      func(hasProperty);
55      if (hasProperty)
56        hasProperty = 0;
57      if (has)
58        hasProperty = 1;
59      return hasProperty;
60      };
61     func(hasProperty);
62     func(has);
63     b();
64     if (hasProperty)
65       hasProperty = 1;
66     if (has)
67       has = 2;
68     return hasProperty = 1;
69   }
70 }
71 
72 // Move __block variables to the heap when possible.
73 class MoveOnly {
74 public:
75   MoveOnly();
76   MoveOnly(const MoveOnly&) = delete;
77   MoveOnly(MoveOnly&&);
78 };
79 
move_block()80 void move_block() {
81   __block MoveOnly mo;
82 }
83 
84 // Don't crash after failing to build a block due to a capture of an
85 // invalid declaration.
86 namespace test5 {
87   struct B { // expected-note 2 {{candidate constructor}}
88     void *p;
89     B(int); // expected-note {{candidate constructor}}
90   };
91 
92   void use_block(void (^)());
93   void use_block_2(void (^)(), const B &a);
94 
test()95   void test() {
96     B x; // expected-error {{no matching constructor for initialization}}
97     use_block(^{
98         int y;
99         use_block_2(^{ (void) y; }, x);
100       });
101   }
102 }
103 
104 
105 // rdar://16356628
106 //
107 // Ensure that we can end function bodies while parsing an
108 // expression that requires an explicitly-tracked cleanup object
109 // (i.e. a block literal).
110 
111 // The nested function body in this test case is a template
112 // instantiation.  The template function has to be constexpr because
113 // we'll otherwise delay its instantiation to the end of the
114 // translation unit.
115 namespace test6a {
func()116   template <class T> constexpr int func() { return 0; }
117   void run(void (^)(), int);
118 
test()119   void test() {
120     int aCapturedVar = 0;
121     run(^{ (void) aCapturedVar; }, func<int>());
122   }
123 }
124 
125 // The nested function body in this test case is a method of a local
126 // class.
127 namespace test6b {
128   void run(void (^)(), void (^)());
test()129   void test() {
130     int aCapturedVar = 0;
131     run(^{ (void) aCapturedVar; },
132         ^{ struct A { static void foo() {} };
133             A::foo(); });
134   }
135 }
136 
137 // The nested function body in this test case is a lambda invocation
138 // function.
139 namespace test6c {
140   void run(void (^)(), void (^)());
test()141   void test() {
142     int aCapturedVar = 0;
143     run(^{ (void) aCapturedVar; },
144         ^{ struct A { static void foo() {} };
145             A::foo(); });
146   }
147 }
148 
149 namespace test7 {
150 struct S {};
f()151 void f() {
152   constexpr S s;
153   auto some_block = ^{ (void)s; };
154 }
155 }
156 
static_data_member()157 void static_data_member() {
158   auto block = ^{
159     class X {
160       static int x; // expected-error {{static data member 'x' not allowed in local class 'X'}}
161     };
162     class Y {
163       struct Z {
164         static int z; // expected-error {{static data member 'z' not allowed in local struct 'Z'}}
165       };
166     };
167   };
168 }
169