aboutsummaryrefslogtreecommitdiff
path: root/test/CXX/expr/expr.prim/expr.prim.lambda/blocks.mm
blob: 96e8fcd8d37179bf43afcaf4f8cc2b16d2bbba46 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
// RUN: %clang_cc1 -triple i686-pc-linux -std=c++11 -fblocks %s -verify

void block_capture_errors() {
  __block int var; // expected-note 2{{'var' declared here}}
  (void)[var] { }; // expected-error{{__block variable 'var' cannot be captured in a lambda}}

  (void)[=] { var = 17; }; // expected-error{{__block variable 'var' cannot be captured in a lambda}}
}

void conversion_to_block(int captured) {
  int (^b1)(int) = [=](int x) { return x + captured; };

  const auto lambda = [=](int x) { return x + captured; };
  int (^b2)(int) = lambda;
}

template<typename T>
class ConstCopyConstructorBoom {
public:
  ConstCopyConstructorBoom(ConstCopyConstructorBoom&);

  ConstCopyConstructorBoom(const ConstCopyConstructorBoom&) {
    T *ptr = 1; // expected-error{{cannot initialize a variable of type 'float *' with an rvalue of type 'int'}}
  }

  void foo() const;
};

void conversion_to_block_init(ConstCopyConstructorBoom<int> boom,
                              ConstCopyConstructorBoom<float> boom2) {
  const auto& lambda1([=] { boom.foo(); }); // okay

  const auto& lambda2([=] { boom2.foo(); }); // expected-note{{in instantiation of member function}}
  void (^block)(void) = lambda2;
}


void nesting() {
  int array[7]; // expected-note 2{{'array' declared here}}
  [=] () mutable {
    [&] {
      ^ {
        int i = array[2];
        i += array[3];
      }();
    }();
  }();

  [&] {
    [=] () mutable {
      ^ {
        int i = array[2]; // expected-error{{cannot refer to declaration with an array type inside block}}
        i += array[3]; // expected-error{{cannot refer to declaration with an array type inside block}}
      }();
    }();
  }();
}

namespace overloading {
  void bool_conversion() {
    if ([](){}) {
    }

    bool b = []{};
    b = (bool)[]{};
  }

  void conversions() {
    int (*fp)(int) = [](int x) { return x + 1; };
    fp = [](int x) { return x + 1; };

    typedef int (*func_ptr)(int);
    fp = (func_ptr)[](int x) { return x + 1; };

    int (^bp)(int) = [](int x) { return x + 1; };
    bp = [](int x) { return x + 1; };

    typedef int (^block_ptr)(int);
    bp = (block_ptr)[](int x) { return x + 1; };
  }

  int &accept_lambda_conv(int (*fp)(int));
  float &accept_lambda_conv(int (^bp)(int));

  void call_with_lambda() {
    int &ir = accept_lambda_conv([](int x) { return x + 1; });
  }

  template<typename T> using id = T;

  auto a = [](){};
  struct C : decltype(a) {
    using decltype(a)::operator id<void(*)()>;
  private:
    using decltype(a)::operator id<void(^)()>;
  } extern c;

  struct D : decltype(a) {
    using decltype(a)::operator id<void(^)()>;
  private:
    using decltype(a)::operator id<void(*)()>; // expected-note {{here}}
  } extern d;

  bool r1 = c;
  bool r2 = d; // expected-error {{private}}
}

namespace PR13117 {
  struct A {
    template<typename ... Args> static void f(Args...);

    template<typename ... Args> static void f1()
    {
      (void)^(Args args) { // expected-error{{block contains unexpanded parameter pack 'Args'}}
      };
    }

    template<typename ... Args> static void f2()
    {
      // FIXME: Allow this.
      f(
        ^(Args args) // expected-error{{block contains unexpanded parameter pack 'Args'}}
        { }
        ... // expected-error{{pack expansion does not contain any unexpanded parameter packs}}
      );
    }

    template<typename ... Args> static void f3()
    {
      (void)[](Args args) { // expected-error{{expression contains unexpanded parameter pack 'Args'}}
      };
    }

    template<typename ... Args> static void f4()
    {
      f([](Args args) { } ...);
    }
  };

  void g() {
    A::f1<int, int>();
    A::f2<int, int>();
  }
}