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 
const_index(int base)22 constexpr int const_index(int base) {
23   return base + 3;
24 }
25 
f(std::array<int,10> a,int pos)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; use gsl::at() instead [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; use gsl::at() instead
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 
g()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; use gsl::at() instead
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 
customOperator()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 
use_A()83 void use_A() {
84   // Force the compiler to generate a copy constructor.
85   A a;
86   A a2(a);
87 }
88