1// RUN: %check_clang_tidy %s readability-make-member-function-const %t
2
3struct Str {
4 void const_method() const;
5 void non_const_method();
6};
7
8namespace Diagnose {
9struct A;
10
11void free_const_use(const A *);
12void free_const_use(const A &);
13
14struct A {
15 int M;
16 const int ConstM;
17 struct {
18 int M;
19 } Struct;
20 Str S;
21 Str &Sref;
22
23 void already_const() const;
24
25 int read_field() {
26 // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: method 'read_field' can be made const
27 // CHECK-FIXES: {{^}} int read_field() const {
28 return M;
29 }
30
31 int read_struct_field() {
32 // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: method 'read_struct_field' can be made const
33 // CHECK-FIXES: {{^}} int read_struct_field() const {
34 return Struct.M;
35 }
36
37 int read_const_field() {
38 // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: method 'read_const_field' can be made const
39 // CHECK-FIXES: {{^}} int read_const_field() const {
40 return ConstM;
41 }
42
43 int read_fields_in_parentheses() {
44 // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: method 'read_fields_in_parentheses' can be made const
45 // CHECK-FIXES: {{^}} int read_fields_in_parentheses() const {
46 return (this)->M + (((((Struct.M))))) + ((this->ConstM));
47 }
48
49 void call_const_member() {
50 // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: method 'call_const_member' can be made const
51 // CHECK-FIXES: {{^}} void call_const_member() const {
52 already_const();
53 }
54
55 void call_const_member_on_public_field() {
56 // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: method 'call_const_member_on_public_field' can be made const
57 // CHECK-FIXES: {{^}} void call_const_member_on_public_field() const {
58 S.const_method();
59 }
60
61 void call_const_member_on_public_field_ref() {
62 // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: method 'call_const_member_on_public_field_ref' can be made const
63 // CHECK-FIXES: {{^}} void call_const_member_on_public_field_ref() const {
64 Sref.const_method();
65 }
66
67 const Str &return_public_field_ref() {
68 // CHECK-MESSAGES: :[[@LINE-1]]:14: warning: method 'return_public_field_ref' can be made const
69 // CHECK-FIXES: {{^}} const Str &return_public_field_ref() const {
70 return S;
71 }
72
73 const A *return_this_const() {
74 // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: method 'return_this_const' can be made const
75 // CHECK-FIXES: {{^}} const A *return_this_const() const {
76 return this;
77 }
78
79 const A &return_this_const_ref() {
80 // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: method 'return_this_const_ref' can be made const
81 // CHECK-FIXES: {{^}} const A &return_this_const_ref() const {
82 return *this;
83 }
84
85 void const_use() {
86 // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: method 'const_use' can be made const
87 // CHECK-FIXES: {{^}} void const_use() const {
88 free_const_use(this);
89 }
90
91 void const_use_ref() {
92 // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: method 'const_use_ref' can be made const
93 // CHECK-FIXES: {{^}} void const_use_ref() const {
94 free_const_use(*this);
95 }
96
97 auto trailingReturn() -> int {
98 // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: method 'trailingReturn' can be made const
99 // CHECK-FIXES: {{^}} auto trailingReturn() const -> int {
100 return M;
101 }
102
103 int volatileFunction() volatile {
104 // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: method 'volatileFunction' can be made const
105 // CHECK-FIXES: {{^}} int volatileFunction() const volatile {
106 return M;
107 }
108
109 int restrictFunction() __restrict {
110 // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: method 'restrictFunction' can be made const
111 // CHECK-FIXES: {{^}} int restrictFunction() const __restrict {
112 return M;
113 }
114
115 int refFunction() & {
116 // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: method 'refFunction' can be made const
117 // CHECK-FIXES: {{^}} int refFunction() const & {
118 return M;
119 }
120
121 void out_of_line_call_const();
122 // CHECK-FIXES: {{^}} void out_of_line_call_const() const;
123};
124
125void A::out_of_line_call_const() {
126 // CHECK-MESSAGES: :[[@LINE-1]]:9: warning: method 'out_of_line_call_const' can be made const
127 // CHECK-FIXES: {{^}}void A::out_of_line_call_const() const {
128 already_const();
129}
130} // namespace Diagnose
131
132namespace Keep {
133struct Keep;
134void free_non_const_use(Keep *);
135void free_non_const_use(Keep &);
136
137struct Keep {
138private:
139 void private_const_method() const;
140 Str PrivateS;
141 Str *Sptr;
142 Str &Sref;
143
144public:
145 int M;
146 Str S;
147
148 void keepTrivial() {}
149
150 // See readability-convert-member-functions-to-static instead.
151 void keepStatic() { int I = 0; }
152
153 const int *keepConstCast() const;
154 int *keepConstCast() { // Needs to stay non-const.
155 return const_cast<int *>(static_cast<const Keep *>(this)->keepConstCast());
156 }
157
158 void non_const_use() { free_non_const_use(this); }
159 void non_const_use_ref() { free_non_const_use(*this); }
160
161 Keep *return_this() {
162 return this;
163 }
164
165 Keep &return_this_ref() {
166 return *this;
167 }
168
169 void escape_this() {
170 Keep *Escaped = this;
171 }
172
173 void call_private_const_method() {
174 private_const_method();
175 }
176
177 int keepConst() const { return M; }
178
179 virtual int keepVirtual() { return M; }
180
181 void writeField() {
182 M = 1;
183 }
184
185 void callNonConstMember() { writeField(); }
186
187 void call_non_const_member_on_field() { S.non_const_method(); }
188
189 void call_const_member_on_private_field() {
190 // Technically, this method could be const-qualified,
191 // but it might not be logically const.
192 PrivateS.const_method();
193 }
194
195 const Str &return_private_field_ref() {
196 // Technically, this method could be const-qualified,
197 // but it might not be logically const.
198 return PrivateS;
199 }
200
201 void call_non_const_member_on_pointee() {
202 Sptr->non_const_method();
203 }
204
205 void call_const_member_on_pointee() {
206 // Technically, this method could be const-qualified,
207 // but it might not be logically const.
208 Sptr->const_method();
209 }
210
211 Str *return_pointer() {
212 // Technically, this method could be const-qualified,
213 // but it might not be logically const.
214 return Sptr;
215 }
216
217 const Str *return_const_pointer() {
218 // Technically, this method could be const-qualified,
219 // but it might not be logically const.
220 return Sptr;
221 }
222
223 void call_non_const_member_on_ref() {
224 Sref.non_const_method();
225 }
226
227 void escaped_private_field() {
228 const auto &Escaped = Sref;
229 }
230
231 Str &return_field_ref() {
232 // Technically, this method could be const-qualified,
233 // but it might not be logically const.
234 return Sref;
235 }
236
237 const Str &return_field_const_ref() {
238 // Technically, this method could be const-qualified,
239 // but it might not be logically const.
240 return Sref;
241 }
242};
243
244struct KeepVirtualDerived : public Keep {
245 int keepVirtual() { return M; }
246};
247
248void KeepLambdas() {
249 auto F = +[]() { return 0; };
250 auto F2 = []() { return 0; };
251}
252
253template <class Base>
254struct KeepWithDependentBase : public Base {
255 int M;
256 // We cannot make this method const because it might need to override
257 // a function from Base.
258 int const_f() { return M; }
259};
260
261template <class T>
262struct KeepClassTemplate {
263 int M;
264 // We cannot make this method const because a specialization
265 // might use *this differently.
266 int const_f() { return M; }
267};
268
269struct KeepMemberFunctionTemplate {
270 int M;
271 // We cannot make this method const because a specialization
272 // might use *this differently.
273 template <class T>
274 int const_f() { return M; }
275};
276
277void instantiate() {
278 struct S {};
279 KeepWithDependentBase<S> I1;
280 I1.const_f();
281
282 KeepClassTemplate<int> I2;
283 I2.const_f();
284
285 KeepMemberFunctionTemplate I3;
286 I3.const_f<int>();
287}
288
289struct NoFixitInMacro {
290 int M;
291
292#define FUN const_use_macro()
293 int FUN {
294 return M;
295 }
296
297#define T(FunctionName, Keyword) \
298 int FunctionName() Keyword { return M; }
299#define EMPTY
300 T(A, EMPTY)
301 T(B, const)
302
303#define T2(FunctionName) \
304 int FunctionName() { return M; }
305 T2(A2)
306};
307
308// Real-world code, see clang::ObjCInterfaceDecl.
309class DataPattern {
310 int &data() const;
311
312public:
313 const int &get() const {
314 return const_cast<DataPattern *>(this)->get();
315 }
316
317 // This member function must stay non-const, even though
318 // it only calls other private const member functions.
319 int &get() {
320 return data();
321 }
322
323 void set() {
324 data() = 42;
325 }
326};
327
328struct MemberFunctionPointer {
329 void call_non_const(void (MemberFunctionPointer::*FP)()) {
330 (this->*FP)();
331 }
332
333 void call_const(void (MemberFunctionPointer::*FP)() const) {
334 (this->*FP)();
335 }
336};
337
338} // namespace Keep
339

source code of clang-tools-extra/test/clang-tidy/checkers/readability/make-member-function-const.cpp