1 // RUN: %check_clang_tidy %s readability-convert-member-functions-to-static %t 2 3 class DoNotMakeEmptyStatic { emptyMethod()4 void emptyMethod() {} 5 void empty_method_out_of_line(); 6 }; 7 empty_method_out_of_line()8void DoNotMakeEmptyStatic::empty_method_out_of_line() {} 9 10 class A { 11 int field; 12 const int const_field; 13 static int static_field; 14 no_use()15 void no_use() { 16 // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: method 'no_use' can be made static 17 // CHECK-FIXES: {{^}} static void no_use() { 18 int i = 1; 19 } 20 read_field()21 int read_field() { 22 return field; 23 } 24 write_field()25 void write_field() { 26 field = 1; 27 } 28 call_non_const_member()29 int call_non_const_member() { return read_field(); } 30 call_static_member()31 int call_static_member() { 32 // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: method 'call_static_member' can be made static 33 // CHECK-FIXES: {{^}} static int call_static_member() { 34 already_static(); 35 } 36 read_static()37 int read_static() { 38 // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: method 'read_static' can be made static 39 // CHECK-FIXES: {{^}} static int read_static() { 40 return static_field; 41 } write_static()42 void write_static() { 43 // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: method 'write_static' can be made static 44 // CHECK-FIXES: {{^}} static void write_static() { 45 static_field = 1; 46 } 47 static_nested()48 void static_nested() { 49 // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: method 'static_nested' can be made static 50 // CHECK-FIXES: {{^}} static void static_nested() { 51 struct Nested { 52 int Foo; 53 int getFoo() { return Foo; } 54 }; 55 } 56 write_nested()57 void write_nested() { 58 struct Nested { 59 int Foo; 60 int getFoo() { return Foo; } 61 }; 62 // Ensure we still detect usages of `this` once we leave the nested class definition. 63 field = 1; 64 } 65 already_static()66 static int already_static() { return static_field; } 67 already_const() const68 int already_const() const { return field; } 69 already_const_convert_to_static() const70 int already_const_convert_to_static() const { 71 // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: method 'already_const_convert_to_static' can be made static 72 // CHECK-FIXES: {{^}} static int already_const_convert_to_static() { 73 return static_field; 74 } 75 76 static int out_of_line_already_static(); 77 78 void out_of_line_call_static(); 79 // CHECK-FIXES: {{^}} static void out_of_line_call_static(); 80 int out_of_line_const_to_static() const; 81 // CHECK-FIXES: {{^}} static int out_of_line_const_to_static() ; 82 }; 83 out_of_line_already_static()84int A::out_of_line_already_static() { return 0; } 85 out_of_line_call_static()86void A::out_of_line_call_static() { 87 // CHECK-MESSAGES: :[[@LINE-1]]:9: warning: method 'out_of_line_call_static' can be made static 88 // CHECK-FIXES: {{^}}void A::out_of_line_call_static() { 89 already_static(); 90 } 91 out_of_line_const_to_static() const92int A::out_of_line_const_to_static() const { 93 // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: method 'out_of_line_const_to_static' can be made static 94 // CHECK-FIXES: {{^}}int A::out_of_line_const_to_static() { 95 return 0; 96 } 97 98 struct KeepVirtual { fKeepVirtual99 virtual int f() { return 0; } hKeepVirtual100 virtual int h() const { return 0; } 101 }; 102 103 struct KeepVirtualDerived : public KeepVirtual { fKeepVirtualDerived104 int f() { return 0; } hKeepVirtualDerived105 int h() const override { return 0; } 106 }; 107 108 // Don't add 'static' to special member functions and operators. 109 struct KeepSpecial { KeepSpecialKeepSpecial110 KeepSpecial() { int L = 0; } ~KeepSpecialKeepSpecial111 ~KeepSpecial() { int L = 0; } operator +KeepSpecial112 int operator+() { return 0; } operator intKeepSpecial113 operator int() { return 0; } 114 }; 115 KeepLambdas()116void KeepLambdas() { 117 using FT = int (*)(); 118 auto F = static_cast<FT>([]() { return 0; }); 119 auto F2 = []() { return 0; }; 120 } 121 122 template <class Base> 123 struct KeepWithTemplateBase : public Base { 124 int i; 125 // We cannot make these methods static because they might need to override 126 // a function from Base. static_fKeepWithTemplateBase127 int static_f() { return 0; } 128 }; 129 130 template <class T> 131 struct KeepTemplateClass { 132 int i; 133 // We cannot make these methods static because a specialization 134 // might use *this differently. static_fKeepTemplateClass135 int static_f() { return 0; } 136 }; 137 138 struct KeepTemplateMethod { 139 int i; 140 // We cannot make these methods static because a specialization 141 // might use *this differently. 142 template <class T> static_fKeepTemplateMethod143 static int static_f() { return 0; } 144 }; 145 instantiate()146void instantiate() { 147 struct S {}; 148 KeepWithTemplateBase<S> I1; 149 I1.static_f(); 150 151 KeepTemplateClass<int> I2; 152 I2.static_f(); 153 154 KeepTemplateMethod I3; 155 I3.static_f<int>(); 156 } 157 158 struct Trailing { gTrailing159 auto g() const -> int { 160 // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: method 'g' can be made static 161 // CHECK-FIXES: {{^}} static auto g() -> int { 162 return 0; 163 } 164 volTrailing165 void vol() volatile { 166 // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: method 'vol' can be made static 167 return; 168 } 169 refTrailing170 void ref() const & { 171 // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: method 'ref' can be made static 172 return; 173 } refrefTrailing174 void refref() const && { 175 // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: method 'refref' can be made static 176 return; 177 } 178 restrTrailing179 void restr() __restrict { 180 // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: method 'restr' can be made static 181 return; 182 } 183 }; 184 185 struct UnevaluatedContext { fUnevaluatedContext186 void f() { sizeof(this); } 187 188 void noex() noexcept(noexcept(this)); 189 }; 190 191 struct LambdaCapturesThis { 192 int Field; 193 explicitCaptureLambdaCapturesThis194 int explicitCapture() { 195 return [this]() { return Field; }(); 196 } 197 implicitCaptureLambdaCapturesThis198 int implicitCapture() { 199 return [&]() { return Field; }(); 200 } 201 }; 202 203 struct NoFixitInMacro { 204 #define CONST const no_use_macro_constNoFixitInMacro205 int no_use_macro_const() CONST { 206 // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: method 'no_use_macro_const' can be made static 207 return 0; 208 } 209 210 #define ADD_CONST(F) F const ADD_CONSTNoFixitInMacro211 int ADD_CONST(no_use_macro2()) { 212 return 0; 213 } 214 215 #define FUN no_use_macro() 216 int i; 217 int FUN { 218 return i; 219 } 220 221 #define T(FunctionName, Keyword) \ 222 Keyword int FunctionName() { return 0; } 223 #define EMPTY 224 T(A, EMPTY) 225 T(B, static) 226 227 #define T2(FunctionName) \ 228 int FunctionName() { return 0; } 229 T2(A2) 230 231 #define VOLATILE volatile 232 void volatileMacro() VOLATILE { 233 // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: method 'volatileMacro' can be made static 234 return; 235 } 236 }; 237