1 // RUN: %check_clang_tidy %s cppcoreguidelines-pro-bounds-constant-array-index %t 2 3 typedef __SIZE_TYPE__ size_t; 4 5 namespace 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 14 namespace 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 22 constexpr int const_index(int base) { 23 return base + 3; 24 } 25 26 void f(std::array<int, 10> a, int pos) { 27 a [ pos / 2 /*comment*/] = 1; 28 // 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] 29 int j = a[pos - 1]; 30 // CHECK-MESSAGES: :[[@LINE-1]]:11: warning: do not use array subscript when the index is not an integer constant expression 31 32 a.at(pos-1) = 2; // OK, at() instead of [] 33 gsl::at(a, pos-1) = 2; // OK, gsl::at() instead of [] 34 35 a[-1] = 3; 36 // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: std::array<> index -1 is negative [cppcoreguidelines-pro-bounds-constant-array-index] 37 a[10] = 4; 38 // 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] 39 40 a[const_index(7)] = 3; 41 // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: std::array<> index 10 is past the end of the array (which contains 10 elements) 42 43 a[0] = 3; // OK, constant index and inside bounds 44 a[1] = 3; // OK, constant index and inside bounds 45 a[9] = 3; // OK, constant index and inside bounds 46 a[const_index(6)] = 3; // OK, constant index and inside bounds 47 } 48 49 void g() { 50 int a[10]; 51 for (int i = 0; i < 10; ++i) { 52 a[i] = i; 53 // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: do not use array subscript when the index is not an integer constant expression 54 // CHECK-FIXES: gsl::at(a, i) = i; 55 gsl::at(a, i) = i; // OK, gsl::at() instead of [] 56 } 57 58 a[-1] = 3; // flagged by clang-diagnostic-array-bounds 59 a[10] = 4; // flagged by clang-diagnostic-array-bounds 60 a[const_index(7)] = 3; // flagged by clang-diagnostic-array-bounds 61 62 a[0] = 3; // OK, constant index and inside bounds 63 a[1] = 3; // OK, constant index and inside bounds 64 a[9] = 3; // OK, constant index and inside bounds 65 a[const_index(6)] = 3; // OK, constant index and inside bounds 66 } 67 68 struct S { 69 int& operator[](int i); 70 }; 71 72 void customOperator() { 73 S s; 74 int i = 0; 75 s[i] = 3; // OK, custom operator 76 } 77 78 struct A { 79 // The compiler-generated copy constructor uses an ArraySubscriptExpr. Don't warn. 80 int x[3]; 81 }; 82 83 void use_A() { 84 // Force the compiler to generate a copy constructor. 85 A a; 86 A a2(a); 87 } 88