1// RUN: %check_clang_tidy %s readability-convert-member-functions-to-static %t
2
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 static
17 // 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 static
33 // CHECK-FIXES: {{^}} static int call_static_member() {
34 already_static();
35 }
36
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 }
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
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
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
66 static int already_static() { return static_field; }
67
68 int already_const() const { return field; }
69
70 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
84int A::out_of_line_already_static() { return 0; }
85
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
92int 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
98struct KeepVirtual {
99 virtual int f() { return 0; }
100 virtual int h() const { return 0; }
101};
102
103struct KeepVirtualDerived : public KeepVirtual {
104 int f() { return 0; }
105 int h() const override { return 0; }
106};
107
108// Don't add 'static' to special member functions and operators.
109struct KeepSpecial {
110 KeepSpecial() { int L = 0; }
111 ~KeepSpecial() { int L = 0; }
112 int operator+() { return 0; }
113 operator int() { return 0; }
114};
115
116void KeepLambdas() {
117 using FT = int (*)();
118 auto F = static_cast<FT>([]() { return 0; });
119 auto F2 = []() { return 0; };
120}
121
122template <class Base>
123struct KeepWithTemplateBase : public Base {
124 int i;
125 // We cannot make these methods static because they might need to override
126 // a function from Base.
127 int static_f() { return 0; }
128};
129
130template <class T>
131struct KeepTemplateClass {
132 int i;
133 // We cannot make these methods static because a specialization
134 // might use *this differently.
135 int static_f() { return 0; }
136};
137
138struct KeepTemplateMethod {
139 int i;
140 // We cannot make these methods static because a specialization
141 // might use *this differently.
142 template <class T>
143 static int static_f() { return 0; }
144};
145
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
158struct Trailing {
159 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
165 void vol() volatile {
166 // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: method 'vol' can be made static
167 return;
168 }
169
170 void ref() const & {
171 // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: method 'ref' can be made static
172 return;
173 }
174 void refref() const && {
175 // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: method 'refref' can be made static
176 return;
177 }
178
179 void restr() __restrict {
180 // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: method 'restr' can be made static
181 return;
182 }
183};
184
185struct UnevaluatedContext {
186 void f() { sizeof(this); }
187
188 void noex() noexcept(noexcept(this));
189};
190
191struct LambdaCapturesThis {
192 int Field;
193
194 int explicitCapture() {
195 return [this]() { return Field; }();
196 }
197
198 int implicitCapture() {
199 return [&]() { return Field; }();
200 }
201};
202
203struct NoFixitInMacro {
204#define CONST const
205 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
211 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

source code of clang-tools-extra/test/clang-tidy/checkers/readability/convert-member-functions-to-static.cpp