1018 lines · cpp
1// RUN: %check_clang_tidy %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 -fexceptions8 9// ------- Provide test samples for primitive builtins ---------10// - every 'p_*' variable is a 'potential_const_*' variable11// - every 'np_*' variable is a 'non_potential_const_*' variable12 13bool global;14char np_global = 0; // globals can't be known to be const15 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 globals22} // namespace foo23 24// FIXME: Similary to 'static' globals, anonymous globals are not matched and analyzed.25namespace {26int np_anonymous_global;27int p_anonymous_global = 43;28} // namespace29 30// Lambdas should be ignored, because they do not follow the normal variable31// 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 = 2;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 = 0;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 = 2;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 = 42;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 = 1;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 = 0;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 = 1;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(&np_local2);135 136 // Prevents const.137 int np_local3 = 42;138 out = &np_local3; // This returns and invalid address, its just about the AST139 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 = 42;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 = 42;148 function_in_pointer(&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(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 = 42;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 = 42;172 function_in_ref(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 = 0.0;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 = 0.0;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 = 24.4;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 = 0.0;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 = 24.4;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(np_local0);213 214 const int np_local1 = 42;215 overloaded_arguments(np_local1);216 217 int np_local2 = 42;218 overloaded_arguments(&np_local2);219 220 const int np_local3 = 42;221 overloaded_arguments(&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 = 42;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 needs253 // 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 needs262 // 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 needs270 // 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_local0, np_local1, np_local0);280 define_locals(np_local1, np_local1, 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_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 = p_local2 - p_local2;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] = {0., 1., 2., 3., 4., 5., 6., 7., 8., 9.};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 = p_local0[5];418 419 // The following subscript calls surprisingly choose the non-const operator420 // 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 = np_local2[42];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 = np_local5[42];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 const444 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 default446 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_local4[2]);457 double np_local5[10] = {0., 1., 2., 3., 4., 5., 6., 7., 8., 9.};458 non_const_handle(&np_local5[2]);459 460 // Constant handles are ok461 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] = {0., 1., 2., 3., 4., 5., 6., 7., 8., 9.};464 const double *p_local2 = &p_local1[2]; // Could be `const double *const`, but warning deactivated by default465 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] = {0., 1., 2., 3., 4., 5., 6., 7., 8., 9.};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] = {0., 1., 2., 3., 4., 5., 6., 7., 8., 9.};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] = {0., 1., 2., 3., 4., 5., 6., 7., 8., 9.};480 const_handle(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] = {0., 1., 2., 3., 4., 5., 6., 7., 8., 9.};484 const_handle(&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 silenced509 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] = {1, 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: for (int const value : p_local0) {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] = {1, 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 = 42;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 = 43;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 = static_cast<short>(p_local1);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, np_local3 = 5;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 450654template <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 = 42;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 fields687struct 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{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{3, 22};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(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 = 42;749 int np_local0 = 42;750 f_signature action = my_alloc;751 action(np_local0);752 my_alloc(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{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, so785// they are always a mutation. If 'np_local1' is fixed to const it results in786// 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: for (int const p_local0 : np_local3)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: for (int const p_local1 : np_local4, np_local5)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: for (int const p_local2 : 1 > 2 ? np_local6 : np_local7)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: for (int const p_local3 : 2 > 1 ? np_local8 : (np_local8, np_local9))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 = p_local0;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: for (int const p_local2 : p_local1) {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: for (int const p_local4 : p_local3)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] = np_local0;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: for (int const p_local1 : p_local0) {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 = 42;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 awful901 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 = {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 = {np_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 = {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 = {np_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 = static_cast<base &>(np_local0);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 that955 // 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_val0970 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_ref0975 auto &auto_ref1 = return_ref<int>(); // Bad976 auto *auto_ref2 = return_ptr<int>();977 978 auto auto_ptr0 = return_ptr<int>();979 // CHECK-FIXES-NOT: auto const auto_ptr0980 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_td0986 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_positive1010 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_positive1018