1// RUN: %clang_cc1 -triple i686-pc-linux -std=c++11 -fblocks %s -verify
2
3void block_capture_errors() {
4  __block int var; // expected-note 2{{'var' declared here}}
5  (void)[var] { }; // expected-error{{__block variable 'var' cannot be captured in a lambda}}
6
7  (void)[=] { var = 17; }; // expected-error{{__block variable 'var' cannot be captured in a lambda}}
8}
9
10void conversion_to_block(int captured) {
11  int (^b1)(int) = [=](int x) { return x + captured; };
12
13  const auto lambda = [=](int x) { return x + captured; };
14  int (^b2)(int) = lambda;
15}
16
17template<typename T>
18class ConstCopyConstructorBoom {
19public:
20  ConstCopyConstructorBoom(ConstCopyConstructorBoom&);
21
22  ConstCopyConstructorBoom(const ConstCopyConstructorBoom&) {
23    T *ptr = 1; // expected-error{{cannot initialize a variable of type 'float *' with an rvalue of type 'int'}}
24  }
25
26  void foo() const;
27};
28
29void conversion_to_block_init(ConstCopyConstructorBoom<int> boom,
30                              ConstCopyConstructorBoom<float> boom2) {
31  const auto& lambda1([=] { boom.foo(); }); // okay
32
33  const auto& lambda2([=] { boom2.foo(); }); // expected-note{{in instantiation of member function}}
34  void (^block)(void) = lambda2;
35}
36
37
38void nesting() {
39  int array[7]; // expected-note 2{{'array' declared here}}
40  [=] () mutable {
41    [&] {
42      ^ {
43        int i = array[2];
44        i += array[3];
45      }();
46    }();
47  }();
48
49  [&] {
50    [=] () mutable {
51      ^ {
52        int i = array[2]; // expected-error{{cannot refer to declaration with an array type inside block}}
53        i += array[3];
54      }();
55    }();
56
57    [=] () mutable {
58      ^ {
59        int i = 0;
60        i += array[3]; // expected-error{{cannot refer to declaration with an array type inside block}}
61      }();
62    }();
63  }();
64}
65
66namespace overloading {
67  void bool_conversion() {
68    if ([](){}) {
69    }
70
71    bool b = []{};
72    b = (bool)[]{};
73  }
74
75  void conversions() {
76    int (*fp)(int) = [](int x) { return x + 1; };
77    fp = [](int x) { return x + 1; };
78
79    typedef int (*func_ptr)(int);
80    fp = (func_ptr)[](int x) { return x + 1; };
81
82    int (^bp)(int) = [](int x) { return x + 1; };
83    bp = [](int x) { return x + 1; };
84
85    typedef int (^block_ptr)(int);
86    bp = (block_ptr)[](int x) { return x + 1; };
87  }
88
89  int &accept_lambda_conv(int (*fp)(int));
90  float &accept_lambda_conv(int (^bp)(int));
91
92  void call_with_lambda() {
93    int &ir = accept_lambda_conv([](int x) { return x + 1; });
94  }
95
96  template<typename T> using id = T;
97
98  auto a = [](){};
99  struct C : decltype(a) {
100    using decltype(a)::operator id<void(*)()>;
101  private:
102    using decltype(a)::operator id<void(^)()>;
103  } extern c;
104
105  struct D : decltype(a) {
106    using decltype(a)::operator id<void(^)()>;
107  private:
108    using decltype(a)::operator id<void(*)()>; // expected-note {{here}}
109  } extern d;
110
111  bool r1 = c;
112  bool r2 = d; // expected-error {{private}}
113}
114
115namespace PR13117 {
116  struct A {
117    template<typename ... Args> static void f(Args...);
118
119    template<typename ... Args> static void f1()
120    {
121      (void)^(Args args) { // expected-error{{block contains unexpanded parameter pack 'Args'}}
122      };
123    }
124
125    template<typename ... Args> static void f2()
126    {
127      // FIXME: Allow this.
128      f(
129        ^(Args args) // expected-error{{block contains unexpanded parameter pack 'Args'}}
130        { }
131        ... // expected-error{{pack expansion does not contain any unexpanded parameter packs}}
132      );
133    }
134
135    template<typename ... Args> static void f3()
136    {
137      (void)[](Args args) { // expected-error{{expression contains unexpanded parameter pack 'Args'}}
138      };
139    }
140
141    template<typename ... Args> static void f4()
142    {
143      f([](Args args) { } ...);
144    }
145  };
146
147  void g() {
148    A::f1<int, int>();
149    A::f2<int, int>();
150  }
151}
152