1// RUN: %check_clang_tidy --match-partial-fixes %s misc-const-correctness %t -- \
2// RUN: -config="{CheckOptions: {\
3// RUN: misc-const-correctness.TransformValues: true, \
4// RUN: misc-const-correctness.WarnPointersAsValues: false, \
5// RUN: misc-const-correctness.WarnPointersAsPointers: false, \
6// RUN: misc-const-correctness.TransformPointersAsValues: false \
7// RUN: }}" -- -fno-delayed-template-parsing -fexceptions
8
9// ------- Provide test samples for primitive builtins ---------
10// - every 'p_*' variable is a 'potential_const_*' variable
11// - every 'np_*' variable is a 'non_potential_const_*' variable
12
13bool global;
14char np_global = 0; // globals can't be known to be const
15
16// FIXME: 'static' globals are not matched right now. They could be analyzed but aren't right now.
17static int p_static_global = 42;
18
19namespace foo {
20int scoped;
21float np_scoped = 1; // namespace variables are like globals
22} // namespace foo
23
24// FIXME: Similary to 'static' globals, anonymous globals are not matched and analyzed.
25namespace {
26int np_anonymous_global;
27int p_anonymous_global = 43;
28} // namespace
29
30// Lambdas should be ignored, because they do not follow the normal variable
31// semantic (e.g. the type is only known to the compiler).
32void lambdas() {
33 auto Lambda = [](int i) { return i < 0; };
34}
35
36void some_function(double, wchar_t);
37
38void some_function(double np_arg0, wchar_t np_arg1) {
39 int p_local0 = 2;
40 // CHECK-MESSAGES: [[@LINE-1]]:3: warning: variable 'p_local0' of type 'int' can be declared 'const'
41 // CHECK-FIXES: int const p_local0
42
43 int np_local0;
44 const int np_local1 = 42;
45
46 unsigned int np_local2 = 3;
47 np_local2 <<= 4;
48
49 int np_local3 = 4;
50 ++np_local3;
51 int np_local4 = 4;
52 np_local4++;
53
54 int np_local5 = 4;
55 --np_local5;
56 int np_local6 = 4;
57 np_local6--;
58}
59
60int function_try_block() try {
61 int p_local0 = 0;
62 // CHECK-MESSAGES: [[@LINE-1]]:3: warning: variable 'p_local0' of type 'int' can be declared 'const'
63 // CHECK-FIXES: int const p_local0
64 return p_local0;
65} catch (...) {
66 return 0;
67}
68
69void nested_scopes() {
70 int p_local0 = 2;
71 // CHECK-MESSAGES: [[@LINE-1]]:3: warning: variable 'p_local0' of type 'int' can be declared 'const'
72 // CHECK-FIXES: int const p_local0
73 int np_local0 = 42;
74
75 {
76 int p_local1 = 42;
77 // CHECK-MESSAGES: [[@LINE-1]]:5: warning: variable 'p_local1' of type 'int' can be declared 'const'
78 // CHECK-FIXES: int const p_local1
79 np_local0 *= 2;
80 }
81}
82
83void ignore_reference_to_pointers() {
84 int *np_local0 = nullptr;
85 int *&np_local1 = np_local0;
86}
87
88void some_lambda_environment_capture_all_by_reference(double np_arg0) {
89 int np_local0 = 0;
90 int p_local0 = 1;
91 // CHECK-MESSAGES: [[@LINE-1]]:3: warning: variable 'p_local0' of type 'int' can be declared 'const'
92 // CHECK-FIXES: int const p_local0
93
94 int np_local2;
95 const int np_local3 = 2;
96
97 // Capturing all variables by reference prohibits making them const.
98 [&]() { ++np_local0; };
99
100 int p_local1 = 0;
101 // CHECK-MESSAGES: [[@LINE-1]]:3: warning: variable 'p_local1' of type 'int' can be declared 'const'
102 // CHECK-FIXES: int const p_local1
103}
104
105void some_lambda_environment_capture_all_by_value(double np_arg0) {
106 int np_local0 = 0;
107 int p_local0 = 1;
108 // CHECK-MESSAGES: [[@LINE-1]]:3: warning: variable 'p_local0' of type 'int' can be declared 'const'
109 // CHECK-FIXES: int const p_local0
110
111 int np_local1;
112 const int np_local2 = 2;
113
114 // Capturing by value has no influence on them.
115 [=]() { (void)p_local0; };
116
117 np_local0 += 10;
118}
119
120void function_inout_pointer(int *inout);
121void function_in_pointer(const int *in);
122
123void some_pointer_taking(int *out) {
124 int np_local0 = 42;
125 const int *const p0_np_local0 = &np_local0;
126 int *const p1_np_local0 = &np_local0;
127
128 int np_local1 = 42;
129 const int *const p0_np_local1 = &np_local1;
130 int *const p1_np_local1 = &np_local1;
131 *p1_np_local0 = 43;
132
133 int np_local2 = 42;
134 function_inout_pointer(inout: &np_local2);
135
136 // Prevents const.
137 int np_local3 = 42;
138 out = &np_local3; // This returns and invalid address, its just about the AST
139
140 int p_local1 = 42;
141 // CHECK-MESSAGES: [[@LINE-1]]:3: warning: variable 'p_local1' of type 'int' can be declared 'const'
142 // CHECK-FIXES: int const p_local1
143 const int *const p0_p_local1 = &p_local1;
144
145 int p_local2 = 42;
146 // CHECK-MESSAGES: [[@LINE-1]]:3: warning: variable 'p_local2' of type 'int' can be declared 'const'
147 // CHECK-FIXES: int const p_local2
148 function_in_pointer(in: &p_local2);
149}
150
151void function_inout_ref(int &inout);
152void function_in_ref(const int &in);
153
154void some_reference_taking() {
155 int np_local0 = 42;
156 const int &r0_np_local0 = np_local0;
157 int &r1_np_local0 = np_local0;
158 r1_np_local0 = 43;
159 const int &r2_np_local0 = r1_np_local0;
160
161 int np_local1 = 42;
162 function_inout_ref(inout&: np_local1);
163
164 int p_local0 = 42;
165 // CHECK-MESSAGES: [[@LINE-1]]:3: warning: variable 'p_local0' of type 'int' can be declared 'const'
166 // CHECK-FIXES: int const p_local0
167 const int &r0_p_local0 = p_local0;
168
169 int p_local1 = 42;
170 // CHECK-MESSAGES: [[@LINE-1]]:3: warning: variable 'p_local1' of type 'int' can be declared 'const'
171 // CHECK-FIXES: int const p_local1
172 function_in_ref(in: p_local1);
173}
174
175double *non_const_pointer_return() {
176 double p_local0 = 0.0;
177 // CHECK-MESSAGES: [[@LINE-1]]:3: warning: variable 'p_local0' of type 'double' can be declared 'const'
178 // CHECK-FIXES: double const p_local0
179 double np_local0 = 24.4;
180
181 return &np_local0;
182}
183
184const double *const_pointer_return() {
185 double p_local0 = 0.0;
186 // CHECK-MESSAGES: [[@LINE-1]]:3: warning: variable 'p_local0' of type 'double' can be declared 'const'
187 // CHECK-FIXES: double const p_local0
188 double p_local1 = 24.4;
189 // CHECK-MESSAGES: [[@LINE-1]]:3: warning: variable 'p_local1' of type 'double' can be declared 'const'
190 // CHECK-FIXES: double const p_local1
191 return &p_local1;
192}
193
194// Also see const-correctness-values.cpp-before-cxx23.cpp for `non_const_ref_return` and `return_non_const_pointer_ref`
195const double &const_ref_return() {
196 double p_local0 = 0.0;
197 // CHECK-MESSAGES: [[@LINE-1]]:3: warning: variable 'p_local0' of type 'double' can be declared 'const'
198 // CHECK-FIXES: double const p_local0
199 double p_local1 = 24.4;
200 // CHECK-MESSAGES: [[@LINE-1]]:3: warning: variable 'p_local1' of type 'double' can be declared 'const'
201 // CHECK-FIXES: double const p_local1
202 return p_local1;
203}
204
205void overloaded_arguments(const int &in);
206void overloaded_arguments(int &inout);
207void overloaded_arguments(const int *in);
208void overloaded_arguments(int *inout);
209
210void function_calling() {
211 int np_local0 = 42;
212 overloaded_arguments(inout&: np_local0);
213
214 const int np_local1 = 42;
215 overloaded_arguments(in: np_local1);
216
217 int np_local2 = 42;
218 overloaded_arguments(inout: &np_local2);
219
220 const int np_local3 = 42;
221 overloaded_arguments(in: &np_local3);
222}
223
224template <typename T>
225void define_locals(T np_arg0, T &np_arg1, int np_arg2) {
226 T np_local0 = 0;
227 np_local0 += np_arg0 * np_arg1;
228
229 T np_local1 = 42;
230 np_local0 += np_local1;
231
232 // Used as argument to an overloaded function with const and non-const.
233 T np_local2 = 42;
234 overloaded_arguments(np_local2);
235
236 int np_local4 = 42;
237 // non-template values are ok still.
238 int p_local0 = 42;
239 // CHECK-MESSAGES: [[@LINE-1]]:3: warning: variable 'p_local0' of type 'int' can be declared 'const'
240 // CHECK-FIXES: int const p_local0
241 np_local4 += p_local0;
242}
243
244template <typename T>
245void more_template_locals() {
246 const T np_local0 = {};
247 auto np_local1 = T{};
248 T &np_local2 = np_local1;
249 T *np_local_ptr = &np_local1;
250
251 const auto np_local3 = T{};
252 // FIXME: False positive, the reference points to a template type and needs
253 // to be excluded from analysis, but somehow isn't (matchers don't work)
254 auto &np_local4 = np_local3;
255
256 const auto *np_local5 = &np_local3;
257 auto *np_local6 = &np_local1;
258
259 using TypedefToTemplate = T;
260 TypedefToTemplate np_local7{};
261 // FIXME: False positive, the reference points to a template type and needs
262 // to be excluded from analysis, but somehow isn't (matchers don't work)
263 // auto &np_local8 = np_local7;
264 const auto &np_local9 = np_local7;
265 auto np_local10 = np_local7;
266 auto *np_local11 = &np_local10;
267 const auto *const np_local12 = &np_local10;
268
269 // FIXME: False positive, the reference points to a template type and needs
270 // to be excluded from analysis, but somehow isn't (matchers don't work)
271 // TypedefToTemplate &np_local13 = np_local7;
272 TypedefToTemplate *np_local14 = &np_local7;
273}
274
275void template_instantiation() {
276 const int np_local0 = 42;
277 int np_local1 = 42;
278
279 define_locals(np_arg0: np_local0, np_arg1&: np_local1, np_arg2: np_local0);
280 define_locals(np_arg0: np_local1, np_arg1&: np_local1, np_arg2: np_local1);
281 more_template_locals<int>();
282}
283
284struct ConstNonConstClass {
285 ConstNonConstClass();
286 ConstNonConstClass(double &np_local0);
287 double nonConstMethod() { return 0; }
288 double constMethod() const { return 0; }
289 double modifyingMethod(double &np_arg0) const;
290
291 double NonConstMember;
292 const double ConstMember;
293
294 double &NonConstMemberRef;
295 const double &ConstMemberRef;
296
297 double *NonConstMemberPtr;
298 const double *ConstMemberPtr;
299};
300
301void direct_class_access() {
302 ConstNonConstClass np_local0;
303
304 np_local0.constMethod();
305 np_local0.nonConstMethod();
306
307 ConstNonConstClass p_local0;
308 // CHECK-MESSAGES: [[@LINE-1]]:3: warning: variable 'p_local0' of type 'ConstNonConstClass' can be declared 'const'
309 // CHECK-FIXES: ConstNonConstClass const p_local0
310 p_local0.constMethod();
311
312 ConstNonConstClass p_local1;
313 // CHECK-MESSAGES: [[@LINE-1]]:3: warning: variable 'p_local1' of type 'ConstNonConstClass' can be declared 'const'
314 // CHECK-FIXES: ConstNonConstClass const p_local1
315 double np_local1;
316 p_local1.modifyingMethod(np_arg0&: np_local1);
317
318 double np_local2;
319 ConstNonConstClass p_local2(np_local2);
320 // CHECK-MESSAGES: [[@LINE-1]]:3: warning: variable 'p_local2' of type 'ConstNonConstClass' can be declared 'const'
321 // CHECK-FIXES: ConstNonConstClass const p_local2(np_local2)
322
323 ConstNonConstClass np_local3;
324 np_local3.NonConstMember = 42.;
325
326 ConstNonConstClass np_local4;
327 np_local4.NonConstMemberRef = 42.;
328
329 ConstNonConstClass p_local3;
330 // CHECK-MESSAGES: [[@LINE-1]]:3: warning: variable 'p_local3' of type 'ConstNonConstClass' can be declared 'const'
331 // CHECK-FIXES: ConstNonConstClass const p_local3
332 const double val0 = p_local3.NonConstMember;
333 const double val1 = p_local3.NonConstMemberRef;
334 const double val2 = *p_local3.NonConstMemberPtr;
335
336 ConstNonConstClass p_local4;
337 // CHECK-MESSAGES: [[@LINE-1]]:3: warning: variable 'p_local4' of type 'ConstNonConstClass' can be declared 'const'
338 // CHECK-FIXES: ConstNonConstClass const p_local4
339 *np_local4.NonConstMemberPtr = 42.;
340}
341
342void class_access_array() {
343 ConstNonConstClass np_local0[2];
344 np_local0[0].constMethod();
345 np_local0[1].constMethod();
346 np_local0[1].nonConstMethod();
347
348 ConstNonConstClass p_local0[2];
349 // CHECK-MESSAGES: [[@LINE-1]]:3: warning: variable 'p_local0' of type 'ConstNonConstClass[2]' can be declared 'const'
350 // CHECK-FIXES: ConstNonConstClass const p_local0[2]
351 p_local0[0].constMethod();
352 np_local0[1].constMethod();
353}
354
355struct OperatorsAsConstAsPossible {
356 OperatorsAsConstAsPossible &operator+=(const OperatorsAsConstAsPossible &rhs);
357 OperatorsAsConstAsPossible operator+(const OperatorsAsConstAsPossible &rhs) const;
358};
359
360struct NonConstOperators {
361};
362NonConstOperators operator+(NonConstOperators &lhs, NonConstOperators &rhs);
363NonConstOperators operator-(NonConstOperators lhs, NonConstOperators rhs);
364
365void internal_operator_calls() {
366 OperatorsAsConstAsPossible np_local0;
367 OperatorsAsConstAsPossible np_local1;
368 OperatorsAsConstAsPossible p_local0;
369 // CHECK-MESSAGES: [[@LINE-1]]:3: warning: variable 'p_local0' of type 'OperatorsAsConstAsPossible' can be declared 'const'
370 // CHECK-FIXES: OperatorsAsConstAsPossible const p_local0
371 OperatorsAsConstAsPossible p_local1;
372 // CHECK-MESSAGES: [[@LINE-1]]:3: warning: variable 'p_local1' of type 'OperatorsAsConstAsPossible' can be declared 'const'
373 // CHECK-FIXES: OperatorsAsConstAsPossible const p_local1
374
375 np_local0 += p_local0;
376 np_local1 = p_local0 + p_local1;
377
378 NonConstOperators np_local2;
379 NonConstOperators np_local3;
380 NonConstOperators np_local4;
381
382 np_local2 = np_local3 + np_local4;
383
384 NonConstOperators p_local2;
385 // CHECK-MESSAGES: [[@LINE-1]]:3: warning: variable 'p_local2' of type 'NonConstOperators' can be declared 'const'
386 // CHECK-FIXES: NonConstOperators const p_local2
387 NonConstOperators p_local3 = p_local2 - p_local2;
388 // CHECK-MESSAGES: [[@LINE-1]]:3: warning: variable 'p_local3' of type 'NonConstOperators' can be declared 'const'
389 // CHECK-FIXES: NonConstOperators const p_local3
390}
391
392struct MyVector {
393 double *begin();
394 const double *begin() const;
395
396 double *end();
397 const double *end() const;
398
399 double &operator[](int index);
400 double operator[](int index) const;
401
402 double values[100];
403};
404
405void vector_usage() {
406 double np_local0[10];
407 np_local0[5] = 42.;
408
409 MyVector np_local1;
410 np_local1[5] = 42.;
411
412 double p_local0[10] = {0., 1., 2., 3., 4., 5., 6., 7., 8., 9.};
413 // CHECK-MESSAGES: [[@LINE-1]]:3: warning: variable 'p_local0' of type 'double[10]' can be declared 'const'
414 // CHECK-FIXES: double const p_local0[10]
415 double p_local1 = p_local0[5];
416 // CHECK-MESSAGES: [[@LINE-1]]:3: warning: variable 'p_local1' of type 'double' can be declared 'const'
417 // CHECK-FIXES: double const p_local1
418
419 // The following subscript calls suprisingly choose the non-const operator
420 // version.
421 MyVector np_local2;
422 double p_local2 = np_local2[42];
423 // CHECK-MESSAGES: [[@LINE-1]]:3: warning: variable 'p_local2' of type 'double' can be declared 'const'
424 // CHECK-FIXES: double const p_local2
425
426 MyVector np_local3;
427 const double np_local4 = np_local3[42];
428
429 // This subscript results in const overloaded operator.
430 const MyVector np_local5{};
431 double p_local3 = np_local5[42];
432 // CHECK-MESSAGES: [[@LINE-1]]:3: warning: variable 'p_local3' of type 'double' can be declared 'const'
433 // CHECK-FIXES: double const p_local3
434}
435
436void const_handle(const double &np_local0);
437void const_handle(const double *np_local0);
438
439void non_const_handle(double &np_local0);
440void non_const_handle(double *np_local0);
441
442void handle_from_array() {
443 // Non-const handle from non-const array forbids declaring the array as const
444 double np_local0[10] = {0., 1., 2., 3., 4., 5., 6., 7., 8., 9.};
445 double *p_local0 = &np_local0[1]; // Could be `double *const`, but warning deactivated by default
446
447 double np_local1[10] = {0., 1., 2., 3., 4., 5., 6., 7., 8., 9.};
448 double &non_const_ref = np_local1[1];
449 non_const_ref = 42.;
450
451 double np_local2[10] = {0., 1., 2., 3., 4., 5., 6., 7., 8., 9.};
452 double *np_local3;
453 np_local3 = &np_local2[5];
454
455 double np_local4[10] = {0., 1., 2., 3., 4., 5., 6., 7., 8., 9.};
456 non_const_handle(np_local0&: np_local4[2]);
457 double np_local5[10] = {0., 1., 2., 3., 4., 5., 6., 7., 8., 9.};
458 non_const_handle(np_local0: &np_local5[2]);
459
460 // Constant handles are ok
461 double p_local1[10] = {0., 1., 2., 3., 4., 5., 6., 7., 8., 9.};
462 // CHECK-MESSAGES: [[@LINE-1]]:3: warning: variable 'p_local1' of type 'double[10]' can be declared 'const'
463 // CHECK-FIXES: double const p_local1[10]
464 const double *p_local2 = &p_local1[2]; // Could be `const double *const`, but warning deactivated by default
465
466 double p_local3[10] = {0., 1., 2., 3., 4., 5., 6., 7., 8., 9.};
467 // CHECK-MESSAGES: [[@LINE-1]]:3: warning: variable 'p_local3' of type 'double[10]' can be declared 'const'
468 // CHECK-FIXES: double const p_local3[10]
469 const double &const_ref = p_local3[2];
470
471 double p_local4[10] = {0., 1., 2., 3., 4., 5., 6., 7., 8., 9.};
472 // CHECK-MESSAGES: [[@LINE-1]]:3: warning: variable 'p_local4' of type 'double[10]' can be declared 'const'
473 // CHECK-FIXES: double const p_local4[10]
474 const double *const_ptr;
475 const_ptr = &p_local4[2];
476
477 double p_local5[10] = {0., 1., 2., 3., 4., 5., 6., 7., 8., 9.};
478 // CHECK-MESSAGES: [[@LINE-1]]:3: warning: variable 'p_local5' of type 'double[10]' can be declared 'const'
479 // CHECK-FIXES: double const p_local5[10]
480 const_handle(np_local0: p_local5[2]);
481 double p_local6[10] = {0., 1., 2., 3., 4., 5., 6., 7., 8., 9.};
482 // CHECK-MESSAGES: [[@LINE-1]]:3: warning: variable 'p_local6' of type 'double[10]' can be declared 'const'
483 // CHECK-FIXES: double const p_local6[10]
484 const_handle(np_local0: &p_local6[2]);
485}
486
487void range_for() {
488 int np_local0[2] = {1, 2};
489 for (int &non_const_ref : np_local0) {
490 non_const_ref = 42;
491 }
492
493 int np_local1[2] = {1, 2};
494 for (auto &non_const_ref : np_local1) {
495 non_const_ref = 43;
496 }
497
498 int np_local2[2] = {1, 2};
499 for (auto &&non_const_ref : np_local2) {
500 non_const_ref = 44;
501 }
502
503 int *np_local3[2] = {&np_local0[0], &np_local0[1]};
504 for (int *non_const_ptr : np_local3) {
505 *non_const_ptr = 45;
506 }
507
508 // FIXME same as above, but silenced
509 int *const np_local4[2] = {&np_local0[0], &np_local0[1]};
510 for (auto *non_const_ptr : np_local4) {
511 *non_const_ptr = 46;
512 }
513
514 int p_local0[2] = {1, 2};
515 // CHECK-MESSAGES: [[@LINE-1]]:3: warning: variable 'p_local0' of type 'int[2]' can be declared 'const'
516 // CHECK-FIXES: int const p_local0[2]
517 for (int value : p_local0) {
518 // CHECK-MESSAGES: [[@LINE-1]]:8: warning: variable 'value' of type 'int' can be declared 'const'
519 // CHECK-FIXES: int const value
520 }
521
522 int p_local1[2] = {1, 2};
523 // CHECK-MESSAGES: [[@LINE-1]]:3: warning: variable 'p_local1' of type 'int[2]' can be declared 'const'
524 // CHECK-FIXES: int const p_local1[2]
525 for (const int &const_ref : p_local1) {
526 }
527}
528
529void arrays_of_pointers_are_ignored() {
530 int *np_local0[2] = {nullptr, nullptr};
531
532 using intPtr = int*;
533 intPtr np_local1[2] = {nullptr, nullptr};
534}
535
536inline void *operator new(decltype(sizeof(void *)), void *p) { return p; }
537
538struct Value {
539};
540void placement_new() {
541 Value Mem;
542 Value *V = new (&Mem) Value;
543}
544
545struct ModifyingConversion {
546 operator int() { return 15; }
547};
548struct NonModifyingConversion {
549 operator int() const { return 15; }
550};
551void conversion_operators() {
552 ModifyingConversion np_local0;
553 NonModifyingConversion p_local0;
554 // CHECK-MESSAGES: [[@LINE-1]]:3: warning: variable 'p_local0' of type 'NonModifyingConversion' can be declared 'const'
555 // CHECK-FIXES: NonModifyingConversion const p_local0
556
557 int np_local1 = np_local0;
558 np_local1 = p_local0;
559}
560
561void casts() {
562 decltype(sizeof(void *)) p_local0 = 42;
563 // CHECK-MESSAGES: [[@LINE-1]]:3: warning: variable 'p_local0' of type 'decltype(sizeof(void *))'
564 // CHECK-FIXES: decltype(sizeof(void *)) const p_local0
565 auto np_local0 = reinterpret_cast<void *>(p_local0);
566 np_local0 = nullptr;
567
568 int p_local1 = 43;
569 // CHECK-MESSAGES: [[@LINE-1]]:3: warning: variable 'p_local1' of type 'int' can be declared 'const'
570 // CHECK-FIXES: int const p_local1
571 short p_local2 = static_cast<short>(p_local1);
572 // CHECK-MESSAGES: [[@LINE-1]]:3: warning: variable 'p_local2' of type 'short' can be declared 'const'
573 // CHECK-FIXES: short const p_local2
574
575 int np_local1 = p_local2;
576 int &np_local2 = static_cast<int &>(np_local1);
577 np_local2 = 5;
578}
579
580void ternary_operator() {
581 int np_local0 = 1, np_local1 = 2;
582 int &np_local2 = true ? np_local0 : np_local1;
583 np_local2 = 2;
584
585 int p_local0 = 3, np_local3 = 5;
586 // CHECK-MESSAGES: [[@LINE-1]]:3: warning: variable 'p_local0' of type 'int' can be declared 'const'
587 // CHECK-NOT-FIXES: int const p_local0 = 3
588 const int &np_local4 = true ? p_local0 : ++np_local3;
589
590 int np_local5[3] = {1, 2, 3};
591 int &np_local6 = np_local5[1] < np_local5[2] ? np_local5[0] : np_local5[2];
592 np_local6 = 42;
593
594 int np_local7[3] = {1, 2, 3};
595 int *np_local8 = np_local7[1] < np_local7[2] ? &np_local7[0] : &np_local7[2];
596 *np_local8 = 42;
597}
598
599// Taken from libcxx/include/type_traits and improved readability.
600template <class Tp, Tp v>
601struct integral_constant {
602 static constexpr const Tp value = v;
603 using value_type = Tp;
604 using type = integral_constant;
605 constexpr operator value_type() const noexcept { return value; }
606 constexpr value_type operator()() const noexcept { return value; }
607};
608
609template <typename T>
610struct is_integral : integral_constant<bool, false> {};
611template <>
612struct is_integral<int> : integral_constant<bool, true> {};
613
614template <typename T>
615struct not_integral : integral_constant<bool, false> {};
616template <>
617struct not_integral<double> : integral_constant<bool, true> {};
618
619template <bool, typename Tp = void>
620struct enable_if {};
621
622template <typename Tp>
623struct enable_if<true, Tp> { using type = Tp; };
624
625template <typename T>
626struct TMPClass {
627 T alwaysConst() const { return T{}; }
628
629 template <typename T2 = T, typename = typename enable_if<is_integral<T2>::value>::type>
630 T sometimesConst() const { return T{}; }
631
632 template <typename T2 = T, typename = typename enable_if<not_integral<T2>::value>::type>
633 T sometimesConst() { return T{}; }
634};
635
636void meta_type() {
637 TMPClass<int> p_local0;
638 // CHECK-MESSAGES: [[@LINE-1]]:3: warning: variable 'p_local0' of type 'TMPClass<int>' can be declared 'const'
639 // CHECK-FIXES: TMPClass<int> const p_local0
640 p_local0.alwaysConst();
641 p_local0.sometimesConst();
642
643 TMPClass<double> p_local1;
644 // CHECK-MESSAGES: [[@LINE-1]]:3: warning: variable 'p_local1' of type 'TMPClass<double>' can be declared 'const'
645 // CHECK-FIXES: TMPClass<double> const p_local1
646 p_local1.alwaysConst();
647
648 TMPClass<double> np_local0;
649 np_local0.alwaysConst();
650 np_local0.sometimesConst();
651}
652
653// This test is the essence from llvm/lib/Support/MemoryBuffer.cpp at line 450
654template <typename T>
655struct to_construct : T {
656 to_construct(int &j) {}
657};
658template <typename T>
659void placement_new_in_unique_ptr() {
660 int p_local0 = 42;
661 // CHECK-MESSAGES: [[@LINE-1]]:3: warning: variable 'p_local0' of type 'int' can be declared 'const'
662 // CHECK-FIXES: int const p_local0
663 int np_local0 = p_local0;
664 new to_construct<T>(np_local0);
665}
666
667struct stream_obj {};
668stream_obj &operator>>(stream_obj &o, unsigned &foo);
669void input_operator() {
670 stream_obj np_local0;
671 unsigned np_local1 = 42;
672 np_local0 >> np_local1;
673}
674
675struct stream_obj_template {};
676template <typename IStream>
677IStream &operator>>(IStream &o, unsigned &foo);
678
679template <typename Stream>
680void input_operator_template() {
681 Stream np_local0;
682 unsigned np_local1 = 42;
683 np_local0 >> np_local1;
684}
685
686// Test bit fields
687struct HardwareRegister {
688 unsigned field : 5;
689 unsigned : 7;
690 unsigned another : 20;
691};
692
693void TestRegisters() {
694 HardwareRegister np_reg0;
695 np_reg0.field = 3;
696
697 HardwareRegister p_reg1{.field: 3, 22};
698 // CHECK-MESSAGES: [[@LINE-1]]:3: warning: variable 'p_reg1' of type 'HardwareRegister' can be declared 'const'
699 // CHECK-FIXES: HardwareRegister const p_reg1
700 const unsigned p_val = p_reg1.another;
701}
702
703struct IntWrapper {
704 IntWrapper &operator=(unsigned value) { return *this; }
705 template <typename Istream>
706 friend Istream &operator>>(Istream &is, IntWrapper &rhs);
707};
708struct IntMaker {
709 friend IntMaker &operator>>(IntMaker &, unsigned &);
710};
711template <typename Istream>
712Istream &operator>>(Istream &is, IntWrapper &rhs) {
713 unsigned np_local0 = 0;
714 is >> np_local0;
715 return is;
716}
717
718struct Actuator {
719 int actuations;
720};
721struct Sensor {
722 int observations;
723};
724struct System : public Actuator, public Sensor {
725};
726int some_computation(int arg);
727int test_inheritance() {
728 System np_sys;
729 np_sys.actuations = 5;
730 return some_computation(arg: np_sys.actuations);
731}
732struct AnotherActuator : Actuator {
733};
734Actuator &test_return_polymorphic() {
735 static AnotherActuator np_local0;
736 return np_local0;
737}
738
739using f_signature = int *(*)(int &);
740int *my_alloc(int &size) { return new int[size]; }
741struct A {
742 int f(int &i) { return i + 1; }
743 int (A::*x)(int &);
744};
745void f() {
746 int p_local0 = 42;
747 // CHECK-MESSAGES: [[@LINE-1]]:3: warning: variable 'p_local0' of type 'int' can be declared 'const'
748 // CHECK-FIXES: int const p_local0
749 int np_local0 = 42;
750 f_signature action = my_alloc;
751 action(np_local0);
752 my_alloc(size&: np_local0);
753
754 int np_local1 = 42;
755 A a;
756 a.x = &A::f;
757 (a.*(a.x))(np_local1);
758}
759
760struct nested_data {
761 int more_data;
762};
763struct repro_assignment_to_reference {
764 int my_data;
765 nested_data nested;
766};
767void assignment_reference() {
768 repro_assignment_to_reference np_local0{.my_data: 42};
769 int &np_local1 = np_local0.my_data;
770 np_local1++;
771
772 repro_assignment_to_reference np_local2;
773 int &np_local3 = np_local2.nested.more_data;
774 np_local3++;
775}
776
777struct non_const_iterator {
778 int data[42];
779
780 int *begin() { return &data[0]; }
781 int *end() { return &data[41]; }
782};
783
784// The problem is, that 'begin()' and 'end()' are not const overloaded, so
785// they are always a mutation. If 'np_local1' is fixed to const it results in
786// a compilation error.
787void for_bad_iterators() {
788 non_const_iterator np_local0;
789 non_const_iterator &np_local1 = np_local0;
790
791 for (int np_local2 : np_local1) {
792 np_local2++;
793 }
794
795 non_const_iterator np_local3;
796 for (int p_local0 : np_local3)
797 // CHECK-MESSAGES: [[@LINE-1]]:8: warning: variable 'p_local0' of type 'int' can be declared 'const'
798 // CHECK-FIXES: int const p_local0
799 ;
800
801 // Horrible code constructs...
802 {
803 non_const_iterator np_local4;
804 np_local4.data[0]++;
805 non_const_iterator np_local5;
806 for (int p_local1 : np_local4, np_local5)
807 // CHECK-MESSAGES: [[@LINE-1]]:10: warning: variable 'p_local1' of type 'int' can be declared 'const'
808 // CHECK-FIXES: int const p_local1
809 ;
810
811 non_const_iterator np_local6;
812 non_const_iterator np_local7;
813 for (int p_local2 : 1 > 2 ? np_local6 : np_local7)
814 // CHECK-MESSAGES: [[@LINE-1]]:10: warning: variable 'p_local2' of type 'int' can be declared 'const'
815 // CHECK-FIXES: int const p_local2
816 ;
817
818 non_const_iterator np_local8;
819 non_const_iterator np_local9;
820 for (int p_local3 : 2 > 1 ? np_local8 : (np_local8, np_local9))
821 // CHECK-MESSAGES: [[@LINE-1]]:10: warning: variable 'p_local3' of type 'int' can be declared 'const'
822 // CHECK-FIXES: int const p_local3
823 ;
824 }
825}
826
827struct good_iterator {
828 int data[3] = {1, 2, 3};
829
830 int *begin() { return &data[0]; }
831 int *end() { return &data[2]; }
832 const int *begin() const { return &data[0]; }
833 const int *end() const { return &data[2]; }
834};
835
836void good_iterators() {
837 good_iterator p_local0;
838 // CHECK-MESSAGES: [[@LINE-1]]:3: warning: variable 'p_local0' of type 'good_iterator' can be declared 'const'
839 // CHECK-FIXES: good_iterator const p_local0
840 good_iterator &p_local1 = p_local0;
841 // CHECK-MESSAGES: [[@LINE-1]]:3: warning: variable 'p_local1' of type 'good_iterator &' can be declared 'const'
842 // CHECK-FIXES: good_iterator const&p_local1
843
844 for (int p_local2 : p_local1) {
845 // CHECK-MESSAGES: [[@LINE-1]]:8: warning: variable 'p_local2' of type 'int' can be declared 'const'
846 // CHECK-FIXES: int const p_local2
847 (void)p_local2;
848 }
849
850 good_iterator p_local3;
851 // CHECK-MESSAGES: [[@LINE-1]]:3: warning: variable 'p_local3' of type 'good_iterator' can be declared 'const'
852 // CHECK-FIXES: good_iterator const p_local3
853 for (int p_local4 : p_local3)
854 // CHECK-MESSAGES: [[@LINE-1]]:8: warning: variable 'p_local4' of type 'int' can be declared 'const'
855 // CHECK-FIXES: int const p_local4
856 ;
857 good_iterator np_local1;
858 for (int &np_local2 : np_local1)
859 np_local2++;
860}
861
862void for_bad_iterators_array() {
863 int np_local0[42];
864 int(&np_local1)[42] = np_local0;
865
866 for (int &np_local2 : np_local1) {
867 np_local2++;
868 }
869}
870void for_ok_iterators_array() {
871 int np_local0[42];
872 int(&p_local0)[42] = np_local0;
873 // CHECK-MESSAGES: [[@LINE-1]]:3: warning: variable 'p_local0' of type 'int (&)[42]' can be declared 'const'
874 // CHECK-FIXES: int const(&p_local0)[42]
875
876 for (int p_local1 : p_local0) {
877 // CHECK-MESSAGES: [[@LINE-1]]:8: warning: variable 'p_local1' of type 'int' can be declared 'const'
878 // CHECK-FIXES: int const p_local1
879 (void)p_local1;
880 }
881}
882
883void take_ref(int &);
884void ternary_reference() {
885 int np_local0 = 42;
886 int np_local1 = 43;
887 take_ref((np_local0 > np_local1 ? np_local0 : (np_local0, np_local1)));
888}
889
890void complex_usage() {
891 int np_local0 = 42;
892 int p_local0 = 42;
893 // CHECK-MESSAGES: [[@LINE-1]]:3: warning: variable 'p_local0' of type 'int' can be declared 'const'
894 // CHECK-FIXES: int const p_local0
895 int np_local1 = 42;
896 (np_local0 == p_local0 ? np_local0 : (p_local0, np_local1))++;
897}
898
899void vlas() {
900 int N = 1; // Can't make N 'const' because VLAs make everything awful
901 sizeof(int[++N]);
902}
903
904struct base {
905 int member;
906};
907struct derived : base {};
908struct another_struct {
909 derived member;
910};
911void another_struct_f() {
912 another_struct np_local0{};
913 base &np_local1 = np_local0.member;
914 np_local1.member++;
915}
916struct list_init {
917 int &member;
918};
919void create_false_positive() {
920 int np_local0 = 42;
921 list_init p_local0 = {.member: np_local0};
922 // CHECK-MESSAGES:[[@LINE-1]]:3: warning: variable 'p_local0' of type 'list_init' can be declared 'const'
923 // CHECK-FIXES: list_init const p_local0
924}
925struct list_init_derived {
926 base &member;
927};
928void list_init_derived_func() {
929 derived np_local0;
930 list_init_derived p_local0 = {.member: np_local0};
931 // CHECK-MESSAGES:[[@LINE-1]]:3: warning: variable 'p_local0' of type 'list_init_derived' can be declared 'const'
932 // CHECK-FIXES: list_init_derived const p_local0
933}
934template <typename L, typename R>
935struct ref_pair {
936 L &first;
937 R &second;
938};
939template <typename T>
940void list_init_template() {
941 T np_local0{};
942 ref_pair<T, T> p_local0 = {np_local0, np_local0};
943}
944void cast_in_class_hierarchy() {
945 derived np_local0;
946 base p_local1 = static_cast<base &>(np_local0);
947 // CHECK-MESSAGES:[[@LINE-1]]:3: warning: variable 'p_local1' of type 'base' can be declared 'const'
948 // CHECK-FIXES: base const p_local1
949}
950
951void function_ref_target(int);
952using my_function_type = void (&)(int);
953void func_references() {
954 // Could be const, because the reference is not adjusted but adding that
955 // has no effect and creates a compiler warning.
956 my_function_type ptr = function_ref_target;
957}
958
959template <typename T>
960T &return_ref() {
961 static T global;
962 return global;
963}
964template <typename T>
965T *return_ptr() { return &return_ref<T>(); }
966
967void auto_usage_variants() {
968 auto auto_val0 = int{};
969 // CHECK-FIXES-NOT: auto const auto_val0
970 auto &auto_val1 = auto_val0;
971 auto *auto_val2 = &auto_val0;
972
973 auto auto_ref0 = return_ref<int>();
974 // CHECK-FIXES-NOT: auto const auto_ref0
975 auto &auto_ref1 = return_ref<int>(); // Bad
976 auto *auto_ref2 = return_ptr<int>();
977
978 auto auto_ptr0 = return_ptr<int>();
979 // CHECK-FIXES-NOT: auto const auto_ptr0
980 auto &auto_ptr1 = auto_ptr0;
981 auto *auto_ptr2 = return_ptr<int>();
982
983 using MyTypedef = int;
984 auto auto_td0 = MyTypedef{};
985 // CHECK-FIXES-NOT: auto const auto_td0
986 auto &auto_td1 = auto_td0;
987 auto *auto_td2 = &auto_td0;
988}
989
990using PointerToMemberFunction = int (Value::*)();
991void member_pointer(Value &x, PointerToMemberFunction m) {
992 Value &member_pointer_tmp = x;
993 (member_pointer_tmp.*m)();
994}
995
996using PointerToConstMemberFunction = int (Value::*)() const;
997void member_pointer_const(Value &x, PointerToConstMemberFunction m) {
998 Value &member_pointer_tmp = x;
999 // CHECK-MESSAGES:[[@LINE-1]]:3: warning: variable 'member_pointer_tmp' of type 'Value &' can be declared 'const'
1000 (member_pointer_tmp.*m)();
1001}
1002
1003namespace gh127776_false_positive {
1004template <class T> struct vector { T &operator[](int t); };
1005template <typename T> void f() {
1006 vector<int> x;
1007 x[T{}] = 3;
1008}
1009} // namespace gh127776_false_positive
1010
1011namespace gh132931_false_positive {
1012using T = const int;
1013void valid(int i) {
1014 const int arr0[] = {1, 2, 3};
1015 T arr1[] = {1, 2, 3};
1016}
1017} // namespace gh132931_false_positive
1018

Provided by KDAB

Privacy Policy
Improve your Profiling and Debugging skills
Find out more

source code of clang-tools-extra/test/clang-tidy/checkers/misc/const-correctness-values.cpp