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 | } |
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 | |
84 | int A::out_of_line_already_static() { return 0; } |
85 | |
86 | void 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 | |
92 | int 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 { |
99 | virtual int f() { return 0; } |
100 | virtual int h() const { return 0; } |
101 | }; |
102 | |
103 | struct 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. |
109 | struct KeepSpecial { |
110 | KeepSpecial() { int L = 0; } |
111 | ~KeepSpecial() { int L = 0; } |
112 | int operator+() { return 0; } |
113 | operator int() { return 0; } |
114 | }; |
115 | |
116 | void 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. |
127 | 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. |
135 | 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> |
143 | static int static_f() { return 0; } |
144 | }; |
145 | |
146 | void 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 { |
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 | |
185 | struct UnevaluatedContext { |
186 | void f() { sizeof(this); } |
187 | |
188 | void noex() noexcept(noexcept(this)); |
189 | }; |
190 | |
191 | struct 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 | |
203 | struct 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 | |