| Richard Smith | ba71c08 | 2013-05-16 06:20:58 +0000 | [diff] [blame^] | 1 | // RUN: %clang_cc1 -std=c++1y %s -verify |
| 2 | |
| 3 | // For every init-capture a non-static data member named by the identifier of |
| 4 | // the init-capture is declared in the closure type. |
| 5 | const char *has_member_x = [x("hello")] {}.x; |
| 6 | // This member is not a bit-field... |
| 7 | auto capturing_lambda = [n(0)] {}; |
| 8 | int decltype(capturing_lambda)::*mem_ptr = &decltype(capturing_lambda)::n; |
| 9 | // ... and not mutable. |
| 10 | const auto capturing_lambda_copy = capturing_lambda; |
| 11 | int &n = capturing_lambda_copy.n; // expected-error {{drops qualifiers}} |
| 12 | |
| 13 | // The type of that member [...is that of a...] variable declaration of the form |
| 14 | // "auto init-capture ;"... |
| 15 | auto with_float = [f(1.0f)] {}; |
| 16 | float &f = with_float.f; |
| 17 | // ... except that the variable name is replaced by a unique identifier. |
| 18 | auto with_float_2 = [&f(f)] {}; // ok, refers to outer f |
| 19 | float &f2 = with_float_2.f; |
| 20 | |
| 21 | // Within the lambda-expression's lambda-declarator (FIXME) and |
| 22 | // compound-statement, the identifier in the init-capture hides any declaration |
| 23 | // of the same name in scopes enclosing the lambda-expression. |
| 24 | void hiding() { |
| 25 | char c; |
| 26 | (void) [c("foo")] { |
| 27 | static_assert(sizeof(c) == sizeof(const char*), ""); |
| 28 | }; |
| 29 | (void) [c("bar")] () -> decltype(c) { |
| 30 | // FIXME: the 'c' in the return type should be the init-capture, not the |
| 31 | // outer c. |
| 32 | return "baz"; // expected-error {{cannot initialize}} |
| 33 | }; |
| 34 | } |
| 35 | |
| 36 | struct ExplicitCopy { |
| 37 | ExplicitCopy(); // expected-note 2{{not viable}} |
| 38 | explicit ExplicitCopy(const ExplicitCopy&); |
| 39 | }; |
| 40 | auto init_kind_1 = [ec(ExplicitCopy())] {}; |
| 41 | auto init_kind_2 = [ec = ExplicitCopy()] {}; // expected-error {{no matching constructor}} |
| 42 | |
| 43 | template<typename T> void init_kind_template() { |
| 44 | auto init_kind_1 = [ec(T())] {}; |
| 45 | auto init_kind_2 = [ec = T()] {}; // expected-error {{no matching constructor}} |
| 46 | } |
| 47 | template void init_kind_template<int>(); |
| 48 | template void init_kind_template<ExplicitCopy>(); // expected-note {{instantiation of}} |
| 49 | |
| 50 | void void_fn(); |
| 51 | int overload_fn(); |
| 52 | int overload_fn(int); |
| 53 | |
| 54 | auto bad_init_1 = [a()] {}; // expected-error {{expected expression}} |
| 55 | auto bad_init_2 = [a(1, 2)] {}; // expected-error {{initializer for lambda capture 'a' contains multiple expressions}} |
| 56 | auto bad_init_3 = [&a(void_fn())] {}; // expected-error {{cannot form a reference to 'void'}} |
| 57 | auto bad_init_4 = [a(void_fn())] {}; // expected-error {{field has incomplete type 'void'}} |
| 58 | auto bad_init_5 = [a(overload_fn)] {}; // expected-error {{cannot deduce type for lambda capture 'a' from initializer of type '<overloaded function}} |
| 59 | auto bad_init_6 = [a{overload_fn}] {}; // expected-error {{cannot deduce type for lambda capture 'a' from initializer list}} |
| 60 | |
| 61 | template<typename...T> void pack_1(T...t) { [a(t...)] {}; } // expected-error {{initializer missing for lambda capture 'a'}} |
| 62 | template void pack_1<>(); // expected-note {{instantiation of}} |
| 63 | |
| 64 | auto multi_return(int a, int b) { |
| 65 | return [n(a + 2*b), m(a - 2*b)] {}; |
| 66 | } |
| 67 | auto use_multi_return() { |
| 68 | auto nm = multi_return(5, 9); |
| 69 | return nm.n + nm.m; |
| 70 | } |
| 71 | |
| 72 | auto a = [a(4), b = 5, &c = static_cast<const int&&>(0)] { |
| 73 | static_assert(sizeof(a) == sizeof(int), ""); |
| 74 | static_assert(sizeof(b) == sizeof(int), ""); |
| 75 | using T = decltype(c); |
| 76 | using T = const int &; |
| 77 | }; |
| 78 | auto b = [a{0}] {}; // expected-error {{include <initializer_list>}} |
| 79 | |
| 80 | struct S { S(); S(S&&); }; |
| 81 | template<typename T> struct remove_reference { typedef T type; }; |
| 82 | template<typename T> struct remove_reference<T&> { typedef T type; }; |
| 83 | template<typename T> decltype(auto) move(T &&t) { return static_cast<typename remove_reference<T>::type&&>(t); } |
| 84 | auto s = [s(move(S()))] {}; |