146ae26e7SJonas Toth // RUN: %check_clang_tidy %s misc-const-correctness %t -- \ 21af159e9SPiotr Zegar // RUN: -config="{CheckOptions: {\ 31af159e9SPiotr Zegar // RUN: misc-const-correctness.TransformValues: true, \ 41af159e9SPiotr Zegar // RUN: misc-const-correctness.WarnPointersAsValues: false, \ 5fda77784SAdrian Vogelsgesang // RUN: misc-const-correctness.TransformPointersAsValues: false \ 6*2dd82c5aSPiotr Zegar // RUN: }}" -- -fno-delayed-template-parsing -fexceptions 746ae26e7SJonas Toth 846ae26e7SJonas Toth // ------- Provide test samples for primitive builtins --------- 946ae26e7SJonas Toth // - every 'p_*' variable is a 'potential_const_*' variable 1046ae26e7SJonas Toth // - every 'np_*' variable is a 'non_potential_const_*' variable 1146ae26e7SJonas Toth 1246ae26e7SJonas Toth bool global; 1346ae26e7SJonas Toth char np_global = 0; // globals can't be known to be const 1446ae26e7SJonas Toth 1546ae26e7SJonas Toth // FIXME: 'static' globals are not matched right now. They could be analyzed but aren't right now. 1646ae26e7SJonas Toth static int p_static_global = 42; 1746ae26e7SJonas Toth 1846ae26e7SJonas Toth namespace foo { 1946ae26e7SJonas Toth int scoped; 2046ae26e7SJonas Toth float np_scoped = 1; // namespace variables are like globals 2146ae26e7SJonas Toth } // namespace foo 2246ae26e7SJonas Toth 2346ae26e7SJonas Toth // FIXME: Similary to 'static' globals, anonymous globals are not matched and analyzed. 2446ae26e7SJonas Toth namespace { 2546ae26e7SJonas Toth int np_anonymous_global; 2646ae26e7SJonas Toth int p_anonymous_global = 43; 2746ae26e7SJonas Toth } // namespace 2846ae26e7SJonas Toth 2946ae26e7SJonas Toth // Lambdas should be ignored, because they do not follow the normal variable 3046ae26e7SJonas Toth // semantic (e.g. the type is only known to the compiler). 3146ae26e7SJonas Toth void lambdas() { 3246ae26e7SJonas Toth auto Lambda = [](int i) { return i < 0; }; 3346ae26e7SJonas Toth } 3446ae26e7SJonas Toth 3546ae26e7SJonas Toth void some_function(double, wchar_t); 3646ae26e7SJonas Toth 3746ae26e7SJonas Toth void some_function(double np_arg0, wchar_t np_arg1) { 3846ae26e7SJonas Toth int p_local0 = 2; 3946ae26e7SJonas Toth // CHECK-MESSAGES: [[@LINE-1]]:3: warning: variable 'p_local0' of type 'int' can be declared 'const' 4046ae26e7SJonas Toth // CHECK-FIXES: int const p_local0 4146ae26e7SJonas Toth 4246ae26e7SJonas Toth int np_local0; 4346ae26e7SJonas Toth const int np_local1 = 42; 4446ae26e7SJonas Toth 4546ae26e7SJonas Toth unsigned int np_local2 = 3; 4646ae26e7SJonas Toth np_local2 <<= 4; 4746ae26e7SJonas Toth 4846ae26e7SJonas Toth int np_local3 = 4; 4946ae26e7SJonas Toth ++np_local3; 5046ae26e7SJonas Toth int np_local4 = 4; 5146ae26e7SJonas Toth np_local4++; 5246ae26e7SJonas Toth 5346ae26e7SJonas Toth int np_local5 = 4; 5446ae26e7SJonas Toth --np_local5; 5546ae26e7SJonas Toth int np_local6 = 4; 5646ae26e7SJonas Toth np_local6--; 5746ae26e7SJonas Toth } 5846ae26e7SJonas Toth 5926c99c42SThomas Schenker int function_try_block() try { 6026c99c42SThomas Schenker int p_local0 = 0; 6126c99c42SThomas Schenker // CHECK-MESSAGES: [[@LINE-1]]:3: warning: variable 'p_local0' of type 'int' can be declared 'const' 6226c99c42SThomas Schenker // CHECK-FIXES: int const p_local0 6326c99c42SThomas Schenker return p_local0; 6426c99c42SThomas Schenker } catch (...) { 6526c99c42SThomas Schenker return 0; 6626c99c42SThomas Schenker } 6726c99c42SThomas Schenker 6846ae26e7SJonas Toth void nested_scopes() { 6946ae26e7SJonas Toth int p_local0 = 2; 7046ae26e7SJonas Toth // CHECK-MESSAGES: [[@LINE-1]]:3: warning: variable 'p_local0' of type 'int' can be declared 'const' 7146ae26e7SJonas Toth // CHECK-FIXES: int const p_local0 7246ae26e7SJonas Toth int np_local0 = 42; 7346ae26e7SJonas Toth 7446ae26e7SJonas Toth { 7546ae26e7SJonas Toth int p_local1 = 42; 7646ae26e7SJonas Toth // CHECK-MESSAGES: [[@LINE-1]]:5: warning: variable 'p_local1' of type 'int' can be declared 'const' 7746ae26e7SJonas Toth // CHECK-FIXES: int const p_local1 7846ae26e7SJonas Toth np_local0 *= 2; 7946ae26e7SJonas Toth } 8046ae26e7SJonas Toth } 8146ae26e7SJonas Toth 8246ae26e7SJonas Toth void ignore_reference_to_pointers() { 8346ae26e7SJonas Toth int *np_local0 = nullptr; 8446ae26e7SJonas Toth int *&np_local1 = np_local0; 8546ae26e7SJonas Toth } 8646ae26e7SJonas Toth 8746ae26e7SJonas Toth void some_lambda_environment_capture_all_by_reference(double np_arg0) { 8846ae26e7SJonas Toth int np_local0 = 0; 8946ae26e7SJonas Toth int p_local0 = 1; 9046ae26e7SJonas Toth // CHECK-MESSAGES: [[@LINE-1]]:3: warning: variable 'p_local0' of type 'int' can be declared 'const' 9146ae26e7SJonas Toth // CHECK-FIXES: int const p_local0 9246ae26e7SJonas Toth 9346ae26e7SJonas Toth int np_local2; 9446ae26e7SJonas Toth const int np_local3 = 2; 9546ae26e7SJonas Toth 9646ae26e7SJonas Toth // Capturing all variables by reference prohibits making them const. 9746ae26e7SJonas Toth [&]() { ++np_local0; }; 9846ae26e7SJonas Toth 9946ae26e7SJonas Toth int p_local1 = 0; 10046ae26e7SJonas Toth // CHECK-MESSAGES: [[@LINE-1]]:3: warning: variable 'p_local1' of type 'int' can be declared 'const' 10146ae26e7SJonas Toth // CHECK-FIXES: int const p_local1 10246ae26e7SJonas Toth } 10346ae26e7SJonas Toth 10446ae26e7SJonas Toth void some_lambda_environment_capture_all_by_value(double np_arg0) { 10546ae26e7SJonas Toth int np_local0 = 0; 10646ae26e7SJonas Toth int p_local0 = 1; 10746ae26e7SJonas Toth // CHECK-MESSAGES: [[@LINE-1]]:3: warning: variable 'p_local0' of type 'int' can be declared 'const' 10846ae26e7SJonas Toth // CHECK-FIXES: int const p_local0 10946ae26e7SJonas Toth 11046ae26e7SJonas Toth int np_local1; 11146ae26e7SJonas Toth const int np_local2 = 2; 11246ae26e7SJonas Toth 11346ae26e7SJonas Toth // Capturing by value has no influence on them. 11446ae26e7SJonas Toth [=]() { (void)p_local0; }; 11546ae26e7SJonas Toth 11646ae26e7SJonas Toth np_local0 += 10; 11746ae26e7SJonas Toth } 11846ae26e7SJonas Toth 11946ae26e7SJonas Toth void function_inout_pointer(int *inout); 12046ae26e7SJonas Toth void function_in_pointer(const int *in); 12146ae26e7SJonas Toth 12246ae26e7SJonas Toth void some_pointer_taking(int *out) { 12346ae26e7SJonas Toth int np_local0 = 42; 12446ae26e7SJonas Toth const int *const p0_np_local0 = &np_local0; 12546ae26e7SJonas Toth int *const p1_np_local0 = &np_local0; 12646ae26e7SJonas Toth 12746ae26e7SJonas Toth int np_local1 = 42; 12846ae26e7SJonas Toth const int *const p0_np_local1 = &np_local1; 12946ae26e7SJonas Toth int *const p1_np_local1 = &np_local1; 13046ae26e7SJonas Toth *p1_np_local0 = 43; 13146ae26e7SJonas Toth 13246ae26e7SJonas Toth int np_local2 = 42; 13346ae26e7SJonas Toth function_inout_pointer(&np_local2); 13446ae26e7SJonas Toth 13546ae26e7SJonas Toth // Prevents const. 13646ae26e7SJonas Toth int np_local3 = 42; 13746ae26e7SJonas Toth out = &np_local3; // This returns and invalid address, its just about the AST 13846ae26e7SJonas Toth 13946ae26e7SJonas Toth int p_local1 = 42; 14046ae26e7SJonas Toth // CHECK-MESSAGES: [[@LINE-1]]:3: warning: variable 'p_local1' of type 'int' can be declared 'const' 14146ae26e7SJonas Toth // CHECK-FIXES: int const p_local1 14246ae26e7SJonas Toth const int *const p0_p_local1 = &p_local1; 14346ae26e7SJonas Toth 14446ae26e7SJonas Toth int p_local2 = 42; 14546ae26e7SJonas Toth // CHECK-MESSAGES: [[@LINE-1]]:3: warning: variable 'p_local2' of type 'int' can be declared 'const' 14646ae26e7SJonas Toth // CHECK-FIXES: int const p_local2 14746ae26e7SJonas Toth function_in_pointer(&p_local2); 14846ae26e7SJonas Toth } 14946ae26e7SJonas Toth 15046ae26e7SJonas Toth void function_inout_ref(int &inout); 15146ae26e7SJonas Toth void function_in_ref(const int &in); 15246ae26e7SJonas Toth 15346ae26e7SJonas Toth void some_reference_taking() { 15446ae26e7SJonas Toth int np_local0 = 42; 15546ae26e7SJonas Toth const int &r0_np_local0 = np_local0; 15646ae26e7SJonas Toth int &r1_np_local0 = np_local0; 15746ae26e7SJonas Toth r1_np_local0 = 43; 15846ae26e7SJonas Toth const int &r2_np_local0 = r1_np_local0; 15946ae26e7SJonas Toth 16046ae26e7SJonas Toth int np_local1 = 42; 16146ae26e7SJonas Toth function_inout_ref(np_local1); 16246ae26e7SJonas Toth 16346ae26e7SJonas Toth int p_local0 = 42; 16446ae26e7SJonas Toth // CHECK-MESSAGES: [[@LINE-1]]:3: warning: variable 'p_local0' of type 'int' can be declared 'const' 16546ae26e7SJonas Toth // CHECK-FIXES: int const p_local0 16646ae26e7SJonas Toth const int &r0_p_local0 = p_local0; 16746ae26e7SJonas Toth 16846ae26e7SJonas Toth int p_local1 = 42; 16946ae26e7SJonas Toth // CHECK-MESSAGES: [[@LINE-1]]:3: warning: variable 'p_local1' of type 'int' can be declared 'const' 17046ae26e7SJonas Toth // CHECK-FIXES: int const p_local1 17146ae26e7SJonas Toth function_in_ref(p_local1); 17246ae26e7SJonas Toth } 17346ae26e7SJonas Toth 17446ae26e7SJonas Toth double *non_const_pointer_return() { 17546ae26e7SJonas Toth double p_local0 = 0.0; 17646ae26e7SJonas Toth // CHECK-MESSAGES: [[@LINE-1]]:3: warning: variable 'p_local0' of type 'double' can be declared 'const' 17746ae26e7SJonas Toth // CHECK-FIXES: double const p_local0 17846ae26e7SJonas Toth double np_local0 = 24.4; 17946ae26e7SJonas Toth 18046ae26e7SJonas Toth return &np_local0; 18146ae26e7SJonas Toth } 18246ae26e7SJonas Toth 18346ae26e7SJonas Toth const double *const_pointer_return() { 18446ae26e7SJonas Toth double p_local0 = 0.0; 18546ae26e7SJonas Toth // CHECK-MESSAGES: [[@LINE-1]]:3: warning: variable 'p_local0' of type 'double' can be declared 'const' 18646ae26e7SJonas Toth // CHECK-FIXES: double const p_local0 18746ae26e7SJonas Toth double p_local1 = 24.4; 18846ae26e7SJonas Toth // CHECK-MESSAGES: [[@LINE-1]]:3: warning: variable 'p_local1' of type 'double' can be declared 'const' 18946ae26e7SJonas Toth // CHECK-FIXES: double const p_local1 19046ae26e7SJonas Toth return &p_local1; 19146ae26e7SJonas Toth } 19246ae26e7SJonas Toth 193fda77784SAdrian Vogelsgesang // Also see const-correctness-values.cpp-before-cxx23.cpp for `non_const_ref_return` and `return_non_const_pointer_ref` 19446ae26e7SJonas Toth const double &const_ref_return() { 19546ae26e7SJonas Toth double p_local0 = 0.0; 19646ae26e7SJonas Toth // CHECK-MESSAGES: [[@LINE-1]]:3: warning: variable 'p_local0' of type 'double' can be declared 'const' 19746ae26e7SJonas Toth // CHECK-FIXES: double const p_local0 19846ae26e7SJonas Toth double p_local1 = 24.4; 19946ae26e7SJonas Toth // CHECK-MESSAGES: [[@LINE-1]]:3: warning: variable 'p_local1' of type 'double' can be declared 'const' 20046ae26e7SJonas Toth // CHECK-FIXES: double const p_local1 20146ae26e7SJonas Toth return p_local1; 20246ae26e7SJonas Toth } 20346ae26e7SJonas Toth 20446ae26e7SJonas Toth void overloaded_arguments(const int &in); 20546ae26e7SJonas Toth void overloaded_arguments(int &inout); 20646ae26e7SJonas Toth void overloaded_arguments(const int *in); 20746ae26e7SJonas Toth void overloaded_arguments(int *inout); 20846ae26e7SJonas Toth 20946ae26e7SJonas Toth void function_calling() { 21046ae26e7SJonas Toth int np_local0 = 42; 21146ae26e7SJonas Toth overloaded_arguments(np_local0); 21246ae26e7SJonas Toth 21346ae26e7SJonas Toth const int np_local1 = 42; 21446ae26e7SJonas Toth overloaded_arguments(np_local1); 21546ae26e7SJonas Toth 21646ae26e7SJonas Toth int np_local2 = 42; 21746ae26e7SJonas Toth overloaded_arguments(&np_local2); 21846ae26e7SJonas Toth 21946ae26e7SJonas Toth const int np_local3 = 42; 22046ae26e7SJonas Toth overloaded_arguments(&np_local3); 22146ae26e7SJonas Toth } 22246ae26e7SJonas Toth 22346ae26e7SJonas Toth template <typename T> 22446ae26e7SJonas Toth void define_locals(T np_arg0, T &np_arg1, int np_arg2) { 22546ae26e7SJonas Toth T np_local0 = 0; 22646ae26e7SJonas Toth np_local0 += np_arg0 * np_arg1; 22746ae26e7SJonas Toth 22846ae26e7SJonas Toth T np_local1 = 42; 22946ae26e7SJonas Toth np_local0 += np_local1; 23046ae26e7SJonas Toth 23146ae26e7SJonas Toth // Used as argument to an overloaded function with const and non-const. 23246ae26e7SJonas Toth T np_local2 = 42; 23346ae26e7SJonas Toth overloaded_arguments(np_local2); 23446ae26e7SJonas Toth 23546ae26e7SJonas Toth int np_local4 = 42; 23646ae26e7SJonas Toth // non-template values are ok still. 23746ae26e7SJonas Toth int p_local0 = 42; 23846ae26e7SJonas Toth // CHECK-MESSAGES: [[@LINE-1]]:3: warning: variable 'p_local0' of type 'int' can be declared 'const' 23946ae26e7SJonas Toth // CHECK-FIXES: int const p_local0 24046ae26e7SJonas Toth np_local4 += p_local0; 24146ae26e7SJonas Toth } 24246ae26e7SJonas Toth 24346ae26e7SJonas Toth template <typename T> 24446ae26e7SJonas Toth void more_template_locals() { 24546ae26e7SJonas Toth const T np_local0 = {}; 24646ae26e7SJonas Toth auto np_local1 = T{}; 24746ae26e7SJonas Toth T &np_local2 = np_local1; 24846ae26e7SJonas Toth T *np_local_ptr = &np_local1; 24946ae26e7SJonas Toth 25046ae26e7SJonas Toth const auto np_local3 = T{}; 25146ae26e7SJonas Toth // FIXME: False positive, the reference points to a template type and needs 25246ae26e7SJonas Toth // to be excluded from analysis, but somehow isn't (matchers don't work) 25346ae26e7SJonas Toth auto &np_local4 = np_local3; 25446ae26e7SJonas Toth 25546ae26e7SJonas Toth const auto *np_local5 = &np_local3; 25646ae26e7SJonas Toth auto *np_local6 = &np_local1; 25746ae26e7SJonas Toth 25846ae26e7SJonas Toth using TypedefToTemplate = T; 25946ae26e7SJonas Toth TypedefToTemplate np_local7{}; 26046ae26e7SJonas Toth // FIXME: False positive, the reference points to a template type and needs 26146ae26e7SJonas Toth // to be excluded from analysis, but somehow isn't (matchers don't work) 26246ae26e7SJonas Toth // auto &np_local8 = np_local7; 26346ae26e7SJonas Toth const auto &np_local9 = np_local7; 26446ae26e7SJonas Toth auto np_local10 = np_local7; 26546ae26e7SJonas Toth auto *np_local11 = &np_local10; 26646ae26e7SJonas Toth const auto *const np_local12 = &np_local10; 26746ae26e7SJonas Toth 26846ae26e7SJonas Toth // FIXME: False positive, the reference points to a template type and needs 26946ae26e7SJonas Toth // to be excluded from analysis, but somehow isn't (matchers don't work) 27046ae26e7SJonas Toth // TypedefToTemplate &np_local13 = np_local7; 27146ae26e7SJonas Toth TypedefToTemplate *np_local14 = &np_local7; 27246ae26e7SJonas Toth } 27346ae26e7SJonas Toth 27446ae26e7SJonas Toth void template_instantiation() { 27546ae26e7SJonas Toth const int np_local0 = 42; 27646ae26e7SJonas Toth int np_local1 = 42; 27746ae26e7SJonas Toth 27846ae26e7SJonas Toth define_locals(np_local0, np_local1, np_local0); 27946ae26e7SJonas Toth define_locals(np_local1, np_local1, np_local1); 28046ae26e7SJonas Toth more_template_locals<int>(); 28146ae26e7SJonas Toth } 28246ae26e7SJonas Toth 28346ae26e7SJonas Toth struct ConstNonConstClass { 28446ae26e7SJonas Toth ConstNonConstClass(); 28546ae26e7SJonas Toth ConstNonConstClass(double &np_local0); 28646ae26e7SJonas Toth double nonConstMethod() {} 28746ae26e7SJonas Toth double constMethod() const {} 28846ae26e7SJonas Toth double modifyingMethod(double &np_arg0) const; 28946ae26e7SJonas Toth 29046ae26e7SJonas Toth double NonConstMember; 29146ae26e7SJonas Toth const double ConstMember; 29246ae26e7SJonas Toth 29346ae26e7SJonas Toth double &NonConstMemberRef; 29446ae26e7SJonas Toth const double &ConstMemberRef; 29546ae26e7SJonas Toth 29646ae26e7SJonas Toth double *NonConstMemberPtr; 29746ae26e7SJonas Toth const double *ConstMemberPtr; 29846ae26e7SJonas Toth }; 29946ae26e7SJonas Toth 30046ae26e7SJonas Toth void direct_class_access() { 30146ae26e7SJonas Toth ConstNonConstClass np_local0; 30246ae26e7SJonas Toth 30346ae26e7SJonas Toth np_local0.constMethod(); 30446ae26e7SJonas Toth np_local0.nonConstMethod(); 30546ae26e7SJonas Toth 30646ae26e7SJonas Toth ConstNonConstClass p_local0; 30746ae26e7SJonas Toth // CHECK-MESSAGES: [[@LINE-1]]:3: warning: variable 'p_local0' of type 'ConstNonConstClass' can be declared 'const' 30846ae26e7SJonas Toth // CHECK-FIXES: ConstNonConstClass const p_local0 30946ae26e7SJonas Toth p_local0.constMethod(); 31046ae26e7SJonas Toth 31146ae26e7SJonas Toth ConstNonConstClass p_local1; 31246ae26e7SJonas Toth // CHECK-MESSAGES: [[@LINE-1]]:3: warning: variable 'p_local1' of type 'ConstNonConstClass' can be declared 'const' 31346ae26e7SJonas Toth // CHECK-FIXES: ConstNonConstClass const p_local1 31446ae26e7SJonas Toth double np_local1; 31546ae26e7SJonas Toth p_local1.modifyingMethod(np_local1); 31646ae26e7SJonas Toth 31746ae26e7SJonas Toth double np_local2; 31846ae26e7SJonas Toth ConstNonConstClass p_local2(np_local2); 31946ae26e7SJonas Toth // CHECK-MESSAGES: [[@LINE-1]]:3: warning: variable 'p_local2' of type 'ConstNonConstClass' can be declared 'const' 32046ae26e7SJonas Toth // CHECK-FIXES: ConstNonConstClass const p_local2(np_local2) 32146ae26e7SJonas Toth 32246ae26e7SJonas Toth ConstNonConstClass np_local3; 32346ae26e7SJonas Toth np_local3.NonConstMember = 42.; 32446ae26e7SJonas Toth 32546ae26e7SJonas Toth ConstNonConstClass np_local4; 32646ae26e7SJonas Toth np_local4.NonConstMemberRef = 42.; 32746ae26e7SJonas Toth 32846ae26e7SJonas Toth ConstNonConstClass p_local3; 32946ae26e7SJonas Toth // CHECK-MESSAGES: [[@LINE-1]]:3: warning: variable 'p_local3' of type 'ConstNonConstClass' can be declared 'const' 33046ae26e7SJonas Toth // CHECK-FIXES: ConstNonConstClass const p_local3 33146ae26e7SJonas Toth const double val0 = p_local3.NonConstMember; 33246ae26e7SJonas Toth const double val1 = p_local3.NonConstMemberRef; 33346ae26e7SJonas Toth const double val2 = *p_local3.NonConstMemberPtr; 33446ae26e7SJonas Toth 33546ae26e7SJonas Toth ConstNonConstClass p_local4; 33646ae26e7SJonas Toth // CHECK-MESSAGES: [[@LINE-1]]:3: warning: variable 'p_local4' of type 'ConstNonConstClass' can be declared 'const' 33746ae26e7SJonas Toth // CHECK-FIXES: ConstNonConstClass const p_local4 33846ae26e7SJonas Toth *np_local4.NonConstMemberPtr = 42.; 33946ae26e7SJonas Toth } 34046ae26e7SJonas Toth 34146ae26e7SJonas Toth void class_access_array() { 34246ae26e7SJonas Toth ConstNonConstClass np_local0[2]; 34346ae26e7SJonas Toth np_local0[0].constMethod(); 34446ae26e7SJonas Toth np_local0[1].constMethod(); 34546ae26e7SJonas Toth np_local0[1].nonConstMethod(); 34646ae26e7SJonas Toth 34746ae26e7SJonas Toth ConstNonConstClass p_local0[2]; 34846ae26e7SJonas Toth // CHECK-MESSAGES: [[@LINE-1]]:3: warning: variable 'p_local0' of type 'ConstNonConstClass[2]' can be declared 'const' 34946ae26e7SJonas Toth // CHECK-FIXES: ConstNonConstClass const p_local0[2] 35046ae26e7SJonas Toth p_local0[0].constMethod(); 35146ae26e7SJonas Toth np_local0[1].constMethod(); 35246ae26e7SJonas Toth } 35346ae26e7SJonas Toth 35446ae26e7SJonas Toth struct OperatorsAsConstAsPossible { 35546ae26e7SJonas Toth OperatorsAsConstAsPossible &operator+=(const OperatorsAsConstAsPossible &rhs); 35646ae26e7SJonas Toth OperatorsAsConstAsPossible operator+(const OperatorsAsConstAsPossible &rhs) const; 35746ae26e7SJonas Toth }; 35846ae26e7SJonas Toth 35946ae26e7SJonas Toth struct NonConstOperators { 36046ae26e7SJonas Toth }; 36146ae26e7SJonas Toth NonConstOperators operator+(NonConstOperators &lhs, NonConstOperators &rhs); 36246ae26e7SJonas Toth NonConstOperators operator-(NonConstOperators lhs, NonConstOperators rhs); 36346ae26e7SJonas Toth 36446ae26e7SJonas Toth void internal_operator_calls() { 36546ae26e7SJonas Toth OperatorsAsConstAsPossible np_local0; 36646ae26e7SJonas Toth OperatorsAsConstAsPossible np_local1; 36746ae26e7SJonas Toth OperatorsAsConstAsPossible p_local0; 36846ae26e7SJonas Toth // CHECK-MESSAGES: [[@LINE-1]]:3: warning: variable 'p_local0' of type 'OperatorsAsConstAsPossible' can be declared 'const' 36946ae26e7SJonas Toth // CHECK-FIXES: OperatorsAsConstAsPossible const p_local0 37046ae26e7SJonas Toth OperatorsAsConstAsPossible p_local1; 37146ae26e7SJonas Toth // CHECK-MESSAGES: [[@LINE-1]]:3: warning: variable 'p_local1' of type 'OperatorsAsConstAsPossible' can be declared 'const' 37246ae26e7SJonas Toth // CHECK-FIXES: OperatorsAsConstAsPossible const p_local1 37346ae26e7SJonas Toth 37446ae26e7SJonas Toth np_local0 += p_local0; 37546ae26e7SJonas Toth np_local1 = p_local0 + p_local1; 37646ae26e7SJonas Toth 37746ae26e7SJonas Toth NonConstOperators np_local2; 37846ae26e7SJonas Toth NonConstOperators np_local3; 37946ae26e7SJonas Toth NonConstOperators np_local4; 38046ae26e7SJonas Toth 38146ae26e7SJonas Toth np_local2 = np_local3 + np_local4; 38246ae26e7SJonas Toth 38346ae26e7SJonas Toth NonConstOperators p_local2; 38446ae26e7SJonas Toth // CHECK-MESSAGES: [[@LINE-1]]:3: warning: variable 'p_local2' of type 'NonConstOperators' can be declared 'const' 38546ae26e7SJonas Toth // CHECK-FIXES: NonConstOperators const p_local2 38646ae26e7SJonas Toth NonConstOperators p_local3 = p_local2 - p_local2; 38746ae26e7SJonas Toth // CHECK-MESSAGES: [[@LINE-1]]:3: warning: variable 'p_local3' of type 'NonConstOperators' can be declared 'const' 38846ae26e7SJonas Toth // CHECK-FIXES: NonConstOperators const p_local3 38946ae26e7SJonas Toth } 39046ae26e7SJonas Toth 39146ae26e7SJonas Toth struct MyVector { 39246ae26e7SJonas Toth double *begin(); 39346ae26e7SJonas Toth const double *begin() const; 39446ae26e7SJonas Toth 39546ae26e7SJonas Toth double *end(); 39646ae26e7SJonas Toth const double *end() const; 39746ae26e7SJonas Toth 39846ae26e7SJonas Toth double &operator[](int index); 39946ae26e7SJonas Toth double operator[](int index) const; 40046ae26e7SJonas Toth 40146ae26e7SJonas Toth double values[100]; 40246ae26e7SJonas Toth }; 40346ae26e7SJonas Toth 40446ae26e7SJonas Toth void vector_usage() { 40546ae26e7SJonas Toth double np_local0[10]; 40646ae26e7SJonas Toth np_local0[5] = 42.; 40746ae26e7SJonas Toth 40846ae26e7SJonas Toth MyVector np_local1; 40946ae26e7SJonas Toth np_local1[5] = 42.; 41046ae26e7SJonas Toth 41146ae26e7SJonas Toth double p_local0[10] = {0., 1., 2., 3., 4., 5., 6., 7., 8., 9.}; 41246ae26e7SJonas Toth // CHECK-MESSAGES: [[@LINE-1]]:3: warning: variable 'p_local0' of type 'double[10]' can be declared 'const' 41346ae26e7SJonas Toth // CHECK-FIXES: double const p_local0[10] 41446ae26e7SJonas Toth double p_local1 = p_local0[5]; 41546ae26e7SJonas Toth // CHECK-MESSAGES: [[@LINE-1]]:3: warning: variable 'p_local1' of type 'double' can be declared 'const' 41646ae26e7SJonas Toth // CHECK-FIXES: double const p_local1 41746ae26e7SJonas Toth 41846ae26e7SJonas Toth // The following subscript calls suprisingly choose the non-const operator 41946ae26e7SJonas Toth // version. 42046ae26e7SJonas Toth MyVector np_local2; 42146ae26e7SJonas Toth double p_local2 = np_local2[42]; 42246ae26e7SJonas Toth // CHECK-MESSAGES: [[@LINE-1]]:3: warning: variable 'p_local2' of type 'double' can be declared 'const' 42346ae26e7SJonas Toth // CHECK-FIXES: double const p_local2 42446ae26e7SJonas Toth 42546ae26e7SJonas Toth MyVector np_local3; 42646ae26e7SJonas Toth const double np_local4 = np_local3[42]; 42746ae26e7SJonas Toth 42846ae26e7SJonas Toth // This subscript results in const overloaded operator. 42946ae26e7SJonas Toth const MyVector np_local5{}; 43046ae26e7SJonas Toth double p_local3 = np_local5[42]; 43146ae26e7SJonas Toth // CHECK-MESSAGES: [[@LINE-1]]:3: warning: variable 'p_local3' of type 'double' can be declared 'const' 43246ae26e7SJonas Toth // CHECK-FIXES: double const p_local3 43346ae26e7SJonas Toth } 43446ae26e7SJonas Toth 43546ae26e7SJonas Toth void const_handle(const double &np_local0); 43646ae26e7SJonas Toth void const_handle(const double *np_local0); 43746ae26e7SJonas Toth 43846ae26e7SJonas Toth void non_const_handle(double &np_local0); 43946ae26e7SJonas Toth void non_const_handle(double *np_local0); 44046ae26e7SJonas Toth 44146ae26e7SJonas Toth void handle_from_array() { 44246ae26e7SJonas Toth // Non-const handle from non-const array forbids declaring the array as const 44346ae26e7SJonas Toth double np_local0[10] = {0., 1., 2., 3., 4., 5., 6., 7., 8., 9.}; 44446ae26e7SJonas Toth double *p_local0 = &np_local0[1]; // Could be `double *const`, but warning deactivated by default 44546ae26e7SJonas Toth 44646ae26e7SJonas Toth double np_local1[10] = {0., 1., 2., 3., 4., 5., 6., 7., 8., 9.}; 44746ae26e7SJonas Toth double &non_const_ref = np_local1[1]; 44846ae26e7SJonas Toth non_const_ref = 42.; 44946ae26e7SJonas Toth 45046ae26e7SJonas Toth double np_local2[10] = {0., 1., 2., 3., 4., 5., 6., 7., 8., 9.}; 45146ae26e7SJonas Toth double *np_local3; 45246ae26e7SJonas Toth np_local3 = &np_local2[5]; 45346ae26e7SJonas Toth 45446ae26e7SJonas Toth double np_local4[10] = {0., 1., 2., 3., 4., 5., 6., 7., 8., 9.}; 45546ae26e7SJonas Toth non_const_handle(np_local4[2]); 45646ae26e7SJonas Toth double np_local5[10] = {0., 1., 2., 3., 4., 5., 6., 7., 8., 9.}; 45746ae26e7SJonas Toth non_const_handle(&np_local5[2]); 45846ae26e7SJonas Toth 45946ae26e7SJonas Toth // Constant handles are ok 46046ae26e7SJonas Toth double p_local1[10] = {0., 1., 2., 3., 4., 5., 6., 7., 8., 9.}; 46146ae26e7SJonas Toth // CHECK-MESSAGES: [[@LINE-1]]:3: warning: variable 'p_local1' of type 'double[10]' can be declared 'const' 46246ae26e7SJonas Toth // CHECK-FIXES: double const p_local1[10] 46346ae26e7SJonas Toth const double *p_local2 = &p_local1[2]; // Could be `const double *const`, but warning deactivated by default 46446ae26e7SJonas Toth 46546ae26e7SJonas Toth double p_local3[10] = {0., 1., 2., 3., 4., 5., 6., 7., 8., 9.}; 46646ae26e7SJonas Toth // CHECK-MESSAGES: [[@LINE-1]]:3: warning: variable 'p_local3' of type 'double[10]' can be declared 'const' 46746ae26e7SJonas Toth // CHECK-FIXES: double const p_local3[10] 46846ae26e7SJonas Toth const double &const_ref = p_local3[2]; 46946ae26e7SJonas Toth 47046ae26e7SJonas Toth double p_local4[10] = {0., 1., 2., 3., 4., 5., 6., 7., 8., 9.}; 47146ae26e7SJonas Toth // CHECK-MESSAGES: [[@LINE-1]]:3: warning: variable 'p_local4' of type 'double[10]' can be declared 'const' 47246ae26e7SJonas Toth // CHECK-FIXES: double const p_local4[10] 47346ae26e7SJonas Toth const double *const_ptr; 47446ae26e7SJonas Toth const_ptr = &p_local4[2]; 47546ae26e7SJonas Toth 47646ae26e7SJonas Toth double p_local5[10] = {0., 1., 2., 3., 4., 5., 6., 7., 8., 9.}; 47746ae26e7SJonas Toth // CHECK-MESSAGES: [[@LINE-1]]:3: warning: variable 'p_local5' of type 'double[10]' can be declared 'const' 47846ae26e7SJonas Toth // CHECK-FIXES: double const p_local5[10] 47946ae26e7SJonas Toth const_handle(p_local5[2]); 48046ae26e7SJonas Toth double p_local6[10] = {0., 1., 2., 3., 4., 5., 6., 7., 8., 9.}; 48146ae26e7SJonas Toth // CHECK-MESSAGES: [[@LINE-1]]:3: warning: variable 'p_local6' of type 'double[10]' can be declared 'const' 48246ae26e7SJonas Toth // CHECK-FIXES: double const p_local6[10] 48346ae26e7SJonas Toth const_handle(&p_local6[2]); 48446ae26e7SJonas Toth } 48546ae26e7SJonas Toth 48646ae26e7SJonas Toth void range_for() { 48746ae26e7SJonas Toth int np_local0[2] = {1, 2}; 48846ae26e7SJonas Toth for (int &non_const_ref : np_local0) { 48946ae26e7SJonas Toth non_const_ref = 42; 49046ae26e7SJonas Toth } 49146ae26e7SJonas Toth 49246ae26e7SJonas Toth int np_local1[2] = {1, 2}; 49346ae26e7SJonas Toth for (auto &non_const_ref : np_local1) { 49446ae26e7SJonas Toth non_const_ref = 43; 49546ae26e7SJonas Toth } 49646ae26e7SJonas Toth 49746ae26e7SJonas Toth int np_local2[2] = {1, 2}; 49846ae26e7SJonas Toth for (auto &&non_const_ref : np_local2) { 49946ae26e7SJonas Toth non_const_ref = 44; 50046ae26e7SJonas Toth } 50146ae26e7SJonas Toth 50246ae26e7SJonas Toth int *np_local3[2] = {&np_local0[0], &np_local0[1]}; 50346ae26e7SJonas Toth for (int *non_const_ptr : np_local3) { 50446ae26e7SJonas Toth *non_const_ptr = 45; 50546ae26e7SJonas Toth } 50646ae26e7SJonas Toth 50746ae26e7SJonas Toth // FIXME same as above, but silenced 50846ae26e7SJonas Toth int *const np_local4[2] = {&np_local0[0], &np_local0[1]}; 50946ae26e7SJonas Toth for (auto *non_const_ptr : np_local4) { 51046ae26e7SJonas Toth *non_const_ptr = 46; 51146ae26e7SJonas Toth } 51246ae26e7SJonas Toth 51346ae26e7SJonas Toth int p_local0[2] = {1, 2}; 51446ae26e7SJonas Toth // CHECK-MESSAGES: [[@LINE-1]]:3: warning: variable 'p_local0' of type 'int[2]' can be declared 'const' 51546ae26e7SJonas Toth // CHECK-FIXES: int const p_local0[2] 51646ae26e7SJonas Toth for (int value : p_local0) { 51746ae26e7SJonas Toth // CHECK-MESSAGES: [[@LINE-1]]:8: warning: variable 'value' of type 'int' can be declared 'const' 51846ae26e7SJonas Toth // CHECK-FIXES: int const value 51946ae26e7SJonas Toth } 52046ae26e7SJonas Toth 52146ae26e7SJonas Toth int p_local1[2] = {1, 2}; 52246ae26e7SJonas Toth // CHECK-MESSAGES: [[@LINE-1]]:3: warning: variable 'p_local1' of type 'int[2]' can be declared 'const' 52346ae26e7SJonas Toth // CHECK-FIXES: int const p_local1[2] 52446ae26e7SJonas Toth for (const int &const_ref : p_local1) { 52546ae26e7SJonas Toth } 52646ae26e7SJonas Toth } 52746ae26e7SJonas Toth 528e66345d5SJonas Toth void arrays_of_pointers_are_ignored() { 529e66345d5SJonas Toth int *np_local0[2] = {nullptr, nullptr}; 530e66345d5SJonas Toth 531e66345d5SJonas Toth using intPtr = int*; 532e66345d5SJonas Toth intPtr np_local1[2] = {nullptr, nullptr}; 53346ae26e7SJonas Toth } 53446ae26e7SJonas Toth 53546ae26e7SJonas Toth inline void *operator new(decltype(sizeof(void *)), void *p) { return p; } 53646ae26e7SJonas Toth 53746ae26e7SJonas Toth struct Value { 53846ae26e7SJonas Toth }; 53946ae26e7SJonas Toth void placement_new() { 54046ae26e7SJonas Toth Value Mem; 54146ae26e7SJonas Toth Value *V = new (&Mem) Value; 54246ae26e7SJonas Toth } 54346ae26e7SJonas Toth 54446ae26e7SJonas Toth struct ModifyingConversion { 54546ae26e7SJonas Toth operator int() { return 15; } 54646ae26e7SJonas Toth }; 54746ae26e7SJonas Toth struct NonModifyingConversion { 54846ae26e7SJonas Toth operator int() const { return 15; } 54946ae26e7SJonas Toth }; 55046ae26e7SJonas Toth void conversion_operators() { 55146ae26e7SJonas Toth ModifyingConversion np_local0; 55246ae26e7SJonas Toth NonModifyingConversion p_local0; 55346ae26e7SJonas Toth // CHECK-MESSAGES: [[@LINE-1]]:3: warning: variable 'p_local0' of type 'NonModifyingConversion' can be declared 'const' 55446ae26e7SJonas Toth // CHECK-FIXES: NonModifyingConversion const p_local0 55546ae26e7SJonas Toth 55646ae26e7SJonas Toth int np_local1 = np_local0; 55746ae26e7SJonas Toth np_local1 = p_local0; 55846ae26e7SJonas Toth } 55946ae26e7SJonas Toth 56046ae26e7SJonas Toth void casts() { 56146ae26e7SJonas Toth decltype(sizeof(void *)) p_local0 = 42; 56246ae26e7SJonas Toth // CHECK-MESSAGES: [[@LINE-1]]:3: warning: variable 'p_local0' of type 'decltype(sizeof(void *))' 56346ae26e7SJonas Toth // CHECK-FIXES: decltype(sizeof(void *)) const p_local0 56446ae26e7SJonas Toth auto np_local0 = reinterpret_cast<void *>(p_local0); 56546ae26e7SJonas Toth np_local0 = nullptr; 56646ae26e7SJonas Toth 56746ae26e7SJonas Toth int p_local1 = 43; 56846ae26e7SJonas Toth // CHECK-MESSAGES: [[@LINE-1]]:3: warning: variable 'p_local1' of type 'int' can be declared 'const' 56946ae26e7SJonas Toth // CHECK-FIXES: int const p_local1 57046ae26e7SJonas Toth short p_local2 = static_cast<short>(p_local1); 57146ae26e7SJonas Toth // CHECK-MESSAGES: [[@LINE-1]]:3: warning: variable 'p_local2' of type 'short' can be declared 'const' 57246ae26e7SJonas Toth // CHECK-FIXES: short const p_local2 57346ae26e7SJonas Toth 57446ae26e7SJonas Toth int np_local1 = p_local2; 57546ae26e7SJonas Toth int &np_local2 = static_cast<int &>(np_local1); 57646ae26e7SJonas Toth np_local2 = 5; 57746ae26e7SJonas Toth } 57846ae26e7SJonas Toth 57946ae26e7SJonas Toth void ternary_operator() { 58046ae26e7SJonas Toth int np_local0 = 1, np_local1 = 2; 58146ae26e7SJonas Toth int &np_local2 = true ? np_local0 : np_local1; 58246ae26e7SJonas Toth np_local2 = 2; 58346ae26e7SJonas Toth 58446ae26e7SJonas Toth int p_local0 = 3, np_local3 = 5; 58546ae26e7SJonas Toth // CHECK-MESSAGES: [[@LINE-1]]:3: warning: variable 'p_local0' of type 'int' can be declared 'const' 58646ae26e7SJonas Toth // CHECK-NOT-FIXES: int const p_local0 = 3 58746ae26e7SJonas Toth const int &np_local4 = true ? p_local0 : ++np_local3; 58846ae26e7SJonas Toth 58946ae26e7SJonas Toth int np_local5[3] = {1, 2, 3}; 59046ae26e7SJonas Toth int &np_local6 = np_local5[1] < np_local5[2] ? np_local5[0] : np_local5[2]; 59146ae26e7SJonas Toth np_local6 = 42; 59246ae26e7SJonas Toth 59346ae26e7SJonas Toth int np_local7[3] = {1, 2, 3}; 59446ae26e7SJonas Toth int *np_local8 = np_local7[1] < np_local7[2] ? &np_local7[0] : &np_local7[2]; 59546ae26e7SJonas Toth *np_local8 = 42; 59646ae26e7SJonas Toth } 59746ae26e7SJonas Toth 59846ae26e7SJonas Toth // Taken from libcxx/include/type_traits and improved readability. 59946ae26e7SJonas Toth template <class Tp, Tp v> 60046ae26e7SJonas Toth struct integral_constant { 60146ae26e7SJonas Toth static constexpr const Tp value = v; 60246ae26e7SJonas Toth using value_type = Tp; 60346ae26e7SJonas Toth using type = integral_constant; 60446ae26e7SJonas Toth constexpr operator value_type() const noexcept { return value; } 60546ae26e7SJonas Toth constexpr value_type operator()() const noexcept { return value; } 60646ae26e7SJonas Toth }; 60746ae26e7SJonas Toth 60846ae26e7SJonas Toth template <typename T> 60946ae26e7SJonas Toth struct is_integral : integral_constant<bool, false> {}; 61046ae26e7SJonas Toth template <> 61146ae26e7SJonas Toth struct is_integral<int> : integral_constant<bool, true> {}; 61246ae26e7SJonas Toth 61346ae26e7SJonas Toth template <typename T> 61446ae26e7SJonas Toth struct not_integral : integral_constant<bool, false> {}; 61546ae26e7SJonas Toth template <> 61646ae26e7SJonas Toth struct not_integral<double> : integral_constant<bool, true> {}; 61746ae26e7SJonas Toth 61846ae26e7SJonas Toth template <bool, typename Tp = void> 61946ae26e7SJonas Toth struct enable_if {}; 62046ae26e7SJonas Toth 62146ae26e7SJonas Toth template <typename Tp> 62246ae26e7SJonas Toth struct enable_if<true, Tp> { using type = Tp; }; 62346ae26e7SJonas Toth 62446ae26e7SJonas Toth template <typename T> 62546ae26e7SJonas Toth struct TMPClass { 62646ae26e7SJonas Toth T alwaysConst() const { return T{}; } 62746ae26e7SJonas Toth 62846ae26e7SJonas Toth template <typename T2 = T, typename = typename enable_if<is_integral<T2>::value>::type> 62946ae26e7SJonas Toth T sometimesConst() const { return T{}; } 63046ae26e7SJonas Toth 63146ae26e7SJonas Toth template <typename T2 = T, typename = typename enable_if<not_integral<T2>::value>::type> 63246ae26e7SJonas Toth T sometimesConst() { return T{}; } 63346ae26e7SJonas Toth }; 63446ae26e7SJonas Toth 63546ae26e7SJonas Toth void meta_type() { 63646ae26e7SJonas Toth TMPClass<int> p_local0; 63746ae26e7SJonas Toth // CHECK-MESSAGES: [[@LINE-1]]:3: warning: variable 'p_local0' of type 'TMPClass<int>' can be declared 'const' 63846ae26e7SJonas Toth // CHECK-FIXES: TMPClass<int> const p_local0 63946ae26e7SJonas Toth p_local0.alwaysConst(); 64046ae26e7SJonas Toth p_local0.sometimesConst(); 64146ae26e7SJonas Toth 64246ae26e7SJonas Toth TMPClass<double> p_local1; 64346ae26e7SJonas Toth // CHECK-MESSAGES: [[@LINE-1]]:3: warning: variable 'p_local1' of type 'TMPClass<double>' can be declared 'const' 64446ae26e7SJonas Toth // CHECK-FIXES: TMPClass<double> const p_local1 64546ae26e7SJonas Toth p_local1.alwaysConst(); 64646ae26e7SJonas Toth 64746ae26e7SJonas Toth TMPClass<double> np_local0; 64846ae26e7SJonas Toth np_local0.alwaysConst(); 64946ae26e7SJonas Toth np_local0.sometimesConst(); 65046ae26e7SJonas Toth } 65146ae26e7SJonas Toth 65246ae26e7SJonas Toth // This test is the essence from llvm/lib/Support/MemoryBuffer.cpp at line 450 65346ae26e7SJonas Toth template <typename T> 65446ae26e7SJonas Toth struct to_construct : T { 65546ae26e7SJonas Toth to_construct(int &j) {} 65646ae26e7SJonas Toth }; 65746ae26e7SJonas Toth template <typename T> 65846ae26e7SJonas Toth void placement_new_in_unique_ptr() { 65946ae26e7SJonas Toth int p_local0 = 42; 66046ae26e7SJonas Toth // CHECK-MESSAGES: [[@LINE-1]]:3: warning: variable 'p_local0' of type 'int' can be declared 'const' 66146ae26e7SJonas Toth // CHECK-FIXES: int const p_local0 66246ae26e7SJonas Toth int np_local0 = p_local0; 66346ae26e7SJonas Toth new to_construct<T>(np_local0); 66446ae26e7SJonas Toth } 66546ae26e7SJonas Toth 66646ae26e7SJonas Toth struct stream_obj {}; 66746ae26e7SJonas Toth stream_obj &operator>>(stream_obj &o, unsigned &foo); 66846ae26e7SJonas Toth void input_operator() { 66946ae26e7SJonas Toth stream_obj np_local0; 67046ae26e7SJonas Toth unsigned np_local1 = 42; 67146ae26e7SJonas Toth np_local0 >> np_local1; 67246ae26e7SJonas Toth } 67346ae26e7SJonas Toth 67446ae26e7SJonas Toth struct stream_obj_template {}; 67546ae26e7SJonas Toth template <typename IStream> 67646ae26e7SJonas Toth IStream &operator>>(IStream &o, unsigned &foo); 67746ae26e7SJonas Toth 67846ae26e7SJonas Toth template <typename Stream> 67946ae26e7SJonas Toth void input_operator_template() { 68046ae26e7SJonas Toth Stream np_local0; 68146ae26e7SJonas Toth unsigned np_local1 = 42; 68246ae26e7SJonas Toth np_local0 >> np_local1; 68346ae26e7SJonas Toth } 68446ae26e7SJonas Toth 68546ae26e7SJonas Toth // Test bit fields 68646ae26e7SJonas Toth struct HardwareRegister { 68746ae26e7SJonas Toth unsigned field : 5; 68846ae26e7SJonas Toth unsigned : 7; 68946ae26e7SJonas Toth unsigned another : 20; 69046ae26e7SJonas Toth }; 69146ae26e7SJonas Toth 69246ae26e7SJonas Toth void TestRegisters() { 69346ae26e7SJonas Toth HardwareRegister np_reg0; 69446ae26e7SJonas Toth np_reg0.field = 3; 69546ae26e7SJonas Toth 69646ae26e7SJonas Toth HardwareRegister p_reg1{3, 22}; 69746ae26e7SJonas Toth // CHECK-MESSAGES: [[@LINE-1]]:3: warning: variable 'p_reg1' of type 'HardwareRegister' can be declared 'const' 69846ae26e7SJonas Toth // CHECK-FIXES: HardwareRegister const p_reg1 69946ae26e7SJonas Toth const unsigned p_val = p_reg1.another; 70046ae26e7SJonas Toth } 70146ae26e7SJonas Toth 70246ae26e7SJonas Toth struct IntWrapper { 70346ae26e7SJonas Toth IntWrapper &operator=(unsigned value) { return *this; } 70446ae26e7SJonas Toth template <typename Istream> 70546ae26e7SJonas Toth friend Istream &operator>>(Istream &is, IntWrapper &rhs); 70646ae26e7SJonas Toth }; 70746ae26e7SJonas Toth struct IntMaker { 70846ae26e7SJonas Toth friend IntMaker &operator>>(IntMaker &, unsigned &); 70946ae26e7SJonas Toth }; 71046ae26e7SJonas Toth template <typename Istream> 71146ae26e7SJonas Toth Istream &operator>>(Istream &is, IntWrapper &rhs) { 71246ae26e7SJonas Toth unsigned np_local0 = 0; 71346ae26e7SJonas Toth is >> np_local0; 71446ae26e7SJonas Toth return is; 71546ae26e7SJonas Toth } 71646ae26e7SJonas Toth 71746ae26e7SJonas Toth struct Actuator { 71846ae26e7SJonas Toth int actuations; 71946ae26e7SJonas Toth }; 72046ae26e7SJonas Toth struct Sensor { 72146ae26e7SJonas Toth int observations; 72246ae26e7SJonas Toth }; 72346ae26e7SJonas Toth struct System : public Actuator, public Sensor { 72446ae26e7SJonas Toth }; 72546ae26e7SJonas Toth int some_computation(int arg); 72646ae26e7SJonas Toth int test_inheritance() { 72746ae26e7SJonas Toth System np_sys; 72846ae26e7SJonas Toth np_sys.actuations = 5; 72946ae26e7SJonas Toth return some_computation(np_sys.actuations); 73046ae26e7SJonas Toth } 73146ae26e7SJonas Toth struct AnotherActuator : Actuator { 73246ae26e7SJonas Toth }; 73346ae26e7SJonas Toth Actuator &test_return_polymorphic() { 73446ae26e7SJonas Toth static AnotherActuator np_local0; 73546ae26e7SJonas Toth return np_local0; 73646ae26e7SJonas Toth } 73746ae26e7SJonas Toth 73846ae26e7SJonas Toth using f_signature = int *(*)(int &); 73946ae26e7SJonas Toth int *my_alloc(int &size) { return new int[size]; } 74046ae26e7SJonas Toth struct A { 74146ae26e7SJonas Toth int f(int &i) { return i + 1; } 74246ae26e7SJonas Toth int (A::*x)(int &); 74346ae26e7SJonas Toth }; 74446ae26e7SJonas Toth void f() { 74546ae26e7SJonas Toth int p_local0 = 42; 74646ae26e7SJonas Toth // CHECK-MESSAGES: [[@LINE-1]]:3: warning: variable 'p_local0' of type 'int' can be declared 'const' 74746ae26e7SJonas Toth // CHECK-FIXES: int const p_local0 74846ae26e7SJonas Toth int np_local0 = 42; 74946ae26e7SJonas Toth f_signature action = my_alloc; 75046ae26e7SJonas Toth action(np_local0); 75146ae26e7SJonas Toth my_alloc(np_local0); 75246ae26e7SJonas Toth 75346ae26e7SJonas Toth int np_local1 = 42; 75446ae26e7SJonas Toth A a; 75546ae26e7SJonas Toth a.x = &A::f; 75646ae26e7SJonas Toth (a.*(a.x))(np_local1); 75746ae26e7SJonas Toth } 75846ae26e7SJonas Toth 75946ae26e7SJonas Toth struct nested_data { 76046ae26e7SJonas Toth int more_data; 76146ae26e7SJonas Toth }; 76246ae26e7SJonas Toth struct repro_assignment_to_reference { 76346ae26e7SJonas Toth int my_data; 76446ae26e7SJonas Toth nested_data nested; 76546ae26e7SJonas Toth }; 76646ae26e7SJonas Toth void assignment_reference() { 76746ae26e7SJonas Toth repro_assignment_to_reference np_local0{42}; 76846ae26e7SJonas Toth int &np_local1 = np_local0.my_data; 76946ae26e7SJonas Toth np_local1++; 77046ae26e7SJonas Toth 77146ae26e7SJonas Toth repro_assignment_to_reference np_local2; 77246ae26e7SJonas Toth int &np_local3 = np_local2.nested.more_data; 77346ae26e7SJonas Toth np_local3++; 77446ae26e7SJonas Toth } 77546ae26e7SJonas Toth 77646ae26e7SJonas Toth struct non_const_iterator { 77746ae26e7SJonas Toth int data[42]; 77846ae26e7SJonas Toth 77946ae26e7SJonas Toth int *begin() { return &data[0]; } 78046ae26e7SJonas Toth int *end() { return &data[41]; } 78146ae26e7SJonas Toth }; 78246ae26e7SJonas Toth 78346ae26e7SJonas Toth // The problem is, that 'begin()' and 'end()' are not const overloaded, so 78446ae26e7SJonas Toth // they are always a mutation. If 'np_local1' is fixed to const it results in 78546ae26e7SJonas Toth // a compilation error. 78646ae26e7SJonas Toth void for_bad_iterators() { 78746ae26e7SJonas Toth non_const_iterator np_local0; 78846ae26e7SJonas Toth non_const_iterator &np_local1 = np_local0; 78946ae26e7SJonas Toth 79046ae26e7SJonas Toth for (int np_local2 : np_local1) { 79146ae26e7SJonas Toth np_local2++; 79246ae26e7SJonas Toth } 79346ae26e7SJonas Toth 79446ae26e7SJonas Toth non_const_iterator np_local3; 79546ae26e7SJonas Toth for (int p_local0 : np_local3) 79646ae26e7SJonas Toth // CHECK-MESSAGES: [[@LINE-1]]:8: warning: variable 'p_local0' of type 'int' can be declared 'const' 79746ae26e7SJonas Toth // CHECK-FIXES: int const p_local0 79846ae26e7SJonas Toth ; 79946ae26e7SJonas Toth 80046ae26e7SJonas Toth // Horrible code constructs... 80146ae26e7SJonas Toth { 80246ae26e7SJonas Toth non_const_iterator np_local4; 80346ae26e7SJonas Toth np_local4.data[0]++; 80446ae26e7SJonas Toth non_const_iterator np_local5; 80546ae26e7SJonas Toth for (int p_local1 : np_local4, np_local5) 80646ae26e7SJonas Toth // CHECK-MESSAGES: [[@LINE-1]]:10: warning: variable 'p_local1' of type 'int' can be declared 'const' 80746ae26e7SJonas Toth // CHECK-FIXES: int const p_local1 80846ae26e7SJonas Toth ; 80946ae26e7SJonas Toth 81046ae26e7SJonas Toth non_const_iterator np_local6; 81146ae26e7SJonas Toth non_const_iterator np_local7; 81246ae26e7SJonas Toth for (int p_local2 : 1 > 2 ? np_local6 : np_local7) 81346ae26e7SJonas Toth // CHECK-MESSAGES: [[@LINE-1]]:10: warning: variable 'p_local2' of type 'int' can be declared 'const' 81446ae26e7SJonas Toth // CHECK-FIXES: int const p_local2 81546ae26e7SJonas Toth ; 81646ae26e7SJonas Toth 81746ae26e7SJonas Toth non_const_iterator np_local8; 81846ae26e7SJonas Toth non_const_iterator np_local9; 81946ae26e7SJonas Toth for (int p_local3 : 2 > 1 ? np_local8 : (np_local8, np_local9)) 82046ae26e7SJonas Toth // CHECK-MESSAGES: [[@LINE-1]]:10: warning: variable 'p_local3' of type 'int' can be declared 'const' 82146ae26e7SJonas Toth // CHECK-FIXES: int const p_local3 82246ae26e7SJonas Toth ; 82346ae26e7SJonas Toth } 82446ae26e7SJonas Toth } 82546ae26e7SJonas Toth 82646ae26e7SJonas Toth struct good_iterator { 82746ae26e7SJonas Toth int data[3] = {1, 2, 3}; 82846ae26e7SJonas Toth 82946ae26e7SJonas Toth int *begin() { return &data[0]; } 83046ae26e7SJonas Toth int *end() { return &data[2]; } 83146ae26e7SJonas Toth const int *begin() const { return &data[0]; } 83246ae26e7SJonas Toth const int *end() const { return &data[2]; } 83346ae26e7SJonas Toth }; 83446ae26e7SJonas Toth 83546ae26e7SJonas Toth void good_iterators() { 83646ae26e7SJonas Toth good_iterator p_local0; 83746ae26e7SJonas Toth // CHECK-MESSAGES: [[@LINE-1]]:3: warning: variable 'p_local0' of type 'good_iterator' can be declared 'const' 83846ae26e7SJonas Toth // CHECK-FIXES: good_iterator const p_local0 83946ae26e7SJonas Toth good_iterator &p_local1 = p_local0; 84046ae26e7SJonas Toth // CHECK-MESSAGES: [[@LINE-1]]:3: warning: variable 'p_local1' of type 'good_iterator &' can be declared 'const' 84146ae26e7SJonas Toth // CHECK-FIXES: good_iterator const&p_local1 84246ae26e7SJonas Toth 84346ae26e7SJonas Toth for (int p_local2 : p_local1) { 84446ae26e7SJonas Toth // CHECK-MESSAGES: [[@LINE-1]]:8: warning: variable 'p_local2' of type 'int' can be declared 'const' 84546ae26e7SJonas Toth // CHECK-FIXES: int const p_local2 84646ae26e7SJonas Toth (void)p_local2; 84746ae26e7SJonas Toth } 84846ae26e7SJonas Toth 84946ae26e7SJonas Toth good_iterator p_local3; 85046ae26e7SJonas Toth // CHECK-MESSAGES: [[@LINE-1]]:3: warning: variable 'p_local3' of type 'good_iterator' can be declared 'const' 85146ae26e7SJonas Toth // CHECK-FIXES: good_iterator const p_local3 85246ae26e7SJonas Toth for (int p_local4 : p_local3) 85346ae26e7SJonas Toth // CHECK-MESSAGES: [[@LINE-1]]:8: warning: variable 'p_local4' of type 'int' can be declared 'const' 85446ae26e7SJonas Toth // CHECK-FIXES: int const p_local4 85546ae26e7SJonas Toth ; 85646ae26e7SJonas Toth good_iterator np_local1; 85746ae26e7SJonas Toth for (int &np_local2 : np_local1) 85846ae26e7SJonas Toth np_local2++; 85946ae26e7SJonas Toth } 86046ae26e7SJonas Toth 86146ae26e7SJonas Toth void for_bad_iterators_array() { 86246ae26e7SJonas Toth int np_local0[42]; 86346ae26e7SJonas Toth int(&np_local1)[42] = np_local0; 86446ae26e7SJonas Toth 86546ae26e7SJonas Toth for (int &np_local2 : np_local1) { 86646ae26e7SJonas Toth np_local2++; 86746ae26e7SJonas Toth } 86846ae26e7SJonas Toth } 86946ae26e7SJonas Toth void for_ok_iterators_array() { 87046ae26e7SJonas Toth int np_local0[42]; 87146ae26e7SJonas Toth int(&p_local0)[42] = np_local0; 87246ae26e7SJonas Toth // CHECK-MESSAGES: [[@LINE-1]]:3: warning: variable 'p_local0' of type 'int (&)[42]' can be declared 'const' 87346ae26e7SJonas Toth // CHECK-FIXES: int const(&p_local0)[42] 87446ae26e7SJonas Toth 87546ae26e7SJonas Toth for (int p_local1 : p_local0) { 87646ae26e7SJonas Toth // CHECK-MESSAGES: [[@LINE-1]]:8: warning: variable 'p_local1' of type 'int' can be declared 'const' 87746ae26e7SJonas Toth // CHECK-FIXES: int const p_local1 87846ae26e7SJonas Toth (void)p_local1; 87946ae26e7SJonas Toth } 88046ae26e7SJonas Toth } 88146ae26e7SJonas Toth 88246ae26e7SJonas Toth void take_ref(int &); 88346ae26e7SJonas Toth void ternary_reference() { 88446ae26e7SJonas Toth int np_local0 = 42; 88546ae26e7SJonas Toth int np_local1 = 43; 88646ae26e7SJonas Toth take_ref((np_local0 > np_local1 ? np_local0 : (np_local0, np_local1))); 88746ae26e7SJonas Toth } 88846ae26e7SJonas Toth 88946ae26e7SJonas Toth void complex_usage() { 89046ae26e7SJonas Toth int np_local0 = 42; 89146ae26e7SJonas Toth int p_local0 = 42; 89246ae26e7SJonas Toth // CHECK-MESSAGES: [[@LINE-1]]:3: warning: variable 'p_local0' of type 'int' can be declared 'const' 89346ae26e7SJonas Toth // CHECK-FIXES: int const p_local0 89446ae26e7SJonas Toth int np_local1 = 42; 89546ae26e7SJonas Toth (np_local0 == p_local0 ? np_local0 : (p_local0, np_local1))++; 89646ae26e7SJonas Toth } 89746ae26e7SJonas Toth 89846ae26e7SJonas Toth void vlas() { 89946ae26e7SJonas Toth int N = 1; // Can't make N 'const' because VLAs make everything awful 90046ae26e7SJonas Toth sizeof(int[++N]); 90146ae26e7SJonas Toth } 90246ae26e7SJonas Toth 90346ae26e7SJonas Toth struct base { 90446ae26e7SJonas Toth int member; 90546ae26e7SJonas Toth }; 90646ae26e7SJonas Toth struct derived : base {}; 90746ae26e7SJonas Toth struct another_struct { 90846ae26e7SJonas Toth derived member; 90946ae26e7SJonas Toth }; 91046ae26e7SJonas Toth void another_struct_f() { 91146ae26e7SJonas Toth another_struct np_local0{}; 91246ae26e7SJonas Toth base &np_local1 = np_local0.member; 91346ae26e7SJonas Toth np_local1.member++; 91446ae26e7SJonas Toth } 91546ae26e7SJonas Toth struct list_init { 91646ae26e7SJonas Toth int &member; 91746ae26e7SJonas Toth }; 91846ae26e7SJonas Toth void create_false_positive() { 91946ae26e7SJonas Toth int np_local0 = 42; 92046ae26e7SJonas Toth list_init p_local0 = {np_local0}; 92146ae26e7SJonas Toth // CHECK-MESSAGES:[[@LINE-1]]:3: warning: variable 'p_local0' of type 'list_init' can be declared 'const' 92246ae26e7SJonas Toth // CHECK-FIXES: list_init const p_local0 92346ae26e7SJonas Toth } 92446ae26e7SJonas Toth struct list_init_derived { 92546ae26e7SJonas Toth base &member; 92646ae26e7SJonas Toth }; 92746ae26e7SJonas Toth void list_init_derived_func() { 92846ae26e7SJonas Toth derived np_local0; 92946ae26e7SJonas Toth list_init_derived p_local0 = {np_local0}; 93046ae26e7SJonas Toth // CHECK-MESSAGES:[[@LINE-1]]:3: warning: variable 'p_local0' of type 'list_init_derived' can be declared 'const' 93146ae26e7SJonas Toth // CHECK-FIXES: list_init_derived const p_local0 93246ae26e7SJonas Toth } 93346ae26e7SJonas Toth template <typename L, typename R> 93446ae26e7SJonas Toth struct ref_pair { 93546ae26e7SJonas Toth L &first; 93646ae26e7SJonas Toth R &second; 93746ae26e7SJonas Toth }; 93846ae26e7SJonas Toth template <typename T> 93946ae26e7SJonas Toth void list_init_template() { 94046ae26e7SJonas Toth T np_local0{}; 94146ae26e7SJonas Toth ref_pair<T, T> p_local0 = {np_local0, np_local0}; 94246ae26e7SJonas Toth } 94346ae26e7SJonas Toth void cast_in_class_hierarchy() { 94446ae26e7SJonas Toth derived np_local0; 94546ae26e7SJonas Toth base p_local1 = static_cast<base &>(np_local0); 94646ae26e7SJonas Toth // CHECK-MESSAGES:[[@LINE-1]]:3: warning: variable 'p_local1' of type 'base' can be declared 'const' 94746ae26e7SJonas Toth // CHECK-FIXES: base const p_local1 94846ae26e7SJonas Toth } 94946ae26e7SJonas Toth 95046ae26e7SJonas Toth void function_ref_target(int); 95146ae26e7SJonas Toth using my_function_type = void (&)(int); 95246ae26e7SJonas Toth void func_references() { 95346ae26e7SJonas Toth // Could be const, because the reference is not adjusted but adding that 95446ae26e7SJonas Toth // has no effect and creates a compiler warning. 95546ae26e7SJonas Toth my_function_type ptr = function_ref_target; 95646ae26e7SJonas Toth } 95746ae26e7SJonas Toth 95846ae26e7SJonas Toth template <typename T> 95946ae26e7SJonas Toth T &return_ref() { 96046ae26e7SJonas Toth static T global; 96146ae26e7SJonas Toth return global; 96246ae26e7SJonas Toth } 96346ae26e7SJonas Toth template <typename T> 96446ae26e7SJonas Toth T *return_ptr() { return &return_ref<T>(); } 96546ae26e7SJonas Toth 96646ae26e7SJonas Toth void auto_usage_variants() { 96746ae26e7SJonas Toth auto auto_val0 = int{}; 96846ae26e7SJonas Toth // CHECK-FIXES-NOT: auto const auto_val0 96946ae26e7SJonas Toth auto &auto_val1 = auto_val0; 97046ae26e7SJonas Toth auto *auto_val2 = &auto_val0; 97146ae26e7SJonas Toth 97246ae26e7SJonas Toth auto auto_ref0 = return_ref<int>(); 97346ae26e7SJonas Toth // CHECK-FIXES-NOT: auto const auto_ref0 97446ae26e7SJonas Toth auto &auto_ref1 = return_ref<int>(); // Bad 97546ae26e7SJonas Toth auto *auto_ref2 = return_ptr<int>(); 97646ae26e7SJonas Toth 97746ae26e7SJonas Toth auto auto_ptr0 = return_ptr<int>(); 97846ae26e7SJonas Toth // CHECK-FIXES-NOT: auto const auto_ptr0 97946ae26e7SJonas Toth auto &auto_ptr1 = auto_ptr0; 98046ae26e7SJonas Toth auto *auto_ptr2 = return_ptr<int>(); 98146ae26e7SJonas Toth 98246ae26e7SJonas Toth using MyTypedef = int; 98346ae26e7SJonas Toth auto auto_td0 = MyTypedef{}; 98446ae26e7SJonas Toth // CHECK-FIXES-NOT: auto const auto_td0 98546ae26e7SJonas Toth auto &auto_td1 = auto_td0; 98646ae26e7SJonas Toth auto *auto_td2 = &auto_td0; 98746ae26e7SJonas Toth } 988feb7b191SCongcong Cai 989feb7b191SCongcong Cai using PointerToMemberFunction = int (Value::*)(); 990feb7b191SCongcong Cai void member_pointer(Value &x, PointerToMemberFunction m) { 991feb7b191SCongcong Cai Value &member_pointer_tmp = x; 992feb7b191SCongcong Cai (member_pointer_tmp.*m)(); 993feb7b191SCongcong Cai } 994feb7b191SCongcong Cai 995feb7b191SCongcong Cai using PointerToConstMemberFunction = int (Value::*)() const; 996feb7b191SCongcong Cai void member_pointer_const(Value &x, PointerToConstMemberFunction m) { 997feb7b191SCongcong Cai Value &member_pointer_tmp = x; 998feb7b191SCongcong Cai // CHECK-MESSAGES:[[@LINE-1]]:3: warning: variable 'member_pointer_tmp' of type 'Value &' can be declared 'const' 999feb7b191SCongcong Cai (member_pointer_tmp.*m)(); 1000feb7b191SCongcong Cai } 1001