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