1// RUN: %clang_cc1 -fsyntax-only -verify -std=c++11 %s -fblocks
2
3void test_nest_lambda() {
4  int x;
5  int y;
6  [&,y]() {
7    int z;
8    #pragma clang __debug captured
9    {
10      x = y; // OK
11      y = z; // expected-error{{cannot assign to a variable captured by copy in a non-mutable lambda}}
12      z = y; // OK
13    }
14  }();
15
16  int a;
17  #pragma clang __debug captured
18  {
19    int b;
20    int c;
21    [&,c]() {
22      a = b; // OK
23      b = c; // OK
24      c = a; // expected-error{{cannot assign to a variable captured by copy in a non-mutable lambda}}
25    }();
26  }
27}
28
29class test_obj_capture {
30  int a;
31  void b();
32  static void test() {
33    test_obj_capture c;
34    #pragma clang __debug captured
35    { (void)c.a; }  // OK
36    #pragma clang __debug captured
37    { c.b(); }      // OK
38  }
39};
40
41class test_this_capture {
42  int a;
43  void b();
44  void test() {
45    #pragma clang __debug captured
46    { (void)this; } // OK
47    #pragma clang __debug captured
48    { (void)a; }    // OK
49    #pragma clang __debug captured
50    { b(); }        // OK
51  }
52};
53
54template <typename T>
55void template_capture_var() {
56  T x; // expected-error{{declaration of reference variable 'x' requires an initializer}}
57  #pragma clang _debug captured
58  {
59    (void)x;
60  }
61}
62
63template <typename T>
64class Val {
65  T v;
66public:
67  void set(const T &v0) {
68    #pragma clang __debug captured
69    {
70      v = v0;
71    }
72  }
73};
74
75void test_capture_var() {
76  template_capture_var<int>(); // OK
77  template_capture_var<int&>(); // expected-note{{in instantiation of function template specialization 'template_capture_var<int &>' requested here}}
78
79  Val<float> Obj;
80  Obj.set(0.0f); // OK
81}
82
83template <typename S, typename T>
84S template_capture_var(S x, T y) {
85  #pragma clang _debug captured
86  {
87    x++;
88    y++;  // expected-error{{read-only variable is not assignable}}
89  }
90
91  return x;
92}
93
94// Check if can recover from a template error.
95void test_capture_var_error() {
96  template_capture_var<int, int>(0, 1); // OK
97  template_capture_var<int, const int>(0, 1); // expected-note{{in instantiation of function template specialization 'template_capture_var<int, const int>' requested here}}
98  template_capture_var<int, int>(0, 1); // OK
99}
100
101template <typename T>
102void template_capture_in_lambda() {
103  T x, y;
104  [=, &y]() {
105    #pragma clang __debug captured
106    {
107      y += x;
108    }
109  }();
110}
111
112void test_lambda() {
113  template_capture_in_lambda<int>(); // OK
114}
115
116struct Foo {
117  void foo() { }
118  static void bar() { }
119};
120
121template <typename T>
122void template_capture_func(T &t) {
123  #pragma clang __debug captured
124  {
125    t.foo();
126  }
127
128  #pragma clang __debug captured
129  {
130    T::bar();
131  }
132}
133
134void test_template_capture_func() {
135  Foo Obj;
136  template_capture_func(Obj);
137}
138
139template <typename T>
140T captured_sum(const T &a, const T &b) {
141  T result;
142
143  #pragma clang __debug captured
144  {
145    result = a + b;
146  }
147
148  return result;
149}
150
151template <typename T, typename... Args>
152T captured_sum(const T &a, const Args&... args) {
153  T result;
154
155  #pragma clang __debug captured
156  {
157    result = a + captured_sum(args...);
158  }
159
160  return result;
161}
162
163void test_capture_variadic() {
164  (void)captured_sum(1, 2, 3); // OK
165  (void)captured_sum(1, 2, 3, 4, 5); // OK
166}
167
168void test_capture_with_attributes() {
169  [[]] // expected-error {{an attribute list cannot appear here}}
170  #pragma clang __debug captured
171  {
172  }
173}
174