xref: /llvm-project/clang-tools-extra/test/clang-tidy/checkers/misc/const-correctness-values.cpp (revision 2dd82c5ac56623d38de977ef027b252b4908e4c5)
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