1// RUN: %check_clang_tidy -std=c++11-or-later %s bugprone-capturing-this-in-member-variable %t -- -config="{CheckOptions: {bugprone-capturing-this-in-member-variable.FunctionWrapperTypes: '::std::function;::Fn', bugprone-capturing-this-in-member-variable.BindFunctions: '::std::bind;::Bind'}}" --
2
3namespace std {
4
5template<class Fn>
6class function;
7
8template<class R, class ...Args>
9class function<R(Args...)> {
10public:
11 function() noexcept;
12 template<class F> function(F &&);
13};
14
15template <typename F, typename... Args>
16function<F(Args...)> bind(F&&, Args&&...) {
17 return {};
18}
19
20} // namespace std
21
22struct Fn {
23 template<class F> Fn(F &&);
24};
25
26template <typename F, typename... Args>
27std::function<F(Args...)> Bind(F&&, Args&&...) {
28 return {};
29}
30
31struct BasicConstructor {
32 BasicConstructor() : Captured([this]() { static_cast<void>(this); }) {}
33 // CHECK-MESSAGES: :[[@LINE-1]]:33: warning: 'this' captured by a lambda and stored in a class member variable;
34 std::function<void()> Captured;
35 // CHECK-MESSAGES: :[[@LINE-1]]:25: note: class member of type 'std::function<void (void)>' that stores captured 'this'
36};
37
38struct BasicConstructorWithCaptureAllByValue {
39 BasicConstructorWithCaptureAllByValue() : Captured([=]() { static_cast<void>(this); }) {}
40 // CHECK-MESSAGES: :[[@LINE-1]]:54: warning: 'this' captured by a lambda and stored in a class member variable;
41 std::function<void()> Captured;
42 // CHECK-MESSAGES: :[[@LINE-1]]:25: note: class member of type 'std::function<void (void)>' that stores captured 'this'
43};
44
45struct BasicConstructorWithCaptureAllByRef {
46 BasicConstructorWithCaptureAllByRef() : Captured([&]() { static_cast<void>(this); }) {}
47 // CHECK-MESSAGES: :[[@LINE-1]]:52: warning: 'this' captured by a lambda and stored in a class member variable;
48 std::function<void()> Captured;
49 // CHECK-MESSAGES: :[[@LINE-1]]:25: note: class member of type 'std::function<void (void)>' that stores captured 'this'
50};
51
52struct BasicField1 {
53 std::function<void()> Captured = [this]() { static_cast<void>(this); };
54 // CHECK-MESSAGES: :[[@LINE-1]]:36: warning: 'this' captured by a lambda and stored in a class member variable;
55 // CHECK-MESSAGES: :[[@LINE-2]]:25: note: class member of type 'std::function<void (void)>' that stores captured 'this'
56};
57struct BasicField2 {
58 std::function<void()> Captured{[this]() { static_cast<void>(this); }};
59 // CHECK-MESSAGES: :[[@LINE-1]]:34: warning: 'this' captured by a lambda and stored in a class member variable;
60 // CHECK-MESSAGES: :[[@LINE-2]]:25: note: class member of type 'std::function<void (void)>' that stores captured 'this'
61};
62
63struct NotCaptureThis {
64 NotCaptureThis(int V) : Captured([V]() { static_cast<void>(V); }) {}
65 std::function<void()> Captured;
66};
67
68struct AssignCapture {
69 AssignCapture() : Captured([Self = this]() { static_cast<void>(Self); }) {}
70 // CHECK-MESSAGES: :[[@LINE-1]]:30: warning: 'this' captured by a lambda and stored in a class member variable;
71 std::function<void()> Captured;
72 // CHECK-MESSAGES: :[[@LINE-1]]:25: note: class member of type 'std::function<void (void)>' that stores captured 'this'
73};
74
75struct DeleteMoveAndCopy {
76 DeleteMoveAndCopy() : Captured([this]() { static_cast<void>(this); }) {}
77 DeleteMoveAndCopy(DeleteMoveAndCopy const&) = delete;
78 DeleteMoveAndCopy(DeleteMoveAndCopy &&) = delete;
79 DeleteMoveAndCopy& operator=(DeleteMoveAndCopy const&) = delete;
80 DeleteMoveAndCopy& operator=(DeleteMoveAndCopy &&) = delete;
81 std::function<void()> Captured;
82};
83
84struct DeleteCopyImplicitDisabledMove {
85 DeleteCopyImplicitDisabledMove() : Captured([this]() { static_cast<void>(this); }) {}
86 DeleteCopyImplicitDisabledMove(DeleteCopyImplicitDisabledMove const&) = delete;
87 DeleteCopyImplicitDisabledMove& operator=(DeleteCopyImplicitDisabledMove const&) = delete;
88 std::function<void()> Captured;
89};
90
91struct DeleteCopyDefaultMove {
92 DeleteCopyDefaultMove() : Captured([this]() { static_cast<void>(this); }) {}
93 // CHECK-MESSAGES: :[[@LINE-1]]:38: warning: 'this' captured by a lambda and stored in a class member variable;
94 DeleteCopyDefaultMove(DeleteCopyDefaultMove const&) = delete;
95 DeleteCopyDefaultMove(DeleteCopyDefaultMove &&) = default;
96 DeleteCopyDefaultMove& operator=(DeleteCopyDefaultMove const&) = delete;
97 DeleteCopyDefaultMove& operator=(DeleteCopyDefaultMove &&) = default;
98 std::function<void()> Captured;
99 // CHECK-MESSAGES: :[[@LINE-1]]:25: note: class member of type 'std::function<void (void)>' that stores captured 'this'
100};
101
102struct DeleteMoveDefaultCopy {
103 DeleteMoveDefaultCopy() : Captured([this]() { static_cast<void>(this); }) {}
104 // CHECK-MESSAGES: :[[@LINE-1]]:38: warning: 'this' captured by a lambda and stored in a class member variable;
105 DeleteMoveDefaultCopy(DeleteMoveDefaultCopy const&) = default;
106 DeleteMoveDefaultCopy(DeleteMoveDefaultCopy &&) = delete;
107 DeleteMoveDefaultCopy& operator=(DeleteMoveDefaultCopy const&) = default;
108 DeleteMoveDefaultCopy& operator=(DeleteMoveDefaultCopy &&) = delete;
109 std::function<void()> Captured;
110 // CHECK-MESSAGES: :[[@LINE-1]]:25: note: class member of type 'std::function<void (void)>' that stores captured 'this'
111};
112
113struct DeleteCopyBase {
114 DeleteCopyBase() = default;
115 DeleteCopyBase(DeleteCopyBase const&) = delete;
116 DeleteCopyBase(DeleteCopyBase &&) = default;
117 DeleteCopyBase& operator=(DeleteCopyBase const&) = delete;
118 DeleteCopyBase& operator=(DeleteCopyBase &&) = default;
119};
120
121struct DeleteMoveBase {
122 DeleteMoveBase() = default;
123 DeleteMoveBase(DeleteMoveBase const&) = default;
124 DeleteMoveBase(DeleteMoveBase &&) = delete;
125 DeleteMoveBase& operator=(DeleteMoveBase const&) = default;
126 DeleteMoveBase& operator=(DeleteMoveBase &&) = delete;
127};
128
129struct DeleteCopyMoveBase : DeleteCopyBase, DeleteMoveBase {};
130
131struct InheritDeleteCopy : DeleteCopyBase {
132 InheritDeleteCopy() : DeleteCopyBase{}, Captured([this]() { static_cast<void>(this); }) {}
133 // CHECK-MESSAGES: :[[@LINE-1]]:52: warning: 'this' captured by a lambda and stored in a class member variable;
134 std::function<void()> Captured;
135 // CHECK-MESSAGES: :[[@LINE-1]]:25: note: class member of type 'std::function<void (void)>' that stores captured 'this'
136};
137struct InheritDeleteMove : DeleteMoveBase {
138 InheritDeleteMove() : DeleteMoveBase{}, Captured([this]() { static_cast<void>(this); }) {}
139 // CHECK-MESSAGES: :[[@LINE-1]]:52: warning: 'this' captured by a lambda and stored in a class member variable;
140 std::function<void()> Captured;
141 // CHECK-MESSAGES: :[[@LINE-1]]:25: note: class member of type 'std::function<void (void)>' that stores captured 'this'
142};
143struct InheritDeleteCopyMove : DeleteCopyMoveBase {
144 InheritDeleteCopyMove() : DeleteCopyMoveBase{}, Captured([this]() { static_cast<void>(this); }) {}
145 std::function<void()> Captured;
146};
147
148struct PrivateCopyMoveBase {
149// It is how to disable copy and move in C++03
150 PrivateCopyMoveBase() = default;
151private:
152 PrivateCopyMoveBase(PrivateCopyMoveBase const&) = default;
153 PrivateCopyMoveBase(PrivateCopyMoveBase &&) = default;
154 PrivateCopyMoveBase& operator=(PrivateCopyMoveBase const&) = default;
155 PrivateCopyMoveBase& operator=(PrivateCopyMoveBase &&) = default;
156};
157struct InheritPrivateCopyMove : PrivateCopyMoveBase {
158 InheritPrivateCopyMove() : PrivateCopyMoveBase{}, Captured([this]() { static_cast<void>(this); }) {}
159 std::function<void()> Captured;
160};
161
162struct UserDefinedCopyMove {
163 UserDefinedCopyMove() : Captured([this]() { static_cast<void>(this); }) {}
164 UserDefinedCopyMove(UserDefinedCopyMove const&);
165 UserDefinedCopyMove(UserDefinedCopyMove &&);
166 UserDefinedCopyMove& operator=(UserDefinedCopyMove const&);
167 UserDefinedCopyMove& operator=(UserDefinedCopyMove &&);
168 std::function<void()> Captured;
169};
170
171struct UserDefinedCopyMoveWithDefault1 {
172 UserDefinedCopyMoveWithDefault1() : Captured([this]() { static_cast<void>(this); }) {}
173 // CHECK-MESSAGES: :[[@LINE-1]]:48: warning: 'this' captured by a lambda and stored in a class member variable;
174 UserDefinedCopyMoveWithDefault1(UserDefinedCopyMoveWithDefault1 const&) = default;
175 UserDefinedCopyMoveWithDefault1(UserDefinedCopyMoveWithDefault1 &&);
176 UserDefinedCopyMoveWithDefault1& operator=(UserDefinedCopyMoveWithDefault1 const&);
177 UserDefinedCopyMoveWithDefault1& operator=(UserDefinedCopyMoveWithDefault1 &&);
178 std::function<void()> Captured;
179 // CHECK-MESSAGES: :[[@LINE-1]]:25: note: class member of type 'std::function<void (void)>' that stores captured 'this'
180};
181
182struct UserDefinedCopyMoveWithDefault2 {
183 UserDefinedCopyMoveWithDefault2() : Captured([this]() { static_cast<void>(this); }) {}
184 // CHECK-MESSAGES: :[[@LINE-1]]:48: warning: 'this' captured by a lambda and stored in a class member variable;
185 UserDefinedCopyMoveWithDefault2(UserDefinedCopyMoveWithDefault2 const&);
186 UserDefinedCopyMoveWithDefault2(UserDefinedCopyMoveWithDefault2 &&) = default;
187 UserDefinedCopyMoveWithDefault2& operator=(UserDefinedCopyMoveWithDefault2 const&);
188 UserDefinedCopyMoveWithDefault2& operator=(UserDefinedCopyMoveWithDefault2 &&);
189 std::function<void()> Captured;
190 // CHECK-MESSAGES: :[[@LINE-1]]:25: note: class member of type 'std::function<void (void)>' that stores captured 'this'
191};
192
193struct UserDefinedCopyMoveWithDefault3 {
194 UserDefinedCopyMoveWithDefault3() : Captured([this]() { static_cast<void>(this); }) {}
195 // CHECK-MESSAGES: :[[@LINE-1]]:48: warning: 'this' captured by a lambda and stored in a class member variable;
196 UserDefinedCopyMoveWithDefault3(UserDefinedCopyMoveWithDefault3 const&);
197 UserDefinedCopyMoveWithDefault3(UserDefinedCopyMoveWithDefault3 &&);
198 UserDefinedCopyMoveWithDefault3& operator=(UserDefinedCopyMoveWithDefault3 const&) = default;
199 UserDefinedCopyMoveWithDefault3& operator=(UserDefinedCopyMoveWithDefault3 &&);
200 std::function<void()> Captured;
201 // CHECK-MESSAGES: :[[@LINE-1]]:25: note: class member of type 'std::function<void (void)>' that stores captured 'this'
202};
203
204struct UserDefinedCopyMoveWithDefault4 {
205 UserDefinedCopyMoveWithDefault4() : Captured([this]() { static_cast<void>(this); }) {}
206 // CHECK-MESSAGES: :[[@LINE-1]]:48: warning: 'this' captured by a lambda and stored in a class member variable;
207 UserDefinedCopyMoveWithDefault4(UserDefinedCopyMoveWithDefault4 const&);
208 UserDefinedCopyMoveWithDefault4(UserDefinedCopyMoveWithDefault4 &&);
209 UserDefinedCopyMoveWithDefault4& operator=(UserDefinedCopyMoveWithDefault4 const&);
210 UserDefinedCopyMoveWithDefault4& operator=(UserDefinedCopyMoveWithDefault4 &&) = default;
211 std::function<void()> Captured;
212 // CHECK-MESSAGES: :[[@LINE-1]]:25: note: class member of type 'std::function<void (void)>' that stores captured 'this'
213};
214
215struct CustomFunctionWrapper {
216 CustomFunctionWrapper() : Captured([this]() { static_cast<void>(this); }) {}
217 // CHECK-MESSAGES: :[[@LINE-1]]:38: warning: 'this' captured by a lambda and stored in a class member variable;
218 Fn Captured;
219 // CHECK-MESSAGES: :[[@LINE-1]]:6: note: class member of type 'Fn' that stores captured 'this'
220};
221
222struct BindConstructor {
223 BindConstructor() : Captured(std::bind(&BindConstructor::method, this)) {}
224 // CHECK-MESSAGES: :[[@LINE-1]]:32: warning: 'this' captured by a 'std::bind' call and stored in a class member variable;
225 void method() {}
226 std::function<void()> Captured;
227 // CHECK-MESSAGES: :[[@LINE-1]]:25: note: class member of type 'std::function<void (void)>' that stores captured 'this'
228};
229
230struct BindField1 {
231 void method() {}
232 std::function<void()> Captured = std::bind(&BindField1::method, this);
233 // CHECK-MESSAGES: :[[@LINE-1]]:36: warning: 'this' captured by a 'std::bind' call and stored in a class member variable;
234 // CHECK-MESSAGES: :[[@LINE-2]]:25: note: class member of type 'std::function<void (void)>' that stores captured 'this'
235};
236
237struct BindField2 {
238 void method() {}
239 std::function<void()> Captured{std::bind(&BindField2::method, this)};
240 // CHECK-MESSAGES: :[[@LINE-1]]:34: warning: 'this' captured by a 'std::bind' call and stored in a class member variable;
241 // CHECK-MESSAGES: :[[@LINE-2]]:25: note: class member of type 'std::function<void (void)>' that stores captured 'this'
242};
243
244struct BindCustom {
245 BindCustom() : Captured(Bind(&BindCustom::method, this)) {}
246 // CHECK-MESSAGES: :[[@LINE-1]]:27: warning: 'this' captured by a 'Bind' call and stored in a class member variable;
247 void method() {}
248 std::function<void()> Captured;
249 // CHECK-MESSAGES: :[[@LINE-1]]:25: note: class member of type 'std::function<void (void)>' that stores captured 'this'
250};
251
252struct BindNotCapturingThis {
253 void method(int) {}
254 BindNotCapturingThis(int V) : Captured(std::bind(&BindNotCapturingThis::method, V)) {}
255 std::function<void()> Captured;
256};
257
258struct DeletedCopyMoveWithBind {
259 DeletedCopyMoveWithBind() : Captured(std::bind(&DeletedCopyMoveWithBind::method, this)) {}
260 DeletedCopyMoveWithBind(DeletedCopyMoveWithBind const&) = delete;
261 DeletedCopyMoveWithBind(DeletedCopyMoveWithBind &&) = delete;
262 DeletedCopyMoveWithBind& operator=(DeletedCopyMoveWithBind const&) = delete;
263 DeletedCopyMoveWithBind& operator=(DeletedCopyMoveWithBind &&) = delete;
264 void method() {}
265 std::function<void()> Captured;
266};
267

source code of clang-tools-extra/test/clang-tidy/checkers/bugprone/capturing-this-in-member-variable.cpp