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
8bool global;
9char np_global = 0; // globals can't be known to be const
10
11namespace foo {
12int scoped;
13float 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).
18void lambdas() {
19 auto Lambda = [](int i) { return i < 0; };
20}
21
22void some_function(double, wchar_t);
23
24void 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
30void 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
38template <typename T>
39void 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
46void template_instantiation() {
47 const int np_local0 = 42;
48 int np_local1 = 42;
49
50 define_locals(np_arg0: np_local0, np_arg1&: np_local1, np_arg2: np_local0);
51 define_locals(np_arg0: np_local1, np_arg1&: np_local1, np_arg2: np_local1);
52}
53
54struct ConstNonConstClass {
55 ConstNonConstClass();
56 ConstNonConstClass(double &np_local0);
57 double nonConstMethod() {}
58 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
71void 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
78void 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
85struct 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
98void 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
104void 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
118void 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.
125template <class Tp, Tp v>
126struct integral_constant {
127 static constexpr const Tp value = v;
128 using value_type = Tp;
129 using type = integral_constant;
130 constexpr operator value_type() const noexcept { return value; }
131 constexpr value_type operator()() const noexcept { return value; }
132};
133
134template <typename T>
135struct is_integral : integral_constant<bool, false> {};
136template <>
137struct is_integral<int> : integral_constant<bool, true> {};
138
139template <typename T>
140struct not_integral : integral_constant<bool, false> {};
141template <>
142struct not_integral<double> : integral_constant<bool, true> {};
143
144template <bool, typename Tp = void>
145struct enable_if {};
146
147template <typename Tp>
148struct enable_if<true, Tp> { using type = Tp; };
149
150template <typename T>
151struct TMPClass {
152 T alwaysConst() const { return T{}; }
153
154 template <typename T2 = T, typename = typename enable_if<is_integral<T2>::value>::type>
155 T sometimesConst() const { return T{}; }
156
157 template <typename T2 = T, typename = typename enable_if<not_integral<T2>::value>::type>
158 T sometimesConst() { return T{}; }
159};
160
161void 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

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