Clang Project

clang_source_code/test/SemaObjCXX/blocks.mm
1// RUN: %clang_cc1 -fsyntax-only -verify -fblocks -Wno-objc-root-class -std=c++14 %s
2@protocol NSObject;
3
4void bar(id(^)(void));
5void foo(id <NSObject>(^objectCreationBlock)(void)) {
6    return bar(objectCreationBlock); // OK
7}
8
9void bar2(id(*)(void));
10void foo2(id <NSObject>(*objectCreationBlock)(void)) {
11    return bar2(objectCreationBlock); // expected-warning{{incompatible pointer types passing 'id<NSObject> (*)()' to parameter of type 'id (*)()'}}
12}
13
14void bar3(id(*)()); // expected-note{{candidate function}}
15void foo3(id (*objectCreationBlock)(int)) {
16    return bar3(objectCreationBlock); // expected-error{{no matching}}
17}
18
19void bar4(id(^)()); // expected-note{{candidate function}}
20void foo4(id (^objectCreationBlock)(int)) {
21    return bar4(objectCreationBlock); // expected-error{{no matching}}
22}
23
24void foo5(id (^x)(int)) {
25  if (x) { }
26}
27
28// <rdar://problem/6590445>
29@interface Foo {
30    @private
31    void (^_block)(void);
32}
33- (void)bar;
34@end
35
36namespace N {
37  class X { };      
38  void foo(X);
39}
40
41@implementation Foo
42- (void)bar {
43    _block();
44    foo(N::X()); // okay
45}
46@end
47
48typedef signed char BOOL;
49void foo6(void *block) {  
50 void (^vb)(id obj, int idx, BOOL *stop) = (void (^)(id, int, BOOL *))block;
51    BOOL (^bb)(id obj, int idx, BOOL *stop) = (BOOL (^)(id, int, BOOL *))block;
52}
53
54// <rdar://problem/8600419>: Require that the types of block
55// parameters are complete.
56namespace N1 {
57  template<class _T> class ptr; // expected-note{{template is declared here}}
58
59  template<class _T>
60    class foo {
61  public:
62    void bar(void (^)(ptr<_T>));
63  };
64
65  class X;
66
67  void test2();
68
69  void test()
70  {
71    foo<X> f;
72    f.bar(^(ptr<X> _f) { // expected-error{{implicit instantiation of undefined template 'N1::ptr<N1::X>'}}
73        test2();
74      });
75  }
76}
77
78// Make sure we successfully instantiate the copy constructor of a
79// __block variable's type when the variable is captured by an escaping block.
80namespace N2 {
81  template <int n> struct A {
82    A() {}
83    A(const A &other) {
84      int invalid[-n]; // expected-error 2 {{array with a negative size}}
85    }
86    void m() {}
87  };
88
89  typedef void (^BlockFnTy)();
90  void func(BlockFnTy);
91
92  void test1() {
93    __block A<1> x; // expected-note {{requested here}}
94    func(^{ x.m(); });
95  }
96
97  template <int n> void test2() {
98    __block A<n> x; // expected-note {{requested here}}
99    func(^{ x.m(); });
100  }
101  template void test2<2>();
102}
103
104// Handle value-dependent block declaration references.
105namespace N3 {
106  template<int N> struct X { };
107
108  template<int N>
109  void f() {
110    X<N> xN = ^() { return X<N>(); }();
111  }
112}
113
114// rdar://8979379
115
116@interface A
117@end
118
119@interface B : A
120@end
121
122void f(int (^bl)(A* a)); // expected-note {{candidate function not viable: no known conversion from 'int (^)(B *)' to 'int (^)(A *)' for 1st argument}}
123
124void g() {
125  f(^(B* b) { return 0; }); // expected-error {{no matching function for call to 'f'}}
126}
127
128namespace DependentReturn {
129  template<typename T>
130  void f(T t) {
131    (void)^(T u) {
132      if (t != u)
133        return t + u;
134      else
135        return;
136    };
137
138    (void)^(T u) {
139      if (t == u)
140        return;
141      else
142        return t + u;
143    };
144  }
145
146  struct X { };
147  void operator+(X, X);
148  bool operator==(X, X);
149  bool operator!=(X, X);
150
151  template void f<X>(X);
152}
153
154namespace GenericLambdaCapture {
155int test(int outerp) {
156  auto lambda =[&](auto p) {
157    return ^{
158      return p + outerp;
159    }();
160  };
161  return lambda(1);
162}
163}
164
165namespace MoveBlockVariable {
166struct B0 {
167};
168
169struct B1 { // expected-note 2 {{candidate constructor (the implicit}}
170  B1(B0&&); // expected-note {{candidate constructor not viable}}
171};
172
173B1 test_move() {
174  __block B0 b;
175  return b; // expected-error {{no viable conversion from returned value of type 'MoveBlockVariable::B0' to function return type 'MoveBlockVariable::B1'}}
176}
177}
178