p11-1y.cpp revision d6b698739ab157348acafcec5b06a05d3d35377d
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.
5const char *has_member_x = [x("hello")] {}.x;
6// This member is not a bit-field...
7auto capturing_lambda = [n(0)] {};
8int decltype(capturing_lambda)::*mem_ptr = &decltype(capturing_lambda)::n;
9// ... and not mutable.
10const auto capturing_lambda_copy = capturing_lambda;
11int &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 ;"...
15auto with_float = [f(1.0f)] {};
16float &f = with_float.f;
17// ... except that the variable name is replaced by a unique identifier.
18auto with_float_2 = [&f(f)] {}; // ok, refers to outer f
19float &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.
24void 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
36struct ExplicitCopy {
37  ExplicitCopy(); // expected-note 2{{not viable}}
38  explicit ExplicitCopy(const ExplicitCopy&);
39};
40auto init_kind_1 = [ec(ExplicitCopy())] {};
41auto init_kind_2 = [ec = ExplicitCopy()] {}; // expected-error {{no matching constructor}}
42
43template<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}
47template void init_kind_template<int>();
48template void init_kind_template<ExplicitCopy>(); // expected-note {{instantiation of}}
49
50void void_fn();
51int overload_fn();
52int overload_fn(int);
53
54auto bad_init_1 = [a()] {}; // expected-error {{expected expression}}
55auto bad_init_2 = [a(1, 2)] {}; // expected-error {{initializer for lambda capture 'a' contains multiple expressions}}
56auto bad_init_3 = [&a(void_fn())] {}; // expected-error {{cannot form a reference to 'void'}}
57auto bad_init_4 = [a(void_fn())] {}; // expected-error {{field has incomplete type 'void'}}
58auto bad_init_5 = [a(overload_fn)] {}; // expected-error {{cannot deduce type for lambda capture 'a' from initializer of type '<overloaded function}}
59auto bad_init_6 = [a{overload_fn}] {}; // expected-error {{cannot deduce type for lambda capture 'a' from initializer list}}
60
61template<typename...T> void pack_1(T...t) { [a(t...)] {}; } // expected-error {{initializer missing for lambda capture 'a'}}
62template void pack_1<>(); // expected-note {{instantiation of}}
63
64auto multi_return(int a, int b) {
65  return [n(a + 2*b), m(a - 2*b)] {};
66}
67auto use_multi_return() {
68  auto nm = multi_return(5, 9);
69  return nm.n + nm.m;
70}
71
72auto a = [a(4), b = 5, &c = static_cast<const int&&>(0)] { // expected-warning {{binding reference member 'c' to a temporary value}} expected-note {{here}}
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};
78auto b = [a{0}] {}; // expected-error {{include <initializer_list>}}
79
80struct S { S(); S(S&&); };
81template<typename T> struct remove_reference { typedef T type; };
82template<typename T> struct remove_reference<T&> { typedef T type; };
83template<typename T> decltype(auto) move(T &&t) { return static_cast<typename remove_reference<T>::type&&>(t); }
84auto s = [s(move(S()))] {};
85