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