1// RUN: %clang_cc1 -std=c++1z -verify -fsyntax-only -fblocks -emit-llvm-only %s
2// RUN: %clang_cc1 -std=c++1z -verify -fsyntax-only -fblocks -fdelayed-template-parsing %s -DDELAYED_TEMPLATE_PARSING
3// RUN: %clang_cc1 -std=c++1z -verify -fsyntax-only -fblocks -fms-extensions %s -DMS_EXTENSIONS
4// RUN: %clang_cc1 -std=c++1z -verify -fsyntax-only -fblocks -fdelayed-template-parsing -fms-extensions %s -DMS_EXTENSIONS -DDELAYED_TEMPLATE_PARSING
5
6template<class, class> constexpr bool is_same = false;
7template<class T> constexpr bool is_same<T, T> = true;
8
9namespace test_star_this {
10namespace ns1 {
11class A {
12  int x = 345;
13  auto foo() {
14    (void) [*this, this] { };  //expected-error{{'this' can appear only once}}
15    (void) [this] { ++x; };
16    (void) [*this] { ++x; };  //expected-error{{read-only variable}}
17    (void) [*this] () mutable { ++x; };
18    (void) [=] { return x; };
19    (void) [&, this] { return x; };
20    (void) [=, *this] { return x; };
21    (void) [&, *this] { return x; };
22  }
23};
24} // end ns1
25
26namespace ns2 {
27  class B {
28    B(const B&) = delete; //expected-note{{deleted here}}
29    int *x = (int *) 456;
30    void foo() {
31      (void)[this] { return x; };
32      (void)[*this] { return x; }; //expected-error{{call to deleted}}
33    }
34  };
35} // end ns2
36namespace ns3 {
37  class B {
38    B(const B&) = delete; //expected-note2{{deleted here}}
39
40    int *x = (int *) 456;
41    public:
42    template<class T = int>
43    void foo() {
44      (void)[this] { return x; };
45      (void)[*this] { return x; }; //expected-error2{{call to deleted}}
46    }
47
48    B() = default;
49  } b;
50  B *c = (b.foo(), nullptr); //expected-note{{in instantiation}}
51} // end ns3
52
53namespace ns4 {
54template<class U>
55class B {
56  B(const B&) = delete; //expected-note{{deleted here}}
57  double d = 3.14;
58  public:
59  template<class T = int>
60  auto foo() {
61    const auto &L = [*this] (auto a) mutable { //expected-error{{call to deleted}}
62      d += a;
63      return [this] (auto b) { return d +=b; };
64    };
65  }
66
67  B() = default;
68};
69void main() {
70  B<int*> b;
71  b.foo(); //expected-note{{in instantiation}}
72} // end main
73} // end ns4
74namespace ns5 {
75
76struct X {
77  double d = 3.14;
78  X(const volatile X&);
79  void foo() {
80
81  }
82
83  void foo() const { //expected-note{{const}}
84
85    auto L = [*this] () mutable {
86      static_assert(is_same<decltype(this), X*>);
87      ++d;
88      auto M = [this] {
89        static_assert(is_same<decltype(this), X*>);
90        ++d;
91        auto N = [] {
92          static_assert(is_same<decltype(this), X*>);
93        };
94      };
95    };
96
97    auto L1 = [*this] {
98      static_assert(is_same<decltype(this), const X*>);
99      auto M = [this] () mutable {
100        static_assert(is_same<decltype(this), const X*>);
101        auto N = [] {
102          static_assert(is_same<decltype(this), const X*>);
103        };
104      };
105      auto M2 = [*this] () mutable {
106        static_assert(is_same<decltype(this), X*>);
107        auto N = [] {
108          static_assert(is_same<decltype(this), X*>);
109        };
110      };
111    };
112
113    auto GL1 = [*this] (auto a) {
114      static_assert(is_same<decltype(this), const X*>);
115      auto M = [this] (auto b) mutable {
116        static_assert(is_same<decltype(this), const X*>);
117        auto N = [] (auto c) {
118          static_assert(is_same<decltype(this), const X*>);
119        };
120        return N;
121      };
122
123      auto M2 = [*this] (auto a) mutable {
124        static_assert(is_same<decltype(this), X*>);
125        auto N = [] (auto b) {
126          static_assert(is_same<decltype(this), X*>);
127        };
128        return N;
129      };
130      return [=](auto a) mutable { M(a)(a); M2(a)(a); };
131    };
132
133    GL1("abc")("abc");
134
135
136    auto L2 = [this] () mutable {
137      static_assert(is_same<decltype(this), const X*>);
138      ++d; //expected-error{{cannot assign}}
139    };
140    auto GL = [*this] (auto a) mutable {
141      static_assert(is_same<decltype(this), X*>);
142      ++d;
143      auto M = [this] (auto b) {
144        static_assert(is_same<decltype(this), X*>);
145        ++d;
146        auto N = [] (auto c) {
147          static_assert(is_same<decltype(this), X*>);
148        };
149        N(3.14);
150      };
151      M("abc");
152    };
153    GL(3.14);
154
155  }
156  void foo() volatile const {
157    auto L = [this] () {
158      static_assert(is_same<decltype(this), const volatile X*>);
159      auto M = [*this] () mutable {
160        static_assert(is_same<decltype(this), X*>);
161        auto N = [this] {
162          static_assert(is_same<decltype(this), X*>);
163          auto M = [] {
164            static_assert(is_same<decltype(this), X*>);
165          };
166        };
167        auto N2 = [*this] {
168          static_assert(is_same<decltype(this), const X*>);
169        };
170      };
171      auto M2 = [*this] () {
172        static_assert(is_same<decltype(this), const X*>);
173        auto N = [this] {
174          static_assert(is_same<decltype(this), const X*>);
175        };
176      };
177    };
178  }
179
180};
181
182} //end ns5
183namespace ns6 {
184struct X {
185  double d;
186  auto foo() const {
187    auto L = [*this] () mutable {
188      auto M = [=] (auto a) {
189        auto N = [this] {
190          ++d;
191          static_assert(is_same<decltype(this), X*>);
192          auto O = [*this] {
193            static_assert(is_same<decltype(this), const X*>);
194          };
195        };
196        N();
197        static_assert(is_same<decltype(this), X*>);
198      };
199      return M;
200    };
201    return L;
202  }
203};
204
205int main() {
206  auto L = X{}.foo();
207  auto M = L();
208  M(3.14);
209}
210} // end ns6
211namespace ns7 {
212
213struct X {
214  double d;
215  X();
216  X(const X&);
217  X(X&) = delete;
218  auto foo() const {
219    //OK - the object used to initialize our capture is a const object and so prefers the non-deleted ctor.
220    const auto &&L = [*this] { };
221  }
222
223};
224int main() {
225  X x;
226  x.foo();
227}
228} // end ns7
229
230} //end ns test_star_this
231
232