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

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