xref: /llvm-project/clang/test/SemaCXX/blocks.cpp (revision 0f1c1be1968076d6f96f8a7bcc4a15cf195ecd97)
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 namespace radar8382559 {
46   void func(bool& outHasProperty);
47 
test3()48   int test3() {
49     __attribute__((__blocks__(byref))) bool hasProperty = false;
50     bool has = true;
51 
52     bool (^b)() = ^ {
53      func(hasProperty);
54      if (hasProperty)
55        hasProperty = 0;
56      if (has)
57        hasProperty = 1;
58      return hasProperty;
59      };
60     func(hasProperty);
61     func(has);
62     b();
63     if (hasProperty)
64       hasProperty = 1;
65     if (has)
66       has = 2;
67     return hasProperty = 1;
68   }
69 }
70 
71 // Move __block variables to the heap when possible.
72 class MoveOnly {
73 public:
74   MoveOnly();
75   MoveOnly(const MoveOnly&) = delete;
76   MoveOnly(MoveOnly&&);
77 };
78 
move_block()79 void move_block() {
80   __block MoveOnly mo;
81 }
82 
83 // Don't crash after failing to build a block due to a capture of an
84 // invalid declaration.
85 namespace test5 {
86   struct B { // expected-note 2 {{candidate constructor}}
87     void *p;
88     B(int); // expected-note {{candidate constructor}}
89   };
90 
91   void use_block(void (^)());
92   void use_block_2(void (^)(), const B &a);
93 
test()94   void test() {
95     B x; // expected-error {{no matching constructor for initialization}}
96     use_block(^{
97         int y;
98         use_block_2(^{ (void) y; }, x);
99       });
100   }
101 }
102 
103 
104 // Ensure that we can end function bodies while parsing an
105 // expression that requires an explicitly-tracked cleanup object
106 // (i.e. a block literal).
107 
108 // The nested function body in this test case is a template
109 // instantiation.  The template function has to be constexpr because
110 // we'll otherwise delay its instantiation to the end of the
111 // translation unit.
112 namespace test6a {
func()113   template <class T> constexpr int func() { return 0; }
114   void run(void (^)(), int);
115 
test()116   void test() {
117     int aCapturedVar = 0;
118     run(^{ (void) aCapturedVar; }, func<int>());
119   }
120 }
121 
122 // The nested function body in this test case is a method of a local
123 // class.
124 namespace test6b {
125   void run(void (^)(), void (^)());
test()126   void test() {
127     int aCapturedVar = 0;
128     run(^{ (void) aCapturedVar; },
129         ^{ struct A { static void foo() {} };
130             A::foo(); });
131   }
132 }
133 
134 // The nested function body in this test case is a lambda invocation
135 // function.
136 namespace test6c {
137   void run(void (^)(), void (^)());
test()138   void test() {
139     int aCapturedVar = 0;
140     run(^{ (void) aCapturedVar; },
141         ^{ struct A { static void foo() {} };
142             A::foo(); });
143   }
144 }
145 
146 namespace test7 {
147 struct S {};
f()148 void f() {
149   constexpr S s;
150   auto some_block = ^{ (void)s; };
151 }
152 }
153 
static_data_member()154 void static_data_member() {
155   auto block = ^{
156     class X {
157       static int x; // expected-error {{static data member 'x' not allowed in local class 'X'}}
158     };
159     class Y {
160       struct Z {
161         static int z; // expected-error {{static data member 'z' not allowed in local struct 'Z'}}
162       };
163     };
164   };
165 }
166