summaryrefslogtreecommitdiffstats
path: root/test/CXX/expr/expr.prim/expr.prim.lambda/blocks.mm
blob: 0db2bf5646ff4568e3e8f71f9b068f763e27e699 (plain)
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
// RUN: %clang_cc1 -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; });
  }
}

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>();
  }
}
OpenPOWER on IntegriCloud