1// RUN: %check_clang_tidy %s cppcoreguidelines-pro-bounds-constant-array-index %t
2
3typedef __SIZE_TYPE__ size_t;
4
5namespace std {
6 template<typename T, size_t N>
7 struct array {
8 T& operator[](size_t n);
9 T& at(size_t n);
10 };
11}
12
13
14namespace gsl {
15 template<class T, size_t N>
16 T& at( T(&a)[N], size_t index );
17
18 template<class T, size_t N>
19 T& at( std::array<T, N> &a, size_t index );
20}
21
22constexpr int const_index(int base) {
23 return base + 3;
24}
25
26template<class T, size_t N>
27class DerivedArray : public std::array<T, N> {};
28
29void f(std::array<int, 10> a, int pos) {
30 a [ pos / 2 /*comment*/] = 1;
31 // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: do not use array subscript when the index is not an integer constant expression [cppcoreguidelines-pro-bounds-constant-array-index]
32 int j = a[pos - 1];
33 // CHECK-MESSAGES: :[[@LINE-1]]:11: warning: do not use array subscript when the index is not an integer constant expression
34
35 a.at(n: pos-1) = 2; // OK, at() instead of []
36 gsl::at(a, index: pos-1) = 2; // OK, gsl::at() instead of []
37
38 a[-1] = 3;
39 // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: std::array<> index -1 is negative [cppcoreguidelines-pro-bounds-constant-array-index]
40 a[10] = 4;
41 // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: std::array<> index 10 is past the end of the array (which contains 10 elements) [cppcoreguidelines-pro-bounds-constant-array-index]
42
43 a[const_index(base: 7)] = 3;
44 // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: std::array<> index 10 is past the end of the array (which contains 10 elements)
45
46 a[0] = 3; // OK, constant index and inside bounds
47 a[1] = 3; // OK, constant index and inside bounds
48 a[9] = 3; // OK, constant index and inside bounds
49 a[const_index(base: 6)] = 3; // OK, constant index and inside bounds
50
51 using MyArray = std::array<int, 10>;
52 MyArray m{};
53 m [ pos / 2 /*comment*/] = 1;
54 // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: do not use array subscript when the index is not an integer constant expression [cppcoreguidelines-pro-bounds-constant-array-index]
55 int jj = m[pos - 1];
56 // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: do not use array subscript when the index is not an integer constant expression
57
58 m.at(n: pos-1) = 2; // OK, at() instead of []
59 gsl::at(a&: m, index: pos-1) = 2; // OK, gsl::at() instead of []
60 m[-1] = 3;
61 // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: std::array<> index -1 is negative [cppcoreguidelines-pro-bounds-constant-array-index]
62 m[10] = 4;
63 // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: std::array<> index 10 is past the end of the array (which contains 10 elements) [cppcoreguidelines-pro-bounds-constant-array-index]
64
65 m[const_index(base: 7)] = 3;
66 // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: std::array<> index 10 is past the end of the array (which contains 10 elements)
67
68 m[0] = 3; // OK, constant index and inside bounds
69 m[1] = 3; // OK, constant index and inside bounds
70 m[9] = 3; // OK, constant index and inside bounds
71 m[const_index(base: 6)] = 3; // OK, constant index and inside bounds
72}
73
74template<class T, size_t N>
75class PrivateDerivedArray : std::array<T, N> {
76public:
77 T& operator[](size_t n){
78 return std::array<T, N>::operator[](static_cast<int>(n));
79 };
80 T& at(size_t n) {
81 return std::array<T, N>::at(static_cast<int>(n));
82 };
83};
84
85void f_derived(DerivedArray<int, 10> a, int pos) {
86 a [ pos / 2 /*comment*/] = 1;
87 // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: do not use array subscript when the index is not an integer constant expression [cppcoreguidelines-pro-bounds-constant-array-index]
88 int j = a[pos - 1];
89 // CHECK-MESSAGES: :[[@LINE-1]]:11: warning: do not use array subscript when the index is not an integer constant expression
90
91 a.at(n: pos-1) = 2; // OK, at() instead of []
92 gsl::at(a, index: pos-1) = 2; // OK, gsl::at() instead of []
93
94 a[-1] = 3;
95 // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: std::array<> index -1 is negative [cppcoreguidelines-pro-bounds-constant-array-index]
96 a[10] = 4;
97 // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: std::array<> index 10 is past the end of the array (which contains 10 elements) [cppcoreguidelines-pro-bounds-constant-array-index]
98
99 a[const_index(base: 7)] = 3;
100 // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: std::array<> index 10 is past the end of the array (which contains 10 elements)
101
102 a[0] = 3; // OK, constant index and inside bounds
103 a[1] = 3; // OK, constant index and inside bounds
104 a[9] = 3; // OK, constant index and inside bounds
105 a[const_index(base: 6)] = 3; // OK, constant index and inside bounds
106
107 using MyArray = DerivedArray<int, 10>;
108 MyArray m{};
109 m [ pos / 2 /*comment*/] = 1;
110 // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: do not use array subscript when the index is not an integer constant expression [cppcoreguidelines-pro-bounds-constant-array-index]
111 int jj = m[pos - 1];
112 // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: do not use array subscript when the index is not an integer constant expression
113
114 m.at(n: pos-1) = 2; // OK, at() instead of []
115 gsl::at(a&: m, index: pos-1) = 2; // OK, gsl::at() instead of []
116 m[-1] = 3;
117 // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: std::array<> index -1 is negative [cppcoreguidelines-pro-bounds-constant-array-index]
118 m[10] = 4;
119 // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: std::array<> index 10 is past the end of the array (which contains 10 elements) [cppcoreguidelines-pro-bounds-constant-array-index]
120
121 m[const_index(base: 7)] = 3;
122 // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: std::array<> index 10 is past the end of the array (which contains 10 elements)
123
124 m[0] = 3; // OK, constant index and inside bounds
125 m[1] = 3; // OK, constant index and inside bounds
126 m[9] = 3; // OK, constant index and inside bounds
127 m[const_index(base: 6)] = 3; // OK, constant index and inside bounds
128
129 using MyPrivateArray = PrivateDerivedArray<int, 10>;
130 MyPrivateArray pm{};
131 pm [ pos / 2 /*comment*/] = 1;
132 int jjj = pm[pos - 1];
133
134 pm.at(n: pos-1) = 2; // OK, at() instead of []
135 pm[-1] = 3;
136 pm[10] = 4;
137
138 pm[const_index(base: 7)] = 3;
139
140 pm[0] = 3; // OK, constant index and inside bounds
141 pm[1] = 3; // OK, constant index and inside bounds
142 pm[9] = 3; // OK, constant index and inside bounds
143 pm[const_index(base: 6)] = 3; // OK, constant index and inside bounds
144}
145
146
147
148
149void g() {
150 int a[10];
151 for (int i = 0; i < 10; ++i) {
152 a[i] = i;
153 // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: do not use array subscript when the index is not an integer constant expression
154 // CHECK-FIXES: gsl::at(a, i) = i;
155 gsl::at(a, index: i) = i; // OK, gsl::at() instead of []
156 }
157
158 a[-1] = 3; // flagged by clang-diagnostic-array-bounds
159 a[10] = 4; // flagged by clang-diagnostic-array-bounds
160 a[const_index(base: 7)] = 3; // flagged by clang-diagnostic-array-bounds
161
162 a[0] = 3; // OK, constant index and inside bounds
163 a[1] = 3; // OK, constant index and inside bounds
164 a[9] = 3; // OK, constant index and inside bounds
165 a[const_index(base: 6)] = 3; // OK, constant index and inside bounds
166}
167
168struct S {
169 int& operator[](int i);
170};
171
172void customOperator() {
173 S s;
174 int i = 0;
175 s[i] = 3; // OK, custom operator
176}
177
178namespace ArrayInitIndexExpr {
179struct A {
180 // The compiler-generated copy constructor uses an ArraySubscriptExpr. Don't warn.
181 int x[3];
182};
183
184void implicitCopyMoveCtor() {
185 // Force the compiler to generate a copy constructor.
186 A a;
187 A a2(a);
188
189 // Force the compiler to generate a move constructor.
190 A a3 = (A&&) a;
191}
192
193void lambdaCapture() {
194 int arr[3];
195
196 // Capturing an array by value uses an ArraySubscriptExpr. Don't warn.
197 [arr](){};
198}
199
200#if __cplusplus >= 201703L
201void structuredBindings() {
202 int arr[3];
203
204 // Creating structured bindings by value uses an ArraySubscriptExpr. Don't warn.
205 auto [a,b,c] = arr;
206}
207#endif
208} // namespace ArrayInitIndexExpr
209

source code of clang-tools-extra/test/clang-tidy/checkers/cppcoreguidelines/pro-bounds-constant-array-index.cpp