189a1d03eSRichard // RUN: %check_clang_tidy %s readability-convert-member-functions-to-static %t 289a1d03eSRichard 389a1d03eSRichard class DoNotMakeEmptyStatic { emptyMethod()489a1d03eSRichard void emptyMethod() {} 589a1d03eSRichard void empty_method_out_of_line(); 689a1d03eSRichard }; 789a1d03eSRichard empty_method_out_of_line()889a1d03eSRichardvoid DoNotMakeEmptyStatic::empty_method_out_of_line() {} 989a1d03eSRichard 1089a1d03eSRichard class A { 1189a1d03eSRichard int field; 1289a1d03eSRichard const int const_field; 1389a1d03eSRichard static int static_field; 1489a1d03eSRichard no_use()1589a1d03eSRichard void no_use() { 1689a1d03eSRichard // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: method 'no_use' can be made static 1789a1d03eSRichard // CHECK-FIXES: {{^}} static void no_use() { 1889a1d03eSRichard int i = 1; 1989a1d03eSRichard } 2089a1d03eSRichard read_field()2189a1d03eSRichard int read_field() { 2289a1d03eSRichard return field; 2389a1d03eSRichard } 2489a1d03eSRichard write_field()2589a1d03eSRichard void write_field() { 2689a1d03eSRichard field = 1; 2789a1d03eSRichard } 2889a1d03eSRichard call_non_const_member()2989a1d03eSRichard int call_non_const_member() { return read_field(); } 3089a1d03eSRichard call_static_member()3189a1d03eSRichard int call_static_member() { 3289a1d03eSRichard // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: method 'call_static_member' can be made static 3389a1d03eSRichard // CHECK-FIXES: {{^}} static int call_static_member() { 3489a1d03eSRichard already_static(); 3589a1d03eSRichard } 3689a1d03eSRichard read_static()3789a1d03eSRichard int read_static() { 3889a1d03eSRichard // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: method 'read_static' can be made static 3989a1d03eSRichard // CHECK-FIXES: {{^}} static int read_static() { 4089a1d03eSRichard return static_field; 4189a1d03eSRichard } write_static()4289a1d03eSRichard void write_static() { 4389a1d03eSRichard // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: method 'write_static' can be made static 4489a1d03eSRichard // CHECK-FIXES: {{^}} static void write_static() { 4589a1d03eSRichard static_field = 1; 4689a1d03eSRichard } 4789a1d03eSRichard static_nested()48*67e05d38SNathan James void static_nested() { 49*67e05d38SNathan James // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: method 'static_nested' can be made static 50*67e05d38SNathan James // CHECK-FIXES: {{^}} static void static_nested() { 51*67e05d38SNathan James struct Nested { 52*67e05d38SNathan James int Foo; 53*67e05d38SNathan James int getFoo() { return Foo; } 54*67e05d38SNathan James }; 55*67e05d38SNathan James } 56*67e05d38SNathan James write_nested()57*67e05d38SNathan James void write_nested() { 58*67e05d38SNathan James struct Nested { 59*67e05d38SNathan James int Foo; 60*67e05d38SNathan James int getFoo() { return Foo; } 61*67e05d38SNathan James }; 62*67e05d38SNathan James // Ensure we still detect usages of `this` once we leave the nested class definition. 63*67e05d38SNathan James field = 1; 64*67e05d38SNathan James } 65*67e05d38SNathan James already_static()6689a1d03eSRichard static int already_static() { return static_field; } 6789a1d03eSRichard already_const() const6889a1d03eSRichard int already_const() const { return field; } 6989a1d03eSRichard already_const_convert_to_static() const7089a1d03eSRichard int already_const_convert_to_static() const { 7189a1d03eSRichard // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: method 'already_const_convert_to_static' can be made static 7289a1d03eSRichard // CHECK-FIXES: {{^}} static int already_const_convert_to_static() { 7389a1d03eSRichard return static_field; 7489a1d03eSRichard } 7589a1d03eSRichard 7689a1d03eSRichard static int out_of_line_already_static(); 7789a1d03eSRichard 7889a1d03eSRichard void out_of_line_call_static(); 7989a1d03eSRichard // CHECK-FIXES: {{^}} static void out_of_line_call_static(); 8089a1d03eSRichard int out_of_line_const_to_static() const; 8189a1d03eSRichard // CHECK-FIXES: {{^}} static int out_of_line_const_to_static() ; 8289a1d03eSRichard }; 8389a1d03eSRichard out_of_line_already_static()8489a1d03eSRichardint A::out_of_line_already_static() { return 0; } 8589a1d03eSRichard out_of_line_call_static()8689a1d03eSRichardvoid A::out_of_line_call_static() { 8789a1d03eSRichard // CHECK-MESSAGES: :[[@LINE-1]]:9: warning: method 'out_of_line_call_static' can be made static 8889a1d03eSRichard // CHECK-FIXES: {{^}}void A::out_of_line_call_static() { 8989a1d03eSRichard already_static(); 9089a1d03eSRichard } 9189a1d03eSRichard out_of_line_const_to_static() const9289a1d03eSRichardint A::out_of_line_const_to_static() const { 9389a1d03eSRichard // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: method 'out_of_line_const_to_static' can be made static 9489a1d03eSRichard // CHECK-FIXES: {{^}}int A::out_of_line_const_to_static() { 9589a1d03eSRichard return 0; 9689a1d03eSRichard } 9789a1d03eSRichard 9889a1d03eSRichard struct KeepVirtual { fKeepVirtual9989a1d03eSRichard virtual int f() { return 0; } hKeepVirtual10089a1d03eSRichard virtual int h() const { return 0; } 10189a1d03eSRichard }; 10289a1d03eSRichard 10389a1d03eSRichard struct KeepVirtualDerived : public KeepVirtual { fKeepVirtualDerived10489a1d03eSRichard int f() { return 0; } hKeepVirtualDerived10589a1d03eSRichard int h() const override { return 0; } 10689a1d03eSRichard }; 10789a1d03eSRichard 10889a1d03eSRichard // Don't add 'static' to special member functions and operators. 10989a1d03eSRichard struct KeepSpecial { KeepSpecialKeepSpecial11089a1d03eSRichard KeepSpecial() { int L = 0; } ~KeepSpecialKeepSpecial11189a1d03eSRichard ~KeepSpecial() { int L = 0; } operator +KeepSpecial11289a1d03eSRichard int operator+() { return 0; } operator intKeepSpecial11389a1d03eSRichard operator int() { return 0; } 11489a1d03eSRichard }; 11589a1d03eSRichard KeepLambdas()11689a1d03eSRichardvoid KeepLambdas() { 11789a1d03eSRichard using FT = int (*)(); 11889a1d03eSRichard auto F = static_cast<FT>([]() { return 0; }); 11989a1d03eSRichard auto F2 = []() { return 0; }; 12089a1d03eSRichard } 12189a1d03eSRichard 12289a1d03eSRichard template <class Base> 12389a1d03eSRichard struct KeepWithTemplateBase : public Base { 12489a1d03eSRichard int i; 12589a1d03eSRichard // We cannot make these methods static because they might need to override 12689a1d03eSRichard // a function from Base. static_fKeepWithTemplateBase12789a1d03eSRichard int static_f() { return 0; } 12889a1d03eSRichard }; 12989a1d03eSRichard 13089a1d03eSRichard template <class T> 13189a1d03eSRichard struct KeepTemplateClass { 13289a1d03eSRichard int i; 13389a1d03eSRichard // We cannot make these methods static because a specialization 13489a1d03eSRichard // might use *this differently. static_fKeepTemplateClass13589a1d03eSRichard int static_f() { return 0; } 13689a1d03eSRichard }; 13789a1d03eSRichard 13889a1d03eSRichard struct KeepTemplateMethod { 13989a1d03eSRichard int i; 14089a1d03eSRichard // We cannot make these methods static because a specialization 14189a1d03eSRichard // might use *this differently. 14289a1d03eSRichard template <class T> static_fKeepTemplateMethod14389a1d03eSRichard static int static_f() { return 0; } 14489a1d03eSRichard }; 14589a1d03eSRichard instantiate()14689a1d03eSRichardvoid instantiate() { 14789a1d03eSRichard struct S {}; 14889a1d03eSRichard KeepWithTemplateBase<S> I1; 14989a1d03eSRichard I1.static_f(); 15089a1d03eSRichard 15189a1d03eSRichard KeepTemplateClass<int> I2; 15289a1d03eSRichard I2.static_f(); 15389a1d03eSRichard 15489a1d03eSRichard KeepTemplateMethod I3; 15589a1d03eSRichard I3.static_f<int>(); 15689a1d03eSRichard } 15789a1d03eSRichard 15889a1d03eSRichard struct Trailing { gTrailing15989a1d03eSRichard auto g() const -> int { 16089a1d03eSRichard // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: method 'g' can be made static 16189a1d03eSRichard // CHECK-FIXES: {{^}} static auto g() -> int { 16289a1d03eSRichard return 0; 16389a1d03eSRichard } 16489a1d03eSRichard volTrailing16589a1d03eSRichard void vol() volatile { 16689a1d03eSRichard // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: method 'vol' can be made static 16789a1d03eSRichard return; 16889a1d03eSRichard } 16989a1d03eSRichard refTrailing17089a1d03eSRichard void ref() const & { 17189a1d03eSRichard // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: method 'ref' can be made static 17289a1d03eSRichard return; 17389a1d03eSRichard } refrefTrailing17489a1d03eSRichard void refref() const && { 17589a1d03eSRichard // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: method 'refref' can be made static 17689a1d03eSRichard return; 17789a1d03eSRichard } 17889a1d03eSRichard restrTrailing17989a1d03eSRichard void restr() __restrict { 18089a1d03eSRichard // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: method 'restr' can be made static 18189a1d03eSRichard return; 18289a1d03eSRichard } 18389a1d03eSRichard }; 18489a1d03eSRichard 18589a1d03eSRichard struct UnevaluatedContext { fUnevaluatedContext18689a1d03eSRichard void f() { sizeof(this); } 18789a1d03eSRichard 18889a1d03eSRichard void noex() noexcept(noexcept(this)); 18989a1d03eSRichard }; 19089a1d03eSRichard 19189a1d03eSRichard struct LambdaCapturesThis { 19289a1d03eSRichard int Field; 19389a1d03eSRichard explicitCaptureLambdaCapturesThis19489a1d03eSRichard int explicitCapture() { 19589a1d03eSRichard return [this]() { return Field; }(); 19689a1d03eSRichard } 19789a1d03eSRichard implicitCaptureLambdaCapturesThis19889a1d03eSRichard int implicitCapture() { 19989a1d03eSRichard return [&]() { return Field; }(); 20089a1d03eSRichard } 20189a1d03eSRichard }; 20289a1d03eSRichard 20389a1d03eSRichard struct NoFixitInMacro { 20489a1d03eSRichard #define CONST const no_use_macro_constNoFixitInMacro20589a1d03eSRichard int no_use_macro_const() CONST { 20689a1d03eSRichard // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: method 'no_use_macro_const' can be made static 20789a1d03eSRichard return 0; 20889a1d03eSRichard } 20989a1d03eSRichard 21089a1d03eSRichard #define ADD_CONST(F) F const ADD_CONSTNoFixitInMacro21189a1d03eSRichard int ADD_CONST(no_use_macro2()) { 21289a1d03eSRichard return 0; 21389a1d03eSRichard } 21489a1d03eSRichard 21589a1d03eSRichard #define FUN no_use_macro() 21689a1d03eSRichard int i; 21789a1d03eSRichard int FUN { 21889a1d03eSRichard return i; 21989a1d03eSRichard } 22089a1d03eSRichard 22189a1d03eSRichard #define T(FunctionName, Keyword) \ 22289a1d03eSRichard Keyword int FunctionName() { return 0; } 22389a1d03eSRichard #define EMPTY 22489a1d03eSRichard T(A, EMPTY) 22589a1d03eSRichard T(B, static) 22689a1d03eSRichard 22789a1d03eSRichard #define T2(FunctionName) \ 22889a1d03eSRichard int FunctionName() { return 0; } 22989a1d03eSRichard T2(A2) 23089a1d03eSRichard 23189a1d03eSRichard #define VOLATILE volatile 23289a1d03eSRichard void volatileMacro() VOLATILE { 23389a1d03eSRichard // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: method 'volatileMacro' can be made static 23489a1d03eSRichard return; 23589a1d03eSRichard } 23689a1d03eSRichard }; 237