238 lines · cpp
1// RUN: %check_clang_tidy %s readability-convert-member-functions-to-static %t2 3class DoNotMakeEmptyStatic {4 void emptyMethod() {}5 void empty_method_out_of_line();6};7 8void DoNotMakeEmptyStatic::empty_method_out_of_line() {}9 10class A {11 int field;12 const int const_field;13 static int static_field;14 15 void no_use() {16 // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: method 'no_use' can be made static17 // CHECK-FIXES: static void no_use() {18 int i = 1;19 }20 21 int read_field() {22 return field;23 }24 25 void write_field() {26 field = 1;27 }28 29 int call_non_const_member() { return read_field(); }30 31 int call_static_member() {32 // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: method 'call_static_member' can be made static33 // CHECK-FIXES: static int call_static_member() {34 already_static();35 return 0;36 }37 38 int read_static() {39 // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: method 'read_static' can be made static40 // CHECK-FIXES: static int read_static() {41 return static_field;42 }43 void write_static() {44 // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: method 'write_static' can be made static45 // CHECK-FIXES: static void write_static() {46 static_field = 1;47 }48 49 void static_nested() {50 // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: method 'static_nested' can be made static51 // CHECK-FIXES: static void static_nested() {52 struct Nested {53 int Foo;54 int getFoo() { return Foo; }55 };56 }57 58 void write_nested() {59 struct Nested {60 int Foo;61 int getFoo() { return Foo; }62 };63 // Ensure we still detect usages of `this` once we leave the nested class definition.64 field = 1;65 }66 67 static int already_static() { return static_field; }68 69 int already_const() const { return field; }70 71 int already_const_convert_to_static() const {72 // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: method 'already_const_convert_to_static' can be made static73 // CHECK-FIXES: static int already_const_convert_to_static() {74 return static_field;75 }76 77 static int out_of_line_already_static();78 79 void out_of_line_call_static();80 // CHECK-FIXES: static void out_of_line_call_static();81 int out_of_line_const_to_static() const;82 // CHECK-FIXES: static int out_of_line_const_to_static() ;83};84 85int A::out_of_line_already_static() { return 0; }86 87void A::out_of_line_call_static() {88 // CHECK-MESSAGES: :[[@LINE-1]]:9: warning: method 'out_of_line_call_static' can be made static89 // CHECK-FIXES: void A::out_of_line_call_static() {90 already_static();91}92 93int A::out_of_line_const_to_static() const {94 // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: method 'out_of_line_const_to_static' can be made static95 // CHECK-FIXES: int A::out_of_line_const_to_static() {96 return 0;97}98 99struct KeepVirtual {100 virtual int f() { return 0; }101 virtual int h() const { return 0; }102};103 104struct KeepVirtualDerived : public KeepVirtual {105 int f() { return 0; }106 int h() const override { return 0; }107};108 109// Don't add 'static' to special member functions and operators.110struct KeepSpecial {111 KeepSpecial() { int L = 0; }112 ~KeepSpecial() { int L = 0; }113 int operator+() { return 0; }114 operator int() { return 0; }115};116 117void KeepLambdas() {118 using FT = int (*)();119 auto F = static_cast<FT>([]() { return 0; });120 auto F2 = []() { return 0; };121}122 123template <class Base>124struct KeepWithTemplateBase : public Base {125 int i;126 // We cannot make these methods static because they might need to override127 // a function from Base.128 int static_f() { return 0; }129};130 131template <class T>132struct KeepTemplateClass {133 int i;134 // We cannot make these methods static because a specialization135 // might use *this differently.136 int static_f() { return 0; }137};138 139struct KeepTemplateMethod {140 int i;141 // We cannot make these methods static because a specialization142 // might use *this differently.143 template <class T>144 static int static_f() { return 0; }145};146 147void instantiate() {148 struct S {};149 KeepWithTemplateBase<S> I1;150 I1.static_f();151 152 KeepTemplateClass<int> I2;153 I2.static_f();154 155 KeepTemplateMethod I3;156 I3.static_f<int>();157}158 159struct Trailing {160 auto g() const -> int {161 // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: method 'g' can be made static162 // CHECK-FIXES: static auto g() -> int {163 return 0;164 }165 166 void vol() volatile {167 // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: method 'vol' can be made static168 return;169 }170 171 void ref() const & {172 // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: method 'ref' can be made static173 return;174 }175 void refref() const && {176 // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: method 'refref' can be made static177 return;178 }179 180 void restr() __restrict {181 // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: method 'restr' can be made static182 return;183 }184};185 186struct UnevaluatedContext {187 void f() { sizeof(this); }188 189 void noex() noexcept(noexcept(this));190};191 192struct LambdaCapturesThis {193 int Field;194 195 int explicitCapture() {196 return [this]() { return Field; }();197 }198 199 int implicitCapture() {200 return [&]() { return Field; }();201 }202};203 204struct NoFixitInMacro {205#define CONST const206 int no_use_macro_const() CONST {207 // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: method 'no_use_macro_const' can be made static208 return 0;209 }210 211#define ADD_CONST(F) F const212 int ADD_CONST(no_use_macro2()) {213 return 0;214 }215 216#define FUN no_use_macro()217 int i;218 int FUN {219 return i;220 }221 222#define T(FunctionName, Keyword) \223 Keyword int FunctionName() { return 0; }224#define EMPTY225 T(A, EMPTY)226 T(B, static)227 228#define T2(FunctionName) \229 int FunctionName() { return 0; }230 T2(A2)231 232#define VOLATILE volatile233 void volatileMacro() VOLATILE {234 // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: method 'volatileMacro' can be made static235 return;236 }237};238