1 // RUN: %check_clang_tidy %s cppcoreguidelines-pro-bounds-constant-array-index %t -- \
2 // RUN:     -config='{CheckOptions: [{key: cppcoreguidelines-pro-bounds-constant-array-index.GslHeader, value: "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 
const_index(int base)24 constexpr int const_index(int base) {
25   return base + 3;
26 }
27 
f(std::array<int,10> a,int pos)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; use gsl::at() instead [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; use gsl::at() instead
34   // CHECK-FIXES: int j = gsl::at(a, pos - 1);
35 
36   a.at(pos-1) = 2; // OK, at() instead of []
37   gsl::at(a, 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(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(6)] = 3; // OK, constant index and inside bounds
51 }
52 
g()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; use gsl::at() instead
58     // CHECK-FIXES: gsl::at(a, i) = i;
59     gsl::at(a, 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(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(6)] = 3; // OK, constant index and inside bounds
70 }
71 
72 struct S {
73   int& operator[](int i);
74 };
75 
customOperator()76 void customOperator() {
77   S s;
78   int i = 0;
79   s[i] = 3; // OK, custom operator
80 }
81