1 | // RUN: %check_clang_tidy %s cppcoreguidelines-pro-bounds-constant-array-index %t -- \ |
2 | // RUN: -config='{CheckOptions: {cppcoreguidelines-pro-bounds-constant-array-index.GslHeader: "dir1/gslheader.h"}}' |
3 | // CHECK-FIXES: #include "dir1/gslheader.h" |
4 | |
5 | typedef __SIZE_TYPE__ size_t; |
6 | |
7 | namespace std { |
8 | template<typename T, size_t N> |
9 | struct array { |
10 | T& operator[](size_t n); |
11 | T& at(size_t n); |
12 | }; |
13 | } |
14 | |
15 | |
16 | namespace gsl { |
17 | template<class T, size_t N> |
18 | T& at( T(&a)[N], size_t index ); |
19 | |
20 | template<class T, size_t N> |
21 | T& at( std::array<T, N> &a, size_t index ); |
22 | } |
23 | |
24 | constexpr int const_index(int base) { |
25 | return base + 3; |
26 | } |
27 | |
28 | void f(std::array<int, 10> a, int pos) { |
29 | a [ pos / 2 /*comment*/] = 1; |
30 | // 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] |
31 | // CHECK-FIXES: gsl::at(a, pos / 2 /*comment*/) = 1; |
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 | // CHECK-FIXES: int j = gsl::at(a, pos - 1); |
35 | |
36 | a.at(n: pos-1) = 2; // OK, at() instead of [] |
37 | gsl::at(a, index: pos-1) = 2; // OK, gsl::at() instead of [] |
38 | |
39 | a[-1] = 3; |
40 | // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: std::array<> index -1 is negative [cppcoreguidelines-pro-bounds-constant-array-index] |
41 | a[10] = 4; |
42 | // 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] |
43 | |
44 | a[const_index(base: 7)] = 3; |
45 | // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: std::array<> index 10 is past the end of the array (which contains 10 elements) |
46 | |
47 | a[0] = 3; // OK, constant index and inside bounds |
48 | a[1] = 3; // OK, constant index and inside bounds |
49 | a[9] = 3; // OK, constant index and inside bounds |
50 | a[const_index(base: 6)] = 3; // OK, constant index and inside bounds |
51 | } |
52 | |
53 | void g() { |
54 | int a[10]; |
55 | for (int i = 0; i < 10; ++i) { |
56 | a[i] = i; |
57 | // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: do not use array subscript when the index is not an integer constant expression |
58 | // CHECK-FIXES: gsl::at(a, i) = i; |
59 | gsl::at(a, index: i) = i; // OK, gsl::at() instead of [] |
60 | } |
61 | |
62 | a[-1] = 3; // flagged by clang-diagnostic-array-bounds |
63 | a[10] = 4; // flagged by clang-diagnostic-array-bounds |
64 | a[const_index(base: 7)] = 3; // flagged by clang-diagnostic-array-bounds |
65 | |
66 | a[0] = 3; // OK, constant index and inside bounds |
67 | a[1] = 3; // OK, constant index and inside bounds |
68 | a[9] = 3; // OK, constant index and inside bounds |
69 | a[const_index(base: 6)] = 3; // OK, constant index and inside bounds |
70 | } |
71 | |
72 | struct S { |
73 | int& operator[](int i); |
74 | }; |
75 | |
76 | void customOperator() { |
77 | S s; |
78 | int i = 0; |
79 | s[i] = 3; // OK, custom operator |
80 | } |
81 | |