1 // RUN: %check_clang_tidy %s misc-const-correctness %t -- \
2 // RUN:   -config="{CheckOptions: {\
3 // RUN:   misc-const-correctness.TransformValues: true,\
4 // RUN:   misc-const-correctness.WarnPointersAsValues: false, \
5 // RUN:   misc-const-correctness.TransformPointersAsValues: false} \
6 // RUN:   }" -- -fno-delayed-template-parsing
7 
8 bool global;
9 char np_global = 0; // globals can't be known to be const
10 
11 namespace foo {
12 int scoped;
13 float np_scoped = 1; // namespace variables are like globals
14 } // namespace foo
15 
16 // Lambdas should be ignored, because they do not follow the normal variable
17 // semantic (e.g. the type is only known to the compiler).
lambdas()18 void lambdas() {
19   auto Lambda = [](int i) { return i < 0; };
20 }
21 
22 void some_function(double, wchar_t);
23 
some_function(double np_arg0,wchar_t np_arg1)24 void some_function(double np_arg0, wchar_t np_arg1) {
25   int p_local0 = 2;
26   // CHECK-MESSAGES: [[@LINE-1]]:3: warning: variable 'p_local0' of type 'int' can be declared 'const'
27   // CHECK-FIXES: int const p_local0 = 2;
28 }
29 
nested_scopes()30 void nested_scopes() {
31   {
32     int p_local1 = 42;
33     // CHECK-MESSAGES: [[@LINE-1]]:5: warning: variable 'p_local1' of type 'int' can be declared 'const'
34     // CHECK-FIXES: int const p_local1 = 42;
35   }
36 }
37 
38 template <typename T>
define_locals(T np_arg0,T & np_arg1,int np_arg2)39 void define_locals(T np_arg0, T &np_arg1, int np_arg2) {
40   T np_local0 = 0;
41   int p_local1 = 42;
42   // CHECK-MESSAGES: [[@LINE-1]]:3: warning: variable 'p_local1' of type 'int' can be declared 'const'
43   // CHECK-FIXES: int const p_local1 = 42;
44 }
45 
template_instantiation()46 void template_instantiation() {
47   const int np_local0 = 42;
48   int np_local1 = 42;
49 
50   define_locals(np_local0, np_local1, np_local0);
51   define_locals(np_local1, np_local1, np_local1);
52 }
53 
54 struct ConstNonConstClass {
55   ConstNonConstClass();
56   ConstNonConstClass(double &np_local0);
nonConstMethodConstNonConstClass57   double nonConstMethod() {}
constMethodConstNonConstClass58   double constMethod() const {}
59   double modifyingMethod(double &np_arg0) const;
60 
61   double NonConstMember;
62   const double ConstMember;
63 
64   double &NonConstMemberRef;
65   const double &ConstMemberRef;
66 
67   double *NonConstMemberPtr;
68   const double *ConstMemberPtr;
69 };
70 
direct_class_access()71 void direct_class_access() {
72   ConstNonConstClass p_local0;
73   // CHECK-MESSAGES: [[@LINE-1]]:3: warning: variable 'p_local0' of type 'ConstNonConstClass' can be declared 'const'
74   // CHECK-FIXES: ConstNonConstClass const p_local0;
75   p_local0.constMethod();
76 }
77 
class_access_array()78 void class_access_array() {
79   ConstNonConstClass p_local0[2];
80   // CHECK-MESSAGES: [[@LINE-1]]:3: warning: variable 'p_local0' of type 'ConstNonConstClass[2]' can be declared 'const'
81   // CHECK-FIXES: ConstNonConstClass const p_local0[2];
82   p_local0[0].constMethod();
83 }
84 
85 struct MyVector {
86   double *begin();
87   const double *begin() const;
88 
89   double *end();
90   const double *end() const;
91 
92   double &operator[](int index);
93   double operator[](int index) const;
94 
95   double values[100];
96 };
97 
vector_usage()98 void vector_usage() {
99   double p_local0[10] = {0., 1., 2., 3., 4., 5., 6., 7., 8., 9.};
100   // CHECK-MESSAGES: [[@LINE-1]]:3: warning: variable 'p_local0' of type 'double[10]' can be declared 'const'
101   // CHECK-FIXES: double const p_local0[10] = {0., 1., 2., 3., 4., 5., 6., 7., 8., 9.};
102 }
103 
range_for()104 void range_for() {
105   int np_local0[2] = {1, 2};
106   // The transformation is not possible because the range-for-loop mutates the array content.
107   int *const np_local1[2] = {&np_local0[0], &np_local0[1]};
108   for (int *non_const_ptr : np_local1) {
109     *non_const_ptr = 45;
110   }
111 
112   int *np_local2[2] = {&np_local0[0], &np_local0[1]};
113   for (int *non_const_ptr : np_local2) {
114     *non_const_ptr = 45;
115   }
116 }
117 
decltype_declaration()118 void decltype_declaration() {
119   decltype(sizeof(void *)) p_local0 = 42;
120   // CHECK-MESSAGES: [[@LINE-1]]:3: warning: variable 'p_local0' of type 'decltype(sizeof(void *))'
121   // CHECK-FIXES: decltype(sizeof(void *)) const p_local0 = 42;
122 }
123 
124 // Taken from libcxx/include/type_traits and improved readability.
125 template <class Tp, Tp v>
126 struct integral_constant {
127   static constexpr const Tp value = v;
128   using value_type = Tp;
129   using type = integral_constant;
operator value_typeintegral_constant130   constexpr operator value_type() const noexcept { return value; }
operator ()integral_constant131   constexpr value_type operator()() const noexcept { return value; }
132 };
133 
134 template <typename T>
135 struct is_integral : integral_constant<bool, false> {};
136 template <>
137 struct is_integral<int> : integral_constant<bool, true> {};
138 
139 template <typename T>
140 struct not_integral : integral_constant<bool, false> {};
141 template <>
142 struct not_integral<double> : integral_constant<bool, true> {};
143 
144 template <bool, typename Tp = void>
145 struct enable_if {};
146 
147 template <typename Tp>
148 struct enable_if<true, Tp> { using type = Tp; };
149 
150 template <typename T>
151 struct TMPClass {
alwaysConstTMPClass152   T alwaysConst() const { return T{}; }
153 
154   template <typename T2 = T, typename = typename enable_if<is_integral<T2>::value>::type>
sometimesConstTMPClass155   T sometimesConst() const { return T{}; }
156 
157   template <typename T2 = T, typename = typename enable_if<not_integral<T2>::value>::type>
sometimesConstTMPClass158   T sometimesConst() { return T{}; }
159 };
160 
meta_type()161 void meta_type() {
162   TMPClass<int> p_local0;
163   // CHECK-MESSAGES: [[@LINE-1]]:3: warning: variable 'p_local0' of type 'TMPClass<int>' can be declared 'const'
164   // CHECK-FIXES: TMPClass<int> const p_local0;
165   p_local0.alwaysConst();
166   p_local0.sometimesConst();
167 
168   TMPClass<double> p_local1;
169   // CHECK-MESSAGES: [[@LINE-1]]:3: warning: variable 'p_local1' of type 'TMPClass<double>' can be declared 'const'
170   // CHECK-FIXES: TMPClass<double> const p_local1;
171   p_local1.alwaysConst();
172 
173   TMPClass<double> p_local2; // Don't attempt to make this const
174   p_local2.sometimesConst();
175 }
176