267 lines · cpp
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 std21 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++03150 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