1 | // RUN: %check_clang_tidy %s readability-convert-member-functions-to-static %t |
2 | |
3 | class DoNotMakeEmptyStatic { |
4 | void emptyMethod() {} |
5 | void empty_method_out_of_line(); |
6 | }; |
7 | |
8 | void DoNotMakeEmptyStatic::empty_method_out_of_line() {} |
9 | |
10 | class 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 | return 0; |
36 | } |
37 | |
38 | int read_static() { |
39 | // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: method 'read_static' can be made static |
40 | // 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 static |
45 | // 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 static |
51 | // 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 static |
73 | // 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 | |
85 | int A::out_of_line_already_static() { return 0; } |
86 | |
87 | void A::out_of_line_call_static() { |
88 | // CHECK-MESSAGES: :[[@LINE-1]]:9: warning: method 'out_of_line_call_static' can be made static |
89 | // CHECK-FIXES: {{^}}void A::out_of_line_call_static() { |
90 | already_static(); |
91 | } |
92 | |
93 | int 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 static |
95 | // CHECK-FIXES: {{^}}int A::out_of_line_const_to_static() { |
96 | return 0; |
97 | } |
98 | |
99 | struct KeepVirtual { |
100 | virtual int f() { return 0; } |
101 | virtual int h() const { return 0; } |
102 | }; |
103 | |
104 | struct 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. |
110 | struct KeepSpecial { |
111 | KeepSpecial() { int L = 0; } |
112 | ~KeepSpecial() { int L = 0; } |
113 | int operator+() { return 0; } |
114 | operator int() { return 0; } |
115 | }; |
116 | |
117 | void KeepLambdas() { |
118 | using FT = int (*)(); |
119 | auto F = static_cast<FT>([]() { return 0; }); |
120 | auto F2 = []() { return 0; }; |
121 | } |
122 | |
123 | template <class Base> |
124 | struct KeepWithTemplateBase : public Base { |
125 | int i; |
126 | // We cannot make these methods static because they might need to override |
127 | // a function from Base. |
128 | int static_f() { return 0; } |
129 | }; |
130 | |
131 | template <class T> |
132 | struct KeepTemplateClass { |
133 | int i; |
134 | // We cannot make these methods static because a specialization |
135 | // might use *this differently. |
136 | int static_f() { return 0; } |
137 | }; |
138 | |
139 | struct KeepTemplateMethod { |
140 | int i; |
141 | // We cannot make these methods static because a specialization |
142 | // might use *this differently. |
143 | template <class T> |
144 | static int static_f() { return 0; } |
145 | }; |
146 | |
147 | void 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 | |
159 | struct Trailing { |
160 | auto g() const -> int { |
161 | // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: method 'g' can be made static |
162 | // 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 static |
168 | return; |
169 | } |
170 | |
171 | void ref() const & { |
172 | // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: method 'ref' can be made static |
173 | return; |
174 | } |
175 | void refref() const && { |
176 | // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: method 'refref' can be made static |
177 | return; |
178 | } |
179 | |
180 | void restr() __restrict { |
181 | // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: method 'restr' can be made static |
182 | return; |
183 | } |
184 | }; |
185 | |
186 | struct UnevaluatedContext { |
187 | void f() { sizeof(this); } |
188 | |
189 | void noex() noexcept(noexcept(this)); |
190 | }; |
191 | |
192 | struct 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 | |
204 | struct NoFixitInMacro { |
205 | #define CONST const |
206 | int no_use_macro_const() CONST { |
207 | // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: method 'no_use_macro_const' can be made static |
208 | return 0; |
209 | } |
210 | |
211 | #define ADD_CONST(F) F const |
212 | 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 EMPTY |
225 | T(A, EMPTY) |
226 | T(B, static) |
227 | |
228 | #define T2(FunctionName) \ |
229 | int FunctionName() { return 0; } |
230 | T2(A2) |
231 | |
232 | #define VOLATILE volatile |
233 | void volatileMacro() VOLATILE { |
234 | // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: method 'volatileMacro' can be made static |
235 | return; |
236 | } |
237 | }; |
238 | |